UNPKG

react-occult

Version:

Layered Information Visualization based on React and D3

148 lines (131 loc) 3.46 kB
import { hexbin } from 'd3-hexbin'; import { scaleLinear } from 'd3-scale'; import groupData from '../data'; const hexbinProjection = ({ bins, cellPx, binValue, binMax, customMark, frameXScale, frameYScale, size, data, xAccessor, yAccessor, sAccessor, showPoints }) => { let projectedAreas = []; const { groupedData, projectedPoints } = groupData({ data, xAccessor, yAccessor, sAccessor, showPoints }); const hexBinXScale = scaleLinear() .domain(frameXScale.domain()) .range([0, size[0]]); const hexBinYScale = scaleLinear() .domain(frameYScale.domain()) .range([0, size[1]]); const actualResolution = (cellPx && cellPx / 2) || ((bins > 1 ? 1 / bins : bins) * size[0]) / 2; const hexbinner = hexbin() .x(d => hexBinXScale(d._xyPoint.x)) .y(d => hexBinYScale(d._xyPoint.y)) .radius(actualResolution) .size(size); let hexMax; const allHexes = hexbinner.centers(); groupedData.forEach(hexbinData => { hexMax = 0; const hexes = hexbinner( hexbinData._xyCoordinates.map((d, i) => ({ _xyPoint: d, ...hexbinData._baseData[i] })) ); const centerHash = {}; hexes.forEach(d => { centerHash[`${parseInt(d.x)}-${parseInt(d.y)}`] = true; }); allHexes.forEach(hexCenter => { if (!centerHash[`${parseInt(hexCenter[0])}-${parseInt(hexCenter[1])}`]) { const newHex = []; newHex.x = hexCenter[0]; newHex.y = hexCenter[1]; hexes.push(newHex); } }); hexMax = Math.max(...hexes.map(d => binValue(d))); if (binMax) { binMax(hexMax); } //Option for blank hexe const hexBase = [ [0, -1], [0.866, -0.5], [0.866, 0.5], [0, 1], [-0.866, 0.5], [-0.866, -0.5] ]; const hexWidth = hexBinXScale.invert(actualResolution) - frameXScale.domain()[0]; const hexHeight = hexBinYScale.invert(actualResolution) - frameYScale.domain()[0]; const hexacoordinates = hexBase.map(d => [ d[0] * hexWidth, d[1] * hexHeight ]); const hexbinProjectedAreas = hexes.map(d => { const hexValue = binValue(d); const gx = d.x; const gy = d.y; d.x = hexBinXScale.invert(d.x); d.y = hexBinYScale.invert(d.y); const percent = hexValue / hexMax; return { customMark: customMark && ( <g transform={`translate(${gx},${size[1] - gy})`}> {customMark({ d: { ...d, binItems: d, percent, value: hexValue, radius: actualResolution, hexCoordinates: hexBase.map(d => [ d[0] * actualResolution, d[1] * actualResolution ]) }, baseMarkProps, margin, styleFn, classFn, renderFn, chartSize, adjustedSize: size })} </g> ), _xyCoordinates: hexacoordinates.map(p => [p[0] + d.x, p[1] + d.y]), value: hexValue, percent, data: d, parentSummary: hexbinData, centroid: true }; }); projectedAreas = [...projectedAreas, ...hexbinProjectedAreas]; }); return { projectedAreas, projectedPoints, projectedLines: [] }; }; export default hexbinProjection;