Skip to content

Commit

Permalink
Merge pull request #692 from hshoff/chris--sandbox-dots
Browse files Browse the repository at this point in the history
new(vx-demo): convert Dots to codesandbox
  • Loading branch information
williaster authored May 21, 2020
2 parents cd5769b + 9f29aa0 commit b8bf49b
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 129 deletions.
13 changes: 2 additions & 11 deletions packages/vx-demo/src/components/Gallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import Footer from './Footer';

import Bars from '../docs-v2/examples/vx-bars/Example';
import Curves from '../docs-v2/examples/vx-curve/Example';
import Dots from './tiles/Dots';
import Dots from '../docs-v2/examples/vx-dots/Example';
import Gradients from '../docs-v2/examples/vx-gradient/Example';
import Area, { background as areaBackground } from '../docs-v2/examples/vx-area/Example';
import StackedAreas, {
Expand Down Expand Up @@ -143,16 +143,7 @@ export default function Gallery() {
<div className="image">
<ParentSize>
{({ width, height }) => (
<Dots
width={width}
height={height + detailsHeight}
margin={{
top: 0,
left: 0,
right: 0,
bottom: 80,
}}
/>
<Dots showControls={false} width={width} height={height} />
)}
</ParentSize>
</div>
Expand Down
109 changes: 0 additions & 109 deletions packages/vx-demo/src/components/tiles/Dots.tsx

This file was deleted.

165 changes: 165 additions & 0 deletions packages/vx-demo/src/docs-v2/examples/vx-dots/Example.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import React, { useMemo, useState, useCallback, useRef } from 'react';
import { Group } from '@vx/group';
import { Circle } from '@vx/shape';
import { GradientPinkRed } from '@vx/gradient';
import { scaleLinear } from '@vx/scale';
import genRandomNormalPoints, {
PointsRange,
} from '@vx/mock-data/lib/generators/genRandomNormalPoints';
import { withTooltip, Tooltip } from '@vx/tooltip';
import { WithTooltipProvidedProps } from '@vx/tooltip/lib/enhancers/withTooltip';
import { voronoi, VoronoiPolygon } from '@vx/voronoi';
import { localPoint } from '@vx/event';

const points: PointsRange[] = genRandomNormalPoints(600).filter((d, i) => i < 600);

const x = (d: PointsRange) => d[0];
const y = (d: PointsRange) => d[1];

type Props = {
width: number;
height: number;
showControls?: boolean;
};

let tooltipTimeout: number;

export default withTooltip<Props, PointsRange>(
({
width,
height,
showControls = true,
hideTooltip,
showTooltip,
tooltipOpen,
tooltipData,
tooltipLeft,
tooltipTop,
}: Props & WithTooltipProvidedProps<PointsRange>) => {
const [showVoronoi, setShowVoronoi] = useState(showControls);
const svgRef = useRef<SVGSVGElement>(null);
const xScale = useMemo(
() =>
scaleLinear<number>({
domain: [1.3, 2.2],
range: [0, width],
clamp: true,
}),
[width],
);
const yScale = useMemo(
() =>
scaleLinear<number>({
domain: [0.75, 1.6],
range: [height, 0],
clamp: true,
}),
[height],
);
const voronoiLayout = useMemo(
() =>
voronoi<PointsRange>({
x: d => xScale(x(d)),
y: d => yScale(y(d)),
width,
height,
})(points),
[width, height, xScale, yScale],
);

// event handlers
const handleMouseMove = useCallback(
(event: React.MouseEvent | React.TouchEvent) => {
if (tooltipTimeout) clearTimeout(tooltipTimeout);
if (!svgRef.current) return;

// find the nearest polygon to the current mouse position
const point = localPoint(svgRef.current, event);
if (!point) return;
const neighborRadius = 100;
const closest = voronoiLayout.find(point.x, point.y, neighborRadius);
if (closest) {
showTooltip({
tooltipLeft: xScale(x(closest.data)),
tooltipTop: yScale(y(closest.data)),
tooltipData: closest.data,
});
}
},
[xScale, yScale, showTooltip, voronoiLayout],
);

const handleMouseLeave = useCallback(() => {
tooltipTimeout = window.setTimeout(() => {
hideTooltip();
}, 300);
}, [hideTooltip]);

return (
<div>
<svg width={width} height={height} ref={svgRef}>
<GradientPinkRed id="dots-pink" />
{/** capture all mouse events with a rect */}
<rect
width={width}
height={height}
rx={14}
fill="url(#dots-pink)"
onMouseMove={handleMouseMove}
onMouseLeave={handleMouseLeave}
onTouchMove={handleMouseMove}
onTouchEnd={handleMouseLeave}
/>
<Group pointerEvents="none">
{points.map((point, i) => (
<Circle
key={`point-${point[0]}-${i}`}
className="dot"
cx={xScale(x(point))}
cy={yScale(y(point))}
r={i % 3 === 0 ? 2 : 3}
fill={tooltipData === point ? 'white' : '#f6c431'}
/>
))}
{showVoronoi &&
voronoiLayout
.polygons()
.map((polygon, i) => (
<VoronoiPolygon
key={`polygon-${i}`}
polygon={polygon}
fill="white"
stroke="white"
strokeWidth={1}
strokeOpacity={0.2}
fillOpacity={tooltipData === polygon.data ? 0.5 : 0}
/>
))}
</Group>
</svg>
{tooltipOpen && tooltipData && tooltipLeft != null && tooltipTop != null && (
<Tooltip left={tooltipLeft + 10} top={tooltipTop + 10}>
<div>
<strong>x:</strong> {x(tooltipData)}
</div>
<div>
<strong>y:</strong> {y(tooltipData)}
</div>
</Tooltip>
)}
{showControls && (
<div>
<label style={{ fontSize: 12 }}>
<input
type="checkbox"
checked={showVoronoi}
onChange={() => setShowVoronoi(!showVoronoi)}
/>
&nbsp;Show voronoi point map
</label>
</div>
)}
</div>
);
},
);
11 changes: 11 additions & 0 deletions packages/vx-demo/src/docs-v2/examples/vx-dots/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { render } from 'react-dom';
import ParentSize from '@vx/responsive/lib/components/ParentSize';

import Example from './Example';
import './sandbox-styles.css';

render(
<ParentSize>{({ width, height }) => <Example width={width} height={height} />}</ParentSize>,
document.getElementById('root'),
);
30 changes: 30 additions & 0 deletions packages/vx-demo/src/docs-v2/examples/vx-dots/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"name": "@vx/demo-dots",
"description": "Standalone vx scatterplot demo.",
"main": "index.tsx",
"dependencies": {
"@babel/runtime": "^7.8.4",
"@types/react": "^16",
"@types/react-dom": "^16",
"@vx/event": "latest",
"@vx/gradient": "latest",
"@vx/group": "latest",
"@vx/mock-data": "latest",
"@vx/responsive": "latest",
"@vx/scale": "latest",
"@vx/shape": "latest",
"@vx/tooltip": "latest",
"@vx/voronoi": "latest",
"react": "^16.8",
"react-dom": "^16.8",
"react-scripts-ts": "3.1.0",
"typescript": "^3"
},
"keywords": [
"visualization",
"d3",
"react",
"vx",
"visualization"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
html,
body,
#root {
height: 100%;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell,
'Open Sans', 'Helvetica Neue', sans-serif;
line-height: 2em;
}
16 changes: 7 additions & 9 deletions packages/vx-demo/src/pages/Dots.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import React from 'react';
import Show from '../components/Show';
import Dots from '../components/tiles/Dots';
import DotsSource from '!!raw-loader!../components/tiles/Dots';
import Dots from '../docs-v2/examples/vx-dots/Example';
import DotsSource from '!!raw-loader!../docs-v2/examples/vx-dots/Example';

export default () => {
return (
<Show component={Dots} title="Dots">
{DotsSource}
</Show>
);
};
export default () => (
<Show component={Dots} title="Dots" codeSandboxDirectoryName="vx-dots">
{DotsSource}
</Show>
);

0 comments on commit b8bf49b

Please sign in to comment.