Skip to content

Commit b774415

Browse files
committed
Axis example
1 parent 3c4617e commit b774415

7 files changed

Lines changed: 338 additions & 10 deletions

File tree

example/axes.js

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/* eslint no-console: 0 */
2+
3+
import { axisBottom, axisRight } from 'd3-axis';
4+
import { scaleLinear } from 'd3-scale';
5+
import { select } from 'd3-selection';
6+
7+
import createScatterplot from '../src';
8+
9+
const parentWrapper = document.querySelector('#parent-wrapper');
10+
const canvasWrapper = document.querySelector('#canvas-wrapper');
11+
const canvas = document.querySelector('#canvas');
12+
const numPointsEl = document.querySelector('#num-points');
13+
const numPointsValEl = document.querySelector('#num-points-value');
14+
const pointSizeEl = document.querySelector('#point-size');
15+
const pointSizeValEl = document.querySelector('#point-size-value');
16+
const opacityEl = document.querySelector('#opacity');
17+
const opacityValEl = document.querySelector('#opacity-value');
18+
const resetEl = document.querySelector('#reset');
19+
const exampleBg = document.querySelector('#example-axes');
20+
21+
exampleBg.setAttribute('class', 'active');
22+
exampleBg.removeAttribute('href');
23+
24+
const xDomain = [0, 42];
25+
const yDomain = [0, 4.2];
26+
const xScale = scaleLinear().domain(xDomain);
27+
const yScale = scaleLinear().domain(yDomain);
28+
const xAxis = axisBottom(xScale);
29+
const yAxis = axisRight(yScale);
30+
const axisContainer = select(parentWrapper).append('svg');
31+
const xAxisContainer = axisContainer.append('g');
32+
const yAxisContainer = axisContainer.append('g');
33+
const xAxisPadding = 20;
34+
const yAxisPadding = 40;
35+
36+
axisContainer.node().style.position = 'absolute';
37+
axisContainer.node().style.top = 0;
38+
axisContainer.node().style.left = 0;
39+
axisContainer.node().style.width = '100%';
40+
axisContainer.node().style.height = '100%';
41+
axisContainer.node().style.pointerEvents = 'none';
42+
43+
canvasWrapper.style.right = `${yAxisPadding}px`;
44+
canvasWrapper.style.bottom = `${xAxisPadding}px`;
45+
46+
let { width, height } = canvas.getBoundingClientRect();
47+
48+
xScale.range([0, width]);
49+
xAxisContainer.attr('transform', `translate(0, ${height})`).call(xAxis);
50+
51+
yScale.range([height, 0]);
52+
yAxisContainer.attr('transform', `translate(${width}, 0)`).call(yAxis);
53+
54+
let points = [];
55+
let numPoints = 100000;
56+
let pointSize = 2;
57+
let opacity = 0.5;
58+
let selection = [];
59+
60+
const selectHandler = ({ points: selectedPoints }) => {
61+
console.log('Selected:', selectedPoints);
62+
selection = selectedPoints;
63+
if (selection.length === 1) {
64+
const point = points[selection[0]];
65+
console.log(
66+
`X: ${point[0]}\nY: ${point[1]}\nCategory: ${point[2]}\nValue: ${point[3]}`
67+
);
68+
}
69+
};
70+
71+
const deselectHandler = () => {
72+
console.log('Deselected:', selection);
73+
selection = [];
74+
};
75+
76+
const scatterplot = createScatterplot({
77+
canvas,
78+
width,
79+
height,
80+
pointSize,
81+
xDomain,
82+
yDomain,
83+
});
84+
85+
console.log(`Scatterplot v${scatterplot.get('version')}`);
86+
87+
scatterplot.subscribe('select', selectHandler);
88+
scatterplot.subscribe('deselect', deselectHandler);
89+
scatterplot.subscribe('view', (event) => {
90+
xAxisContainer.call(xAxis.scale(xScale.domain(event.xDomainView)));
91+
yAxisContainer.call(yAxis.scale(yScale.domain(event.yDomainView)));
92+
});
93+
94+
xAxisContainer.call(xAxis.scale(xScale.domain(scatterplot.get('xDomainView'))));
95+
yAxisContainer.call(yAxis.scale(yScale.domain(scatterplot.get('yDomainView'))));
96+
97+
const resizeHandler = () => {
98+
({ width, height } = canvas.getBoundingClientRect());
99+
scatterplot.set({ width, height });
100+
};
101+
102+
window.addEventListener('resize', resizeHandler);
103+
104+
const generatePoints = (num) =>
105+
new Array(num).fill().map(() => [
106+
-1 + Math.random() * 2, // x
107+
-1 + Math.random() * 2, // y
108+
Math.round(Math.random() * 9), // category
109+
Math.random(), // value
110+
]);
111+
112+
const setNumPoint = (newNumPoints) => {
113+
numPoints = newNumPoints;
114+
numPointsEl.value = numPoints;
115+
numPointsValEl.innerHTML = numPoints;
116+
points = generatePoints(numPoints);
117+
118+
scatterplot.draw(points);
119+
};
120+
121+
const numPointsInputHandler = (event) => {
122+
numPointsValEl.innerHTML = `${+event.target
123+
.value} <em>release to redraw</em>`;
124+
};
125+
126+
numPointsEl.addEventListener('input', numPointsInputHandler);
127+
128+
const numPointsChangeHandler = (event) => setNumPoint(+event.target.value);
129+
130+
numPointsEl.addEventListener('change', numPointsChangeHandler);
131+
132+
const setPointSize = (newPointSize) => {
133+
pointSize = newPointSize;
134+
pointSizeEl.value = pointSize;
135+
pointSizeValEl.innerHTML = pointSize;
136+
scatterplot.set({ pointSize });
137+
};
138+
139+
const pointSizeInputHandler = (event) => setPointSize(+event.target.value);
140+
141+
pointSizeEl.addEventListener('input', pointSizeInputHandler);
142+
143+
const setOpacity = (newOpacity) => {
144+
opacity = newOpacity;
145+
opacityEl.value = opacity;
146+
opacityValEl.innerHTML = opacity;
147+
scatterplot.set({ opacity });
148+
};
149+
150+
const opacityInputHandler = (event) => setOpacity(+event.target.value);
151+
152+
opacityEl.addEventListener('input', opacityInputHandler);
153+
154+
const resetClickHandler = () => {
155+
scatterplot.reset();
156+
};
157+
158+
resetEl.addEventListener('click', resetClickHandler);
159+
160+
scatterplot.set({
161+
colorBy: 'category',
162+
pointColor: [
163+
'#d192b7',
164+
'#6fb2e4',
165+
'#eecb62',
166+
'#56bf92',
167+
'#dca237',
168+
'#3a84cc',
169+
'#c76526',
170+
],
171+
});
172+
173+
setPointSize(pointSize);
174+
setOpacity(opacity);
175+
setNumPoint(numPoints);

example/index.html

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,14 @@
271271
min-width: 2rem;
272272
}
273273

274+
#parent-wrapper {
275+
position: absolute;
276+
top: 0;
277+
right: 0;
278+
bottom: 0;
279+
left: 0;
280+
}
281+
274282
#canvas-wrapper {
275283
position: absolute;
276284
top: 0;
@@ -350,11 +358,16 @@ <h1 id="title">Regl Scatterplot</h1>
350358
>Background Image</a
351359
>
352360
</li>
361+
<li>
362+
<a id="example-axes" href="axes.html">Axes</a>
363+
</li>
353364
</ul>
354365
</aside>
355366
</header>
356-
<div id="canvas-wrapper">
357-
<canvas id="canvas"></canvas>
367+
<div id="parent-wrapper">
368+
<div id="canvas-wrapper">
369+
<canvas id="canvas"></canvas>
370+
</div>
358371
</div>
359372
</body>
360373
</html>

package-lock.json

Lines changed: 58 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,9 @@
5555
"babel-loader": "^8.1.0",
5656
"babel-plugin-lodash": "^3.3.4",
5757
"browser-env": "^3.3.0",
58+
"d3-axis": "^2.0.0",
59+
"d3-scale": "^3.2.3",
60+
"d3-selection": "^2.0.0",
5861
"eslint": "^6.8.0",
5962
"eslint-config-airbnb": "^18.1.0",
6063
"eslint-config-prettier": "^6.11.0",

src/constants.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ export const DEFAULT_VIEW = new Float32Array([
4343
0, 0, 1, 0,
4444
0, 0, 0, 1
4545
]);
46+
export const DEFAULT_X_DOMAIN = [0, 1];
47+
export const DEFAULT_Y_DOMAIN = [0, 1];
4648

4749
// Default misc
4850
export const DEFAULT_BACKGROUND_IMAGE = null;

0 commit comments

Comments
 (0)