|
| 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); |
0 commit comments