diff --git a/packages/vx-demo/components/gallery.js b/packages/vx-demo/components/gallery.js
index 0ce36571c..69658489e 100644
--- a/packages/vx-demo/components/gallery.js
+++ b/packages/vx-demo/components/gallery.js
@@ -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',
@@ -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 (
@@ -652,7 +654,34 @@ export default class Gallery extends React.Component {
- {false &&
diff --git a/packages/vx-demo/components/tiles/radar.js b/packages/vx-demo/components/tiles/radar.js
new file mode 100644
index 000000000..5222d5083
--- /dev/null
+++ b/packages/vx-demo/components/tiles/radar.js
@@ -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 (
+
+ );
+};
diff --git a/packages/vx-demo/pages/radar.js b/packages/vx-demo/pages/radar.js
new file mode 100644
index 000000000..ba7edb15e
--- /dev/null
+++ b/packages/vx-demo/pages/radar.js
@@ -0,0 +1,135 @@
+import React from 'react';
+import Show from '../components/show';
+import Radar from '../components/tiles/radar';
+
+export default () => {
+ return (
+
+ {`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 (
+
+ );
+};
+`}
+
+ );
+};