From 9b472802f46c3425ee44bae8fb654ccf4e39c1fc Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Mon, 25 Jan 2021 12:02:11 -0800 Subject: [PATCH 1/5] deps(mock-data): d3-random@^2.2.2 for seeded random --- packages/visx-mock-data/package.json | 4 ++-- yarn.lock | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/visx-mock-data/package.json b/packages/visx-mock-data/package.json index 053756e80..0c136a6ae 100644 --- a/packages/visx-mock-data/package.json +++ b/packages/visx-mock-data/package.json @@ -31,7 +31,7 @@ "access": "public" }, "dependencies": { - "@types/d3-random": "^1.1.2", - "d3-random": "^1.0.3" + "@types/d3-random": "^2.2.0", + "d3-random": "^2.2.2" } } diff --git a/yarn.lock b/yarn.lock index 8e4f3a9f2..a722d2361 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3534,10 +3534,10 @@ resolved "https://registry.yarnpkg.com/@types/d3-path/-/d3-path-1.0.8.tgz#48e6945a8ff43ee0a1ce85c8cfa2337de85c7c79" integrity sha512-AZGHWslq/oApTAHu9+yH/Bnk63y9oFOMROtqPAtxl5uB6qm1x2lueWdVEjsjjV3Qc2+QfuzKIwIR5MvVBakfzA== -"@types/d3-random@^1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-1.1.2.tgz#6f77e8b7bb64ac393f92d33fe8f71038bc4f3cde" - integrity sha512-Jui+Zn28pQw/3EayPKaN4c/PqTvqNbIPjHkgIIFnxne1FdwNjfHtAIsZIBMKlquQNrrMjFzCrlF2gPs3xckqaA== +"@types/d3-random@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@types/d3-random/-/d3-random-2.2.0.tgz#fc44cabb966917459490b758f31f5359adeabe5b" + integrity sha512-Hjfj9m68NmYZzushzEG7etPvKH/nj9b9s9+qtkNG3/dbRBjQZQg1XS6nRuHJcCASTjxXlyXZnKu2gDxyQIIu9A== "@types/d3-scale-chromatic@^1.3.1": version "1.5.0" @@ -6222,10 +6222,10 @@ d3-path@1, d3-path@^1.0.5: resolved "https://registry.yarnpkg.com/d3-path/-/d3-path-2.0.0.tgz#55d86ac131a0548adae241eebfb56b4582dd09d8" integrity sha512-ZwZQxKhBnv9yHaiWd6ZU4x5BtCQ7pXszEV9CU6kRgwIQVQGLMv1oiL4M+MK/n79sYzsj+gcgpPQSctJUsLN7fA== -d3-random@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-1.1.2.tgz#2833be7c124360bf9e2d3fd4f33847cfe6cab291" - integrity sha512-6AK5BNpIFqP+cx/sreKzNjWbwZQCSUatxq+pPRmFIQaWuoD+NrbVWw7YWpHiXpCQ/NanKdtGDuB+VQcZDaEmYQ== +d3-random@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/d3-random/-/d3-random-2.2.2.tgz#5eebd209ef4e45a2b362b019c1fb21c2c98cbb6e" + integrity sha512-0D9P8TRj6qDAtHhRQn6EfdOtHMfsUWanl3yb/84C4DqpZ+VsgfI5iTVRNRbELCfNvRfpMr8OrqqUTQ6ANGCijw== d3-scale-chromatic@^1.3.3: version "1.5.0" From 68b0fedaac02fd4ccaf30901790d175babeb4448 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Mon, 25 Jan 2021 12:03:01 -0800 Subject: [PATCH 2/5] new(mock-data): add getSeededRandom, support seeds in all generators --- .../src/generators/genDateValue.ts | 16 +++++++++++++--- .../src/generators/genRandomNormalPoints.ts | 16 +++++++++++----- .../visx-mock-data/src/generators/genStats.ts | 13 ++++++++++--- .../src/generators/getSeededRandom.ts | 9 +++++++++ packages/visx-mock-data/src/index.ts | 1 + 5 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 packages/visx-mock-data/src/generators/getSeededRandom.ts diff --git a/packages/visx-mock-data/src/generators/genDateValue.ts b/packages/visx-mock-data/src/generators/genDateValue.ts index 151d4791c..b3e9ce446 100644 --- a/packages/visx-mock-data/src/generators/genDateValue.ts +++ b/packages/visx-mock-data/src/generators/genDateValue.ts @@ -1,14 +1,24 @@ +import getSeededRandom from './getSeededRandom'; + export interface DateValue { date: Date; value: number; } -export default function genDateValue(length: number): DateValue[] { +export default function genDateValue( + length: number, + /** Optional random seed in the interval [0, 1). */ + seed?: number, + /** Optional start time in ms UTC. */ + startTimeMs?: number, +): DateValue[] { + const random = seed == null ? Math.random : getSeededRandom(seed); + const startDateMs = startTimeMs == null ? Date.now() : new Date(startTimeMs).valueOf(); return new Array(length).fill(1).map((_, idx: number) => { return { - date: new Date(Date.now() - idx * 3600000), + date: new Date(startDateMs - idx * 3600000), // eslint-disable-next-line no-bitwise - value: Math.max(250, (Math.random() * 3000) | 0), + value: (random() * 3000) | 0, }; }); } diff --git a/packages/visx-mock-data/src/generators/genRandomNormalPoints.ts b/packages/visx-mock-data/src/generators/genRandomNormalPoints.ts index e061a1d2b..847f5778f 100644 --- a/packages/visx-mock-data/src/generators/genRandomNormalPoints.ts +++ b/packages/visx-mock-data/src/generators/genRandomNormalPoints.ts @@ -1,9 +1,9 @@ import { randomNormal } from 'd3-random'; +import getSeededRandom from './getSeededRandom'; export type PointConfig = [number, number, number]; export type PointsRange = [number, number, number]; -const random = randomNormal(0, 0.2); const sqrt3: number = Math.sqrt(3); function range(length: number): number[] { @@ -13,16 +13,22 @@ function range(length: number): number[] { export function genPointsRange( length: number, [offsetX, offsetY, index]: PointConfig, + random: () => number = randomNormal(0, 0.2), ): PointsRange[] { return range(length).map(() => { return [random() + offsetX, random() + offsetY, index]; }); } -export default function genPoints(count: number = 300): PointsRange[] { +export default function genPoints( + count: number = 300, + /** Optional random seed in the interval [0, 1). */ + seed: number | undefined = undefined, +): PointsRange[] { + const random = seed == null ? undefined : randomNormal.source(getSeededRandom(seed))(0, 0.2); return [ - ...genPointsRange(count, [sqrt3, 1, 0]), - ...genPointsRange(count, [-sqrt3, 1, 1]), - ...genPointsRange(count, [0, -1, 2]), + ...genPointsRange(count, [sqrt3, 1, 0], random), + ...genPointsRange(count, [-sqrt3, 1, 1], random), + ...genPointsRange(count, [0, -1, 2], random), ]; } diff --git a/packages/visx-mock-data/src/generators/genStats.ts b/packages/visx-mock-data/src/generators/genStats.ts index 32f4ce9cd..08691bf6c 100644 --- a/packages/visx-mock-data/src/generators/genStats.ts +++ b/packages/visx-mock-data/src/generators/genStats.ts @@ -20,11 +20,18 @@ export interface Stats { binData: BinData[]; } -const random = randomNormal(4, 3); -const randomOffset = () => Math.random() * 10; +const defaultRandom = randomNormal(4, 3); +const defaultRandomOffset = () => Math.random() * 10; const sampleSize = 1000; -export default function genStats(number: number): Stats[] { +export default function genStats( + /** Number of stat distributions to generate. */ + number: number, + /** Function which generates a random number. */ + random: () => number = defaultRandom, + /** Function which generates an offset for each data point / invocation of random. */ + randomOffset: () => number = defaultRandomOffset, +): Stats[] { const data = []; for (let i = 0; i < number; i += 1) { diff --git a/packages/visx-mock-data/src/generators/getSeededRandom.ts b/packages/visx-mock-data/src/generators/getSeededRandom.ts new file mode 100644 index 000000000..1a6f538ad --- /dev/null +++ b/packages/visx-mock-data/src/generators/getSeededRandom.ts @@ -0,0 +1,9 @@ +import { randomLcg } from 'd3-random'; + +// returns a seeded random number generator +export default function getSeededRandom( + /** Seed in the interval [0, 1). */ + seed: number, +) { + return randomLcg(seed); +} diff --git a/packages/visx-mock-data/src/index.ts b/packages/visx-mock-data/src/index.ts index f7e951011..a230d36e0 100644 --- a/packages/visx-mock-data/src/index.ts +++ b/packages/visx-mock-data/src/index.ts @@ -1,5 +1,6 @@ export { default as genDateValue } from './generators/genDateValue'; export { default as genRandomNormalPoints } from './generators/genRandomNormalPoints'; +export { default as getSeededRandom } from './generators/getSeededRandom'; export { default as genBin } from './generators/genBin'; export { default as genBins } from './generators/genBins'; export { default as genPhyllotaxis } from './generators/genPhyllotaxis'; From 81a41ea36ad8587a777f17e3490883978abda8ad Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Mon, 25 Jan 2021 12:04:57 -0800 Subject: [PATCH 3/5] test(mock-data): add tests for seeded random across generators --- packages/visx-mock-data/test/genBin.test.ts | 30 +++++++++++++++--- packages/visx-mock-data/test/genBins.test.ts | 31 ++++++++++++++++--- .../visx-mock-data/test/genDateValue.test.ts | 15 ++++++--- .../test/genRandomNormalPoints.test.ts | 17 +++++++--- packages/visx-mock-data/test/genStats.test.ts | 12 +++++-- .../test/getSeededRandom.test.ts | 16 ++++++++++ 6 files changed, 99 insertions(+), 22 deletions(-) create mode 100644 packages/visx-mock-data/test/getSeededRandom.test.ts diff --git a/packages/visx-mock-data/test/genBin.test.ts b/packages/visx-mock-data/test/genBin.test.ts index 70d9c32ef..90bebab8c 100644 --- a/packages/visx-mock-data/test/genBin.test.ts +++ b/packages/visx-mock-data/test/genBin.test.ts @@ -1,25 +1,45 @@ -import { genBin } from '../src'; +import { genBin, getSeededRandom } from '../src'; describe('generators/genBin', () => { - test('it should be defined', () => { + it('should be defined', () => { expect(genBin).toBeDefined(); }); - test('it should have shape [{ bin, count }]', () => { + it('should have shape [{ bin, count }]', () => { const bin = genBin(1); expect(bin).toHaveLength(1); expect(bin[0].bin).toBeDefined(); expect(bin[0].count).toBeDefined(); }); - test('it should take optional bin function', () => { + it('should take optional bin function', () => { const bin = genBin(1, i => i); expect(bin[0].bin).toEqual(0); }); - test('it should take an optional count function', () => { + it('should take an optional count function', () => { const bin = genBin(1, undefined, i => i); expect(bin[0].count).toEqual(0); expect(bin[0].bin).toEqual(0); }); + + it('should support seeded randomness', () => { + const n = 3; + const seededRandom1 = getSeededRandom(0.5); + const seededRandom2 = getSeededRandom(0.5); + + expect( + genBin( + n, + i => i, + (i, number) => 25 * (number - i) * seededRandom1(), + ), + ).toEqual( + genBin( + n, + i => i, + (i, number) => 25 * (number - i) * seededRandom2(), + ), + ); + }); }); diff --git a/packages/visx-mock-data/test/genBins.test.ts b/packages/visx-mock-data/test/genBins.test.ts index 87c3584f9..7796b46be 100644 --- a/packages/visx-mock-data/test/genBins.test.ts +++ b/packages/visx-mock-data/test/genBins.test.ts @@ -1,11 +1,11 @@ -import { genBins } from '../src'; +import { genBins, getSeededRandom } from '../src'; describe('generators/genBins', () => { - test('it should be defined', () => { + it('should be defined', () => { expect(genBins).toBeDefined(); }); - test('it should have the shape of [{bin, bins: [{ bin, count }]}]', () => { + it('should have the shape of [{bin, bins: [{ bin, count }]}]', () => { const bins = genBins(1, 2); expect(bins[0].bin).toEqual(0); expect(bins).toHaveLength(1); @@ -13,13 +13,34 @@ describe('generators/genBins', () => { expect(bins[0].bins[1].bin).toEqual(150); }); - test('it should take an optional bin function parameter', () => { + it('should take an optional bin function parameter', () => { const bins = genBins(1, 1, i => i); expect(bins[0].bins[0].bin).toEqual(0); }); - test('it should take an optional count function parameter', () => { + it('should take an optional count function parameter', () => { const bins = genBins(1, 1, undefined, i => i); expect(bins[0].bins[0].count).toEqual(0); }); + + it('should support seeded randomness', () => { + const seededRandom1 = getSeededRandom(0.5); + const seededRandom2 = getSeededRandom(0.5); + + expect( + genBins( + 2, + 2, + i => i, + (i, number) => 25 * (number - i) * seededRandom1(), + ), + ).toEqual( + genBins( + 2, + 2, + i => i, + (i, number) => 25 * (number - i) * seededRandom2(), + ), + ); + }); }); diff --git a/packages/visx-mock-data/test/genDateValue.test.ts b/packages/visx-mock-data/test/genDateValue.test.ts index 410232e65..4fb11a1b2 100644 --- a/packages/visx-mock-data/test/genDateValue.test.ts +++ b/packages/visx-mock-data/test/genDateValue.test.ts @@ -1,24 +1,31 @@ import { genDateValue } from '../src'; describe('generators/genDateValue', () => { - test('it should be defined', () => { + it('should be defined', () => { expect(genDateValue).toBeDefined(); }); - test('it should be function', () => { + it('should be function', () => { expect(typeof genDateValue).toBe('function'); }); - test('it should return a array of n', () => { + it('should return a array of n', () => { const n = 3; const data = genDateValue(n); expect(data).toHaveLength(3); }); - test('it should return [{ date, value }]', () => { + it('should return [{ date, value }]', () => { const n = 1; const data = genDateValue(n); expect(data[0].date.constructor).toEqual(Date); expect(typeof data[0].value).toBe('number'); }); + + it('should should use a start date and seed if provided', () => { + const n = 3; + const seed = 0.5; + const startDate = new Date('2020-01-01').getUTCMilliseconds(); + expect(genDateValue(n, seed, startDate)).toEqual(genDateValue(n, seed, startDate)); + }); }); diff --git a/packages/visx-mock-data/test/genRandomNormalPoints.test.ts b/packages/visx-mock-data/test/genRandomNormalPoints.test.ts index 32c9fdef2..5e2481df7 100644 --- a/packages/visx-mock-data/test/genRandomNormalPoints.test.ts +++ b/packages/visx-mock-data/test/genRandomNormalPoints.test.ts @@ -1,26 +1,26 @@ import { genRandomNormalPoints } from '../src'; describe('generators/genRandomNormalPoints', () => { - test('it should be defined', () => { + it('should be defined', () => { expect(genRandomNormalPoints).toBeDefined(); }); - test('it should be function', () => { + it('should be function', () => { expect(typeof genRandomNormalPoints).toBe('function'); }); - test('it should default to 3x300 points', () => { + it('should default to 3x300 points', () => { const data = genRandomNormalPoints(); expect(data).toHaveLength(900); }); - test('it should return 3 * n', () => { + it('should return 3 * n', () => { const n = 3; const data = genRandomNormalPoints(n); expect(data).toHaveLength(9); }); - test('it should return points with x, y, index', () => { + it('should return points with x, y, index', () => { const n = 3; const data = genRandomNormalPoints(n); expect(data[0]).toHaveLength(3); @@ -31,4 +31,11 @@ describe('generators/genRandomNormalPoints', () => { expect(data[3][2]).toEqual(1); expect(data[6][2]).toEqual(2); }); + + it('should support seeded randomness', () => { + const n = 3; + const data1 = genRandomNormalPoints(n, 0.5); + const data2 = genRandomNormalPoints(n, 0.5); + expect(data1).toMatchObject(data2); + }); }); diff --git a/packages/visx-mock-data/test/genStats.test.ts b/packages/visx-mock-data/test/genStats.test.ts index e96135728..097d66ba9 100644 --- a/packages/visx-mock-data/test/genStats.test.ts +++ b/packages/visx-mock-data/test/genStats.test.ts @@ -1,15 +1,21 @@ -import { genStats } from '../src'; +import { genStats, getSeededRandom } from '../src'; describe('generators/genStats', () => { - test('it should be defined', () => { + it('should be defined', () => { expect(genStats).toBeDefined(); }); - test('it should have boxPlot and binData', () => { + it('should have boxPlot and binData', () => { const data = genStats(2); expect(data.length).toBeDefined(); expect(data).toHaveLength(2); expect(data[0].boxPlot).toBeDefined(); expect(data[0].binData).toBeDefined(); }); + + it('should support seeded randomness', () => { + const data1 = genStats(1, getSeededRandom(0.5), getSeededRandom(0.75)); + const data2 = genStats(1, getSeededRandom(0.5), getSeededRandom(0.75)); + expect(data1).toMatchObject(data2); + }); }); diff --git a/packages/visx-mock-data/test/getSeededRandom.test.ts b/packages/visx-mock-data/test/getSeededRandom.test.ts new file mode 100644 index 000000000..2682046ff --- /dev/null +++ b/packages/visx-mock-data/test/getSeededRandom.test.ts @@ -0,0 +1,16 @@ +import { getSeededRandom } from '../src'; + +describe('generators/getSeededRandom', () => { + it('should be defined', () => { + expect(getSeededRandom).toBeDefined(); + }); + + it('should return a random number generator that returns the same value given the same seed', () => { + const random1 = getSeededRandom(0.5)(); + const random2 = getSeededRandom(0.5)(); + const random3 = getSeededRandom(0.1)(); + + expect(random1).toEqual(random2); + expect(random1).not.toEqual(random3); + }); +}); From 92b40faca06eff20b79df57c35f16e799b06c177 Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Mon, 25 Jan 2021 12:49:29 -0800 Subject: [PATCH 4/5] new(mock-data): export getRandomNormal --- packages/visx-mock-data/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/visx-mock-data/src/index.ts b/packages/visx-mock-data/src/index.ts index a230d36e0..390d14c42 100644 --- a/packages/visx-mock-data/src/index.ts +++ b/packages/visx-mock-data/src/index.ts @@ -1,6 +1,7 @@ export { default as genDateValue } from './generators/genDateValue'; export { default as genRandomNormalPoints } from './generators/genRandomNormalPoints'; export { default as getSeededRandom } from './generators/getSeededRandom'; +export { randomNormal as getRandomNormal } from 'd3-random'; export { default as genBin } from './generators/genBin'; export { default as genBins } from './generators/genBins'; export { default as genPhyllotaxis } from './generators/genPhyllotaxis'; From d8ae983b5dd913754b4f99108ca4f5f31f15731d Mon Sep 17 00:00:00 2001 From: Chris Williams Date: Mon, 25 Jan 2021 12:50:00 -0800 Subject: [PATCH 5/5] internal(demo): use stable randomness for all demos --- .../src/sandboxes/visx-axis/Example.tsx | 4 +++- .../src/sandboxes/visx-curve/Example.tsx | 11 ++++++----- .../src/sandboxes/visx-dots/Example.tsx | 2 +- .../sandboxes/visx-drag-i/generateCircles.ts | 17 ++++++++++++----- .../src/sandboxes/visx-drag-i/package.json | 1 + .../src/sandboxes/visx-glyph/Example.tsx | 2 +- .../src/sandboxes/visx-heatmap/Example.tsx | 10 +++++++++- .../src/sandboxes/visx-responsive/Lines.tsx | 2 +- .../src/sandboxes/visx-stats/Example.tsx | 6 +++++- .../sandboxes/visx-streamgraph/generateData.ts | 10 +++++++--- .../src/sandboxes/visx-streamgraph/package.json | 3 ++- .../src/sandboxes/visx-voronoi/Example.tsx | 11 ++++++++--- .../src/sandboxes/visx-voronoi/package.json | 1 + .../src/sandboxes/visx-zoom-i/Example.tsx | 4 ++-- 14 files changed, 59 insertions(+), 25 deletions(-) diff --git a/packages/visx-demo/src/sandboxes/visx-axis/Example.tsx b/packages/visx-demo/src/sandboxes/visx-axis/Example.tsx index 6c514893a..81fca7cf3 100644 --- a/packages/visx-demo/src/sandboxes/visx-axis/Example.tsx +++ b/packages/visx-demo/src/sandboxes/visx-axis/Example.tsx @@ -4,6 +4,7 @@ import { curveMonotoneX } from '@visx/curve'; import { scaleUtc, scaleLinear, scaleLog, scaleBand, ScaleInput, coerceNumber } from '@visx/scale'; import { Orientation, SharedAxisProps, AxisScale } from '@visx/axis'; import { AnimatedAxis, AnimatedGridRows, AnimatedGridColumns } from '@visx/react-spring'; +import { getSeededRandom } from '@visx/mock-data'; import { LinearGradient } from '@visx/gradient'; import { timeFormat } from 'd3-time-format'; @@ -12,6 +13,7 @@ const axisColor = '#fff'; const tickLabelColor = '#fff'; export const labelColor = '#340098'; const gridColor = '#6e0fca'; +const seededRandom = getSeededRandom(0.5); const margin = { top: 40, right: 150, @@ -167,7 +169,7 @@ export default function Example({ ('bandwidth' in scale && typeof scale!.bandwidth !== 'undefined' ? scale.bandwidth!() / 2 : 0), - yScale(10 + Math.random() * 90), + yScale(10 + seededRandom() * 90), ])} yScale={yScale} curve={curveMonotoneX} diff --git a/packages/visx-demo/src/sandboxes/visx-curve/Example.tsx b/packages/visx-demo/src/sandboxes/visx-curve/Example.tsx index ae0b11faf..bbe2aaeb0 100644 --- a/packages/visx-demo/src/sandboxes/visx-curve/Example.tsx +++ b/packages/visx-demo/src/sandboxes/visx-curve/Example.tsx @@ -11,11 +11,12 @@ type CurveType = keyof typeof allCurves; const curveTypes = Object.keys(allCurves); const lineCount = 5; -const series = new Array(lineCount) - .fill(null) - .map(_ => - generateDateValue(25).sort((a: DateValue, b: DateValue) => a.date.getTime() - b.date.getTime()), - ); +const series = new Array(lineCount).fill(null).map((_, i) => + // vary each series value deterministically + generateDateValue(25, /* seed= */ i / 72).sort( + (a: DateValue, b: DateValue) => a.date.getTime() - b.date.getTime(), + ), +); const allData = series.reduce((rec, d) => rec.concat(d), []); // data accessors diff --git a/packages/visx-demo/src/sandboxes/visx-dots/Example.tsx b/packages/visx-demo/src/sandboxes/visx-dots/Example.tsx index c75fbdbb7..b412fdfee 100644 --- a/packages/visx-demo/src/sandboxes/visx-dots/Example.tsx +++ b/packages/visx-demo/src/sandboxes/visx-dots/Example.tsx @@ -11,7 +11,7 @@ import { WithTooltipProvidedProps } from '@visx/tooltip/lib/enhancers/withToolti import { voronoi, VoronoiPolygon } from '@visx/voronoi'; import { localPoint } from '@visx/event'; -const points: PointsRange[] = genRandomNormalPoints(600).filter((d, i) => i < 600); +const points: PointsRange[] = genRandomNormalPoints(600, /* seed= */ 0.5).filter((_, i) => i < 600); const x = (d: PointsRange) => d[0]; const y = (d: PointsRange) => d[1]; diff --git a/packages/visx-demo/src/sandboxes/visx-drag-i/generateCircles.ts b/packages/visx-demo/src/sandboxes/visx-drag-i/generateCircles.ts index d33452d89..6dd37836d 100644 --- a/packages/visx-demo/src/sandboxes/visx-drag-i/generateCircles.ts +++ b/packages/visx-demo/src/sandboxes/visx-drag-i/generateCircles.ts @@ -1,3 +1,5 @@ +import { getSeededRandom } from '@visx/mock-data'; + export interface Circle { id: string; radius: number; @@ -5,15 +7,20 @@ export interface Circle { y: number; } -const generateCircles = ({ width, height }: { width: number; height: number }) => - new Array(width < 360 ? 40 : 185).fill(1).map((d, i) => { - const radius = 25 - Math.random() * 20; +const generateCircles = ({ width, height }: { width: number; height: number }) => { + const radiusRandom = getSeededRandom(0.2); + const xRandom = getSeededRandom(0.3); + const yRandom = getSeededRandom(0.4); + + return new Array(width < 360 ? 40 : 185).fill(1).map((d, i) => { + const radius = 25 - radiusRandom() * 20; return { id: `${i}`, radius, - x: Math.round(Math.random() * (width - radius * 2) + radius), - y: Math.round(Math.random() * (height - radius * 2) + radius), + x: Math.round(xRandom() * (width - radius * 2) + radius), + y: Math.round(yRandom() * (height - radius * 2) + radius), }; }); +}; export default generateCircles; diff --git a/packages/visx-demo/src/sandboxes/visx-drag-i/package.json b/packages/visx-demo/src/sandboxes/visx-drag-i/package.json index c253a2630..fd4e951e4 100644 --- a/packages/visx-demo/src/sandboxes/visx-drag-i/package.json +++ b/packages/visx-demo/src/sandboxes/visx-drag-i/package.json @@ -9,6 +9,7 @@ "@types/react-dom": "^16", "@visx/drag": "latest", "@visx/gradient": "latest", + "@visx/mock-data": "latest", "@visx/responsive": "latest", "@visx/scale": "latest", "react": "^16", diff --git a/packages/visx-demo/src/sandboxes/visx-glyph/Example.tsx b/packages/visx-demo/src/sandboxes/visx-glyph/Example.tsx index 84059b417..f77eadaa1 100644 --- a/packages/visx-demo/src/sandboxes/visx-glyph/Example.tsx +++ b/packages/visx-demo/src/sandboxes/visx-glyph/Example.tsx @@ -42,7 +42,7 @@ const Glyphs = [ ), ]; -const data: DateValue[] = genDateValue(Glyphs.length * 2); +const data: DateValue[] = genDateValue(Glyphs.length * 2, 0.91); // accessors const date = (d: DateValue) => d.date.valueOf(); diff --git a/packages/visx-demo/src/sandboxes/visx-heatmap/Example.tsx b/packages/visx-demo/src/sandboxes/visx-heatmap/Example.tsx index 7c802ed4a..42097d8a1 100644 --- a/packages/visx-demo/src/sandboxes/visx-heatmap/Example.tsx +++ b/packages/visx-demo/src/sandboxes/visx-heatmap/Example.tsx @@ -3,6 +3,7 @@ import { Group } from '@visx/group'; import genBins, { Bin, Bins } from '@visx/mock-data/lib/generators/genBins'; import { scaleLinear } from '@visx/scale'; import { HeatmapCircle, HeatmapRect } from '@visx/heatmap'; +import { getSeededRandom } from '@visx/mock-data'; const hot1 = '#77312f'; const hot2 = '#f33d15'; @@ -10,7 +11,14 @@ const cool1 = '#122549'; const cool2 = '#b4fbde'; export const background = '#28272c'; -const binData = genBins(/* length = */ 16, /* height = */ 16); +const seededRandom = getSeededRandom(0.41); + +const binData = genBins( + /* length = */ 16, + /* height = */ 16, + /** binFunc */ idx => 150 * idx, + /** countFunc */ (i, number) => 25 * (number - i) * seededRandom(), +); function max(data: Datum[], value: (d: Datum) => number): number { return Math.max(...data.map(value)); diff --git a/packages/visx-demo/src/sandboxes/visx-responsive/Lines.tsx b/packages/visx-demo/src/sandboxes/visx-responsive/Lines.tsx index 24cf8457c..8e8a860af 100644 --- a/packages/visx-demo/src/sandboxes/visx-responsive/Lines.tsx +++ b/packages/visx-demo/src/sandboxes/visx-responsive/Lines.tsx @@ -6,7 +6,7 @@ import { scaleTime, scaleLinear } from '@visx/scale'; import { extent, max } from 'd3-array'; const lineCount = 12; -const series = new Array(lineCount).fill(null).map(_ => generateDateValue(25)); +const series = new Array(lineCount).fill(null).map((_, i) => generateDateValue(25, i / 47)); const allData = series.reduce((rec, d) => rec.concat(d), []); // data accessors diff --git a/packages/visx-demo/src/sandboxes/visx-stats/Example.tsx b/packages/visx-demo/src/sandboxes/visx-stats/Example.tsx index 412b273ed..8b234f7cb 100644 --- a/packages/visx-demo/src/sandboxes/visx-stats/Example.tsx +++ b/packages/visx-demo/src/sandboxes/visx-stats/Example.tsx @@ -4,11 +4,15 @@ import { ViolinPlot, BoxPlot } from '@visx/stats'; import { LinearGradient } from '@visx/gradient'; import { scaleBand, scaleLinear } from '@visx/scale'; import genStats, { Stats } from '@visx/mock-data/lib/generators/genStats'; +import { getSeededRandom, getRandomNormal } from '@visx/mock-data'; import { withTooltip, Tooltip, defaultStyles as defaultTooltipStyles } from '@visx/tooltip'; import { WithTooltipProvidedProps } from '@visx/tooltip/lib/enhancers/withTooltip'; import { PatternLines } from '@visx/pattern'; -const data: Stats[] = genStats(5); +// seeded randomness +const seededRandom = getSeededRandom(0.1); +const randomNormal = getRandomNormal.source(getSeededRandom(0.789))(4, 3); +const data: Stats[] = genStats(5, randomNormal, () => 10 * seededRandom()); // accessors const x = (d: Stats) => d.boxPlot.x; diff --git a/packages/visx-demo/src/sandboxes/visx-streamgraph/generateData.ts b/packages/visx-demo/src/sandboxes/visx-streamgraph/generateData.ts index e100d5965..348b4613a 100644 --- a/packages/visx-demo/src/sandboxes/visx-streamgraph/generateData.ts +++ b/packages/visx-demo/src/sandboxes/visx-streamgraph/generateData.ts @@ -1,7 +1,11 @@ +import { getSeededRandom } from '@visx/mock-data'; + +const random = getSeededRandom(0.65); + const getPoints = (array: number[], pointCount: number) => { - const x = 1 / (0.1 + Math.random()); - const y = 2 * Math.random() - 0.5; - const z = 10 / (0.1 + Math.random()); + const x = 1 / (0.1 + random()); + const y = 2 * random() - 0.5; + const z = 10 / (0.1 + random()); for (let i = 0; i < pointCount; i += 1) { const w = (i / pointCount - y) * z; array[i] += x * Math.exp(-w * w); diff --git a/packages/visx-demo/src/sandboxes/visx-streamgraph/package.json b/packages/visx-demo/src/sandboxes/visx-streamgraph/package.json index 9cb7d9915..63d0db0b4 100644 --- a/packages/visx-demo/src/sandboxes/visx-streamgraph/package.json +++ b/packages/visx-demo/src/sandboxes/visx-streamgraph/package.json @@ -8,8 +8,9 @@ "@types/d3-array": "^2.0.0", "@types/react": "^16", "@types/react-dom": "^16", - "@visx/responsive": "latest", + "@visx/mock-data": "latest", "@visx/pattern": "latest", + "@visx/responsive": "latest", "@visx/scale": "latest", "@visx/shape": "latest", "d3-array": "^2.4.0", diff --git a/packages/visx-demo/src/sandboxes/visx-voronoi/Example.tsx b/packages/visx-demo/src/sandboxes/visx-voronoi/Example.tsx index ab52dbd90..2dcf29aa5 100644 --- a/packages/visx-demo/src/sandboxes/visx-voronoi/Example.tsx +++ b/packages/visx-demo/src/sandboxes/visx-voronoi/Example.tsx @@ -4,6 +4,7 @@ import { GradientOrangeRed, GradientPinkRed } from '@visx/gradient'; import { RectClipPath } from '@visx/clip-path'; import { voronoi, VoronoiPolygon } from '@visx/voronoi'; import { localPoint } from '@visx/event'; +import { getSeededRandom } from '@visx/mock-data'; type Datum = { x: number; @@ -11,9 +12,11 @@ type Datum = { id: string; }; +const seededRandom = getSeededRandom(0.88); + const data: Datum[] = new Array(150).fill(null).map(() => ({ - x: Math.random(), - y: Math.random(), + x: seededRandom(), + y: seededRandom(), id: Math.random() .toString(36) .slice(2), @@ -34,7 +37,7 @@ export type VoronoiProps = { margin?: { top: number; right: number; bottom: number; left: number }; }; -export default ({ width, height, margin = defaultMargin }: VoronoiProps) => { +const Example = ({ width, height, margin = defaultMargin }: VoronoiProps) => { const innerWidth = width - margin.left - margin.right; const innerHeight = height - margin.top - margin.bottom; @@ -121,3 +124,5 @@ export default ({ width, height, margin = defaultMargin }: VoronoiProps) => { ); }; + +export default Example; diff --git a/packages/visx-demo/src/sandboxes/visx-voronoi/package.json b/packages/visx-demo/src/sandboxes/visx-voronoi/package.json index 5d150f66a..05baae42c 100644 --- a/packages/visx-demo/src/sandboxes/visx-voronoi/package.json +++ b/packages/visx-demo/src/sandboxes/visx-voronoi/package.json @@ -11,6 +11,7 @@ "@visx/event": "latest", "@visx/gradient": "latest", "@visx/group": "latest", + "@visx/mock-data": "latest", "@visx/responsive": "latest", "@visx/voronoi": "latest", "react": "^16.8", diff --git a/packages/visx-demo/src/sandboxes/visx-zoom-i/Example.tsx b/packages/visx-demo/src/sandboxes/visx-zoom-i/Example.tsx index 4d656c352..edbfe9047 100644 --- a/packages/visx-demo/src/sandboxes/visx-zoom-i/Example.tsx +++ b/packages/visx-demo/src/sandboxes/visx-zoom-i/Example.tsx @@ -33,8 +33,8 @@ export type ZoomIProps = { export default function ZoomI({ width, height }: ZoomIProps) { const [showMiniMap, setShowMiniMap] = useState(true); - const genenerator: GenPhyllotaxisFunction = genPhyllotaxis({ radius: 10, width, height }); - const phyllotaxis: PhyllotaxisPoint[] = points.map((d, i) => genenerator(i)); + const generator: GenPhyllotaxisFunction = genPhyllotaxis({ radius: 10, width, height }); + const phyllotaxis: PhyllotaxisPoint[] = points.map((d, i) => generator(i)); return ( <>