Skip to content

Commit

Permalink
Merge b5925a8 into dfaa690
Browse files Browse the repository at this point in the history
  • Loading branch information
williaster committed Jan 10, 2020
2 parents dfaa690 + b5925a8 commit 2b06283
Show file tree
Hide file tree
Showing 10 changed files with 517 additions and 493 deletions.
1 change: 1 addition & 0 deletions packages/vx-demo/package.json
Expand Up @@ -17,6 +17,7 @@
"license": "MIT",
"dependencies": {
"@types/d3-array": "^2.0.0",
"@types/d3-scale-chromatic": "^1.3.1",
"@types/d3-time-format": "2.1.0",
"@types/nprogress": "^0.2.0",
"@types/prismjs": "^1.16.0",
Expand Down
8 changes: 5 additions & 3 deletions packages/vx-demo/src/components/gallery.js
Expand Up @@ -23,7 +23,7 @@ import Heatmap from './tiles/heatmap';
import LineRadial from './tiles/lineradial';
import Pies from './tiles/pie';
import Trees from './tiles/Trees.tsx';
import Cluster from './tiles/dendrogram';
import Dendrograms from './tiles/Dendrograms.tsx';
import Voronoi from './tiles/Voronoi.tsx';
import Legends from './tiles/legends';
import StatsPlot from './tiles/Statsplot.tsx';
Expand All @@ -41,7 +41,7 @@ import LinkTypes from './tiles/LinkTypes.tsx';
import Threshold from './tiles/threshold';
import Chord from './tiles/Chord.tsx';
import Polygons from './tiles/Polygons.tsx';
import ZoomI from './tiles/zoom-i';
import ZoomI from './tiles/Zoom-i.tsx';
import BrushChart from './tiles/brush';

const items = [
Expand Down Expand Up @@ -430,7 +430,9 @@ export default function() {
<div className="gallery-item" style={{ background: '#306c90' }}>
<div className="image">
<ParentSize>
{({ width, height }) => <Cluster width={width} height={height + detailsHeight} />}
{({ width, height }) => (
<Dendrograms width={width} height={height + detailsHeight} />
)}
</ParentSize>
</div>
<div className="details" style={{ color: '#5dc26f' }}>
Expand Down
@@ -1,9 +1,10 @@
import React from 'react';
import { Group } from '@vx/group';
import { Cluster } from '@vx/hierarchy';
import { Cluster, hierarchy } from '@vx/hierarchy';
import { HierarchyPointNode, HierarchyPointLink } from '@vx/hierarchy/lib/types';
import { LinkVertical } from '@vx/shape';
import { hierarchy } from 'd3-hierarchy';
import { LinearGradient } from '@vx/gradient';
import { ShowProvidedProps } from '../../types';

const citrus = '#ddf163';
const white = '#ffffff';
Expand All @@ -12,7 +13,12 @@ const aqua = '#37ac8c';
const merlinsbeard = '#f7f7f3';
const bg = '#306c90';

const clusterData = {
interface NodeShape {
name: string;
children?: NodeShape[];
}

const clusterData: NodeShape = {
name: '$',
children: [
{
Expand Down Expand Up @@ -45,7 +51,7 @@ const clusterData = {
],
};

function Node({ node }) {
function Node({ node }: { node: HierarchyPointNode<NodeShape> }) {
const isRoot = node.depth === 0;
const isParent = !!node.children;

Expand Down Expand Up @@ -77,7 +83,7 @@ function Node({ node }) {
);
}

function RootNode({ node }) {
function RootNode({ node }: { node: HierarchyPointNode<NodeShape> }) {
const width = 40;
const height = 20;
const centerX = -width / 2;
Expand Down Expand Up @@ -109,39 +115,35 @@ export default ({
right: 0,
bottom: 110,
},
}) => {
}: ShowProvidedProps) => {
if (width < 10) return null;

const data = hierarchy(clusterData);
const data = hierarchy<NodeShape>(clusterData);
const xMax = width - margin.left - margin.right;
const yMax = height - margin.top - margin.bottom;

return (
<svg width={width} height={height}>
<LinearGradient id="top" from={green} to={aqua} />
<rect width={width} height={height} rx={14} fill={bg} />
<Cluster root={data} size={[xMax, yMax]}>
{cluster => {
return (
<Group top={margin.top} left={margin.left}>
{cluster.links().map((link, i) => {
return (
<LinkVertical
key={`cluster-link-${i}`}
data={link}
stroke={merlinsbeard}
strokeWidth="1"
strokeOpacity={0.2}
fill="none"
/>
);
})}
{cluster.descendants().map((node, i) => {
return <Node key={`cluster-node-${i}`} node={node} />;
})}
</Group>
);
}}
<Cluster<NodeShape> root={data} size={[xMax, yMax]}>
{cluster => (
<Group top={margin.top} left={margin.left}>
{cluster.links().map((link, i) => (
<LinkVertical<HierarchyPointLink<NodeShape>, HierarchyPointNode<NodeShape>>
key={`cluster-link-${i}`}
data={link}
stroke={merlinsbeard}
strokeWidth="1"
strokeOpacity={0.2}
fill="none"
/>
))}
{cluster.descendants().map((node, i) => (
<Node key={`cluster-node-${i}`} node={node} />
))}
</Group>
)}
</Cluster>
</svg>
);
Expand Down
197 changes: 197 additions & 0 deletions packages/vx-demo/src/components/tiles/Zoom-i.tsx
@@ -0,0 +1,197 @@
/* eslint-disable react/jsx-handler-names */
import React, { useState } from 'react';
import { Zoom } from '@vx/zoom';
import { localPoint } from '@vx/event';
import { RectClipPath } from '@vx/clip-path';
import genPhyllotaxis, {
GenPhyllotaxisFunction,
PhyllotaxisPoint,
} from '@vx/mock-data/lib/generators/genPhyllotaxis';
import { scaleLinear } from '@vx/scale';
import { interpolateRainbow } from 'd3-scale-chromatic';
import { ShowProvidedProps } from '../../types';

const bg = '#0a0a0a';
const points = [...new Array(1000)];

const colorScale = scaleLinear<number>({ range: [0, 1], domain: [0, 1000] });
const sizeScale = scaleLinear<number>({ domain: [0, 600], range: [0.5, 8] });

const initialTransform = {
scaleX: 1.27,
scaleY: 1.27,
translateX: -211.62,
translateY: 162.59,
skewX: 0,
skewY: 0,
};

export default function ZoomI({ width, height }: ShowProvidedProps) {
const [showMiniMap, setShowMiniMap] = useState<boolean>(true);

const gen: GenPhyllotaxisFunction = genPhyllotaxis({ radius: 10, width, height });
const phyllotaxis: PhyllotaxisPoint[] = points.map((d, i) => gen(i));

return (
<>
<Zoom
width={width}
height={height}
scaleXMin={1 / 2}
scaleXMax={4}
scaleYMin={1 / 2}
scaleYMax={4}
transformMatrix={initialTransform}
>
{zoom => (
<div style={{ position: 'relative' }}>
<svg
width={width}
height={height}
style={{ cursor: zoom.isDragging ? 'grabbing' : 'grab' }}
>
<RectClipPath id="zoom-clip" width={width} height={height} />
<rect width={width} height={height} rx={14} fill={bg} />
<g transform={zoom.toString()}>
{phyllotaxis.map(({ x, y }, i) => (
<React.Fragment key={`dot-${i}`}>
<circle
cx={x}
cy={y}
r={i > 500 ? sizeScale(1000 - i) : sizeScale(i)}
fill={interpolateRainbow(colorScale(i))}
/>
</React.Fragment>
))}
</g>
<rect
width={width}
height={height}
rx={14}
fill="transparent"
onTouchStart={zoom.dragStart}
onTouchMove={zoom.dragMove}
onTouchEnd={zoom.dragEnd}
onMouseDown={zoom.dragStart}
onMouseMove={zoom.dragMove}
onMouseUp={zoom.dragEnd}
onMouseLeave={() => {
if (zoom.isDragging) zoom.dragEnd();
}}
onDoubleClick={event => {
const point = localPoint(event) || { x: 0, y: 0 };
zoom.scale({ scaleX: 1.1, scaleY: 1.1, point });
}}
/>
{showMiniMap && (
<g
clipPath="url(#zoom-clip)"
transform={`
scale(0.25)
translate(${width * 4 - width - 60}, ${height * 4 - height - 60})
`}
>
<rect width={width} height={height} fill="#1a1a1a" />
{phyllotaxis.map(({ x, y }, i) => (
<React.Fragment key={`dot-sm-${i}`}>
<circle
cx={x}
cy={y}
r={i > 500 ? sizeScale(1000 - i) : sizeScale(i)}
fill={interpolateRainbow(colorScale(i))}
/>
</React.Fragment>
))}
<rect
width={width}
height={height}
fill="white"
fillOpacity={0.2}
stroke="white"
strokeWidth={4}
transform={zoom.toStringInvert()}
/>
</g>
)}
</svg>
<div className="controls">
<button
className="btn btn-zoom"
onClick={() => zoom.scale({ scaleX: 1.2, scaleY: 1.2 })}
>
+
</button>
<button
className="btn btn-zoom btn-bottom"
onClick={() => zoom.scale({ scaleX: 0.8, scaleY: 0.8 })}
>
-
</button>
<button className="btn btn-lg" onClick={zoom.center}>
Center
</button>
<button className="btn btn-lg" onClick={zoom.reset}>
Reset
</button>
<button className="btn btn-lg" onClick={zoom.clear}>
Clear
</button>
</div>
<div className="mini-map">
<button className="btn btn-lg" onClick={() => setShowMiniMap(!showMiniMap)}>
{showMiniMap ? 'Hide' : 'Show'} Mini Map
</button>
</div>
</div>
)}
</Zoom>
<div className="description">
Based on Mike Bostock's{' '}
<a href="https://bl.ocks.org/mbostock/4e3925cdc804db257a86fdef3a032a45">Pan & Zoom III</a>
</div>
<style jsx>{`
.btn {
margin: 0;
text-align: center;
border: none;
background: #2f2f2f;
color: #888;
padding: 0 4px;
border-top: 1px solid #0a0a0a;
}
.btn-lg {
font-size: 12px;
line-height: 1;
padding: 4px;
}
.btn-zoom {
width: 26px;
font-size: 22px;
}
.btn-bottom {
margin-bottom: 1rem;
}
.description {
font-size: 12px;
margin-right: 0.25rem;
}
.controls {
position: absolute;
top: 15px;
right: 15px;
display: flex;
flex-direction: column;
align-items: flex-end;
}
.mini-map {
position: absolute;
bottom: 25px;
right: 15px;
display: flex;
flex-direction: column;
align-items: flex-end;
}
`}</style>
</>
);
}

0 comments on commit 2b06283

Please sign in to comment.