Skip to content

Commit

Permalink
fix: do not render/compute interaction layers unless active
Browse files Browse the repository at this point in the history
  • Loading branch information
tannerlinsley committed Feb 12, 2022
1 parent d1e38ef commit 28c8e78
Show file tree
Hide file tree
Showing 6 changed files with 83 additions and 25 deletions.
33 changes: 30 additions & 3 deletions examples/simple/src/components/StressTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ export default function StressTest() {
liveDataInterval,
showPoints,
memoizeSeries,
height,
showAxes,
},
setState,
] = React.useState({
Expand All @@ -25,6 +27,8 @@ export default function StressTest() {
liveDataInterval: 1000,
showPoints: true,
memoizeSeries: false,
height: 100,
showAxes: true,
});

const { data, randomizeData } = useDemoConfig({
Expand All @@ -41,8 +45,9 @@ export default function StressTest() {
>(
() => ({
getValue: (datum) => datum.primary as unknown as Date,
show: showAxes,
}),
[]
[showAxes]
);

const secondaryAxes = React.useMemo<
Expand All @@ -52,9 +57,10 @@ export default function StressTest() {
{
getValue: (datum) => datum.secondary,
showDatumElements: showPoints,
show: showAxes,
},
],
[showPoints]
[showAxes, showPoints]
);

React.useEffect(() => {
Expand Down Expand Up @@ -145,6 +151,17 @@ export default function StressTest() {
}}
/>
</label>
<label>
Show Axes:{" "}
<input
type="checkbox"
checked={showAxes}
onChange={(e) => {
e.persist();
setState((old) => ({ ...old, showAxes: !!e.target.checked }));
}}
/>
</label>
<br />
<label>
Memoize Series:{" "}
Expand Down Expand Up @@ -192,11 +209,21 @@ export default function StressTest() {
</select>
</label>
<br />
<label>
Chart Height
<input
type="number"
value={height}
onChange={(e) => {
setState((old) => ({ ...old, height: parseInt(e.target.value) }));
}}
/>
</label>
<button onClick={randomizeData}>Randomize Data</button>
<br />
<br />
{[...new Array(chartCount)].map((d, i) => (
<ResizableBox key={i} height={100}>
<ResizableBox key={i} height={height}>
<Chart
options={{
data,
Expand Down
6 changes: 3 additions & 3 deletions examples/simple/src/useLagRadar.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ function lagRadar(config = {}) {

const styles = document.createTextNode(`
.lagRadar {
pointer-events: none;
}
.lagRadar-sweep > * {
pointer-events: none;
}
.lagRadar-sweep > * {
shape-rendering: crispEdges;
}
.lagRadar-face {
Expand Down
21 changes: 20 additions & 1 deletion src/components/Chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,9 @@ function ChartInner<TDatum>({

const [axisDimensions] = axisDimensionsState

const isInteractingState = React.useState<boolean>(false)
const [isInteracting] = isInteractingState

const focusedDatumState = React.useState<Datum<TDatum> | null>(null)
const [focusedDatum] = focusedDatumState

Expand Down Expand Up @@ -464,11 +467,19 @@ function ChartInner<TDatum>({
}, [allDatums, gridDimensions, height, secondaryAxesOptions, series, width])

const [datumsByInteractionGroup, datumsByTooltipGroup] = React.useMemo(() => {
if (!isInteracting) {
return [new Map(), new Map()]
}

const datumsByInteractionGroup = new Map<any, Datum<TDatum>[]>()
const datumsByTooltipGroup = new Map<any, Datum<TDatum>[]>()

const allBarAndNotStacked = secondaryAxes.every(
d => d.elementType === 'bar' && !d.stacked
)

let getInteractionPrimary = (datum: Datum<TDatum>) => {
if (secondaryAxes.every(d => d.elementType === 'bar' && !d.stacked)) {
if (allBarAndNotStacked) {
const secondaryAxis = secondaryAxes.find(
d => d.id === datum.secondaryAxisId
)!
Expand Down Expand Up @@ -537,6 +548,7 @@ function ChartInner<TDatum>({

return [datumsByInteractionGroup, datumsByTooltipGroup]
}, [
isInteracting,
allDatums,
options.interactionMode,
primaryAxis,
Expand Down Expand Up @@ -615,6 +627,7 @@ function ChartInner<TDatum>({
axisDimensionsState,
focusedDatumState,
svgRef,
isInteractingState,
}

const seriesByAxisId = React.useMemo(
Expand Down Expand Up @@ -696,6 +709,12 @@ function ChartInner<TDatum>({
overflow: options.brush ? 'hidden' : 'visible',
}}
onClick={e => options.onClickDatum?.(focusedDatum, e)}
onMouseEnter={() => {
isInteractingState[1](true)
}}
onMouseLeave={() => {
isInteractingState[1](false)
}}
>
<g className="axes">
{[primaryAxis, ...secondaryAxes].map(axis => (
Expand Down
17 changes: 10 additions & 7 deletions src/components/Voronoi.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@ import { line } from 'd3-shape'
import { getPrimaryGroupLength, getPrimaryLength } from '../seriesTypes/Bar'

export default function Voronoi<TDatum>() {
const { getOptions, focusedDatumState } = useChartContext<TDatum>()
const { getOptions, focusedDatumState, isInteractingState } =
useChartContext<TDatum>()

const [, setFocusedDatum] = focusedDatumState
const [isInteracting] = isInteractingState

const {
onFocusDatum,
Expand All @@ -32,12 +34,13 @@ export default function Voronoi<TDatum>() {
)

const needsVoronoi =
onFocusDatum ||
onClickDatum ||
tooltip ||
primaryCursor ||
secondaryCursor ||
showVoronoi
isInteracting &&
(showVoronoi ||
onFocusDatum ||
onClickDatum ||
tooltip ||
primaryCursor ||
secondaryCursor)

if (!needsVoronoi) {
return null
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export type ChartContextValue<TDatum> = {
Datum<TDatum> | null,
React.Dispatch<React.SetStateAction<Datum<TDatum> | null>>
]
isInteractingState: [boolean, React.Dispatch<React.SetStateAction<boolean>>]
}

export type TooltipOptions<TDatum> = {
Expand Down
30 changes: 19 additions & 11 deletions src/utils/buildAxis.linear.ts
Original file line number Diff line number Diff line change
Expand Up @@ -493,17 +493,21 @@ function stackSeries<TDatum>(
})
)

stacked.forEach((s, sIndex) => {
s.forEach((datum, i) => {
for (let sIndex = 0; sIndex < stacked.length; sIndex++) {
const s = stacked[sIndex]

for (let i = 0; i < s.length; i++) {
const datum = s[i]

if (axisSeries[sIndex].datums[i]) {
// @ts-ignore
datum.data = axisSeries[sIndex].datums[i]

axisSeries[sIndex].datums[i].stackData =
datum as unknown as StackDatum<TDatum>
}
})
})
}
}
}

function buildPrimaryBandScale<TDatum>(
Expand All @@ -516,25 +520,29 @@ function buildPrimaryBandScale<TDatum>(

let impliedBandWidth: number = Math.max(...range)

series.forEach(serie => {
serie.datums.forEach(d1 => {
for (let i = 0; i < series.length; i++) {
const serie = series[i]

for (let j = 0; j < serie.datums.length; j++) {
const d1 = serie.datums[j]
const one = scale(d1.primaryValue ?? NaN)

serie.datums.forEach(d2 => {
for (let k = 0; k < serie.datums.length; k++) {
const d2 = serie.datums[k]
const two = scale(d2.primaryValue ?? NaN)

if (one === two) {
return
continue
}

const diff = Math.abs(Math.max(one, two) - Math.min(one, two))

if (diff < impliedBandWidth) {
impliedBandWidth = diff
}
})
})
})
}
}
}

const bandRange = Math.max(...range)

Expand Down

0 comments on commit 28c8e78

Please sign in to comment.