Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[demo] Add Radar chart; fix #159 #180

Merged
merged 3 commits into from
Oct 26, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 30 additions & 1 deletion packages/vx-demo/components/gallery.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import Network from '../components/tiles/network';
import Streamgraph from '../components/tiles/streamgraph';
import Pack from '../components/tiles/pack';
import Treemap from '../components/tiles/treemap';
import Radar from '../components/tiles/radar';

const items = [
'#242424',
Expand Down Expand Up @@ -97,6 +98,7 @@ export default class Gallery extends React.Component {
const t20 = this.state.dimensions[19] || [8, 300];
const t21 = this.state.dimensions[20] || [8, 300];
const t22 = this.state.dimensions[21] || [8, 300];
const t23 = this.state.dimensions[22] || [8, 300];

return (
<div>
Expand Down Expand Up @@ -652,7 +654,34 @@ export default class Gallery extends React.Component {
</div>
</Link>
</Tilt>
{false && <div className="gallery-item placeholder" />}
<Tilt className="tilt" options={{ max: 8, scale: 1 }}>
<Link prefetch href="/radar">
<div
className="gallery-item"
ref={d => this.nodes.add(d)}
style={{
background: '#FAF7E9',
}}
>
<div className="image">
<Radar width={t23[0]} height={t23[1]} />
</div>
<div
className="details"
style={{
color: '#f5810c',
}}
>
<div className="title">Radar</div>
<div className="description">
<pre>{`<Radar />`}</pre>
</div>
</div>
</div>
</Link>
</Tilt>
{<div className="gallery-item placeholder" />}
{<div className="gallery-item placeholder" />}
</div>

<div>
Expand Down
124 changes: 124 additions & 0 deletions packages/vx-demo/components/tiles/radar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import React from 'react';
import { Group } from '@vx/group';
import { letterFrequency } from '@vx/mock-data';
import { scaleLinear } from '@vx/scale';
import { Point } from '@vx/point';
import { Line, LineRadial } from '@vx/shape';
import { max, min } from 'd3-array';


const ANG = 360;

const _data = letterFrequency.slice(2, 12);
const calcAxis = (length) => {
if (!length) return [];
else return new Array(length + 1)
.fill(0).map((v, i) => ({ angle: i * (ANG / length)}));
}

function calcPoints (length, radius) {
const step = Math.PI * 2 / length;
return new Array(length)
.fill(0).map((v, i) => {
return {
x: radius * Math.sin(i * step),
y: radius * Math.cos(i * step),
}
});
}

function calcCoordinates (data, scale, access) {
const step = Math.PI * 2 / data.length;
const points = new Array(data.length).fill({});
const pointStr = new Array(data.length + 1)
.fill('').reduce((res, v, i) => {
if (i > data.length) return res;
const x = scale(access(data[i - 1])) * Math.sin(i * step);
const y = scale(access(data[i - 1])) * Math.cos(i * step);
points[i - 1] = { x, y };
return res += `${x},${y} `;
});

points.str = pointStr;
return points;
}

export default ({
width,
height,
events = false,
margin = { top: 80, left: 80, right: 80, bottom: 80 },
levels = 5,
}) => {
if (width < 10) return null;

const webs = calcAxis(_data.length);
const radius = min([width, height]) / 2 - max(Object.values(margin));
const points = calcPoints(_data.length, radius);
const labelMargin = max(Object.values(margin)) - 20;

const x = d => d.letter;
const y = d => d.frequency;

const rScale = scaleLinear({
range: [0, Math.PI * 2],
domain: [ANG, 0],
});

const yScale = scaleLinear({
range: [0, radius],
domain: [0, max(_data, y)],
});

const polyPoints = calcCoordinates(_data, yScale, y);

return (
<svg width={width} height={height}>
<Group top={height / 2} left={width / 2}>
{[...new Array(levels)].map((v, i) => (
<LineRadial
data={webs}
key={i}
angle={d => rScale(d.angle)}
radius={(i + 1) * radius / levels}
fill="none"
stroke="#d9d9d9"
strokeWidth={2}
strokeOpacity={0.8}
strokeLinecap="round"
/>
))}
</Group>
<Group top={height / 2} left={width / 2}>
{[...new Array(_data.length)].map((v, i) => (
<Line key={i}
from={new Point({x:0, y:0})}
to={new Point({x:points[i].x, y:points[i].y})}
stroke="#d9d9d9"
/>
))}
</Group>
<Group top={height / 2} left={width / 2}>
<polygon
points={polyPoints.str}
fill="#ff9933"
fillOpacity="0.3"
stroke="#ff9933"
strokeWidth={1}
/>
</Group>
<Group top={height / 2} left={width / 2}>
{polyPoints.map((v, i) => (
<circle
key={i}
cx={v.x}
cy={v.y}
r={4}
fill="#f5810c"
className="dots"
/>
))}
</Group>
</svg>
);
};
135 changes: 135 additions & 0 deletions packages/vx-demo/pages/radar.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import React from 'react';
import Show from '../components/show';
import Radar from '../components/tiles/radar';

export default () => {
return (
<Show component={Radar} title="Radar">
{`import React from 'react';
import { Group } from '@vx/group';
import { letterFrequency } from '@vx/mock-data';
import { scaleLinear } from '@vx/scale';
import { Point } from '@vx/point';
import { Line, LineRadial } from '@vx/shape';
import { max, min } from 'd3-array';


const ANG = 360;

const _data = letterFrequency.slice(2, 12);
const calcAxis = (length) => {
if (!length) return [];
else return new Array(length + 1)
.fill(0).map((v, i) => ({ angle: i * (ANG / length)}));
}

function calcPoints (length, radius) {
const step = Math.PI * 2 / length;
return new Array(length)
.fill(0).map((v, i) => {
return {
x: radius * Math.sin(i * step),
y: radius * Math.cos(i * step),
}
});
}

function calcCoordinates (data, scale, access) {
const step = Math.PI * 2 / data.length;
const points = new Array(data.length).fill({});
const pointStr = new Array(data.length + 1)
.fill('').reduce((res, v, i) => {
if (i > data.length) return res;
const x = scale(access(data[i - 1])) * Math.sin(i * step);
const y = scale(access(data[i - 1])) * Math.cos(i * step);
points[i - 1] = { x, y };
return res += \`$\{x\},$\{y\} \`;
});

points.str = pointStr;
return points;
}

export default ({
width,
height,
events = false,
margin = { top: 80, left: 80, right: 80, bottom: 80 },
levels = 5,
}) => {
if (width < 10) return null;

const webs = calcAxis(_data.length);
const radius = min([width, height]) / 2 - max(Object.values(margin));
const points = calcPoints(_data.length, radius);
const labelMargin = max(Object.values(margin)) - 20;

const x = d => d.letter;
const y = d => d.frequency;

const rScale = scaleLinear({
range: [0, Math.PI * 2],
domain: [ANG, 0],
});

const yScale = scaleLinear({
range: [0, radius],
domain: [0, max(_data, y)],
});

const polyPoints = calcCoordinates(_data, yScale, y);

return (
<svg width={width} height={height}>
<Group top={height / 2} left={width / 2}>
{[...new Array(levels)].map((v, i) => (
<LineRadial
data={webs}
key={i}
angle={d => rScale(d.angle)}
radius={(i + 1) * radius / levels}
fill="none"
stroke="#d9d9d9"
strokeWidth={2}
strokeOpacity={0.8}
strokeLinecap="round"
/>
))}
</Group>
<Group top={height / 2} left={width / 2}>
{[...new Array(_data.length)].map((v, i) => (
<Line key={i}
from={new Point({x:0, y:0})}
to={new Point({x:points[i].x, y:points[i].y})}
stroke="#d9d9d9"
/>
))}
</Group>
<Group top={height / 2} left={width / 2}>
<polygon
points={polyPoints.str}
fill="#ff9933"
fillOpacity="0.3"
stroke="#ff9933"
strokeWidth={1}
/>
</Group>
<Group top={height / 2} left={width / 2}>
{polyPoints.map((v, i) => (
<circle
key={i}
cx={v.x}
cy={v.y}
r={4}
fill="#f5810c"
className="dots"
/>
))}
</Group>
</svg>
);
};
`}
</Show>
);
};