Skip to content

Commit

Permalink
internal(vx-shape/SplitLinePath): remove dir structure, fix types, fe…
Browse files Browse the repository at this point in the history
…wer multiplications, improve path measurement node attributes
  • Loading branch information
williaster committed Aug 14, 2020
1 parent 67b889e commit 6bcd74d
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 89 deletions.
73 changes: 73 additions & 0 deletions packages/vx-shape/src/shapes/SplitLinePath.tsx
@@ -0,0 +1,73 @@
import React, { useMemo } from 'react';
import LinePath from './LinePath';
import getSplitLineSegments from '../util/getSplitLineSegments';
import { LinePathConfig } from '../types';

interface Point {
x: number;
y: number;
}

type SplitLinePathProps<Datum> = {
/** Array of data segments, where each segment will be a separate path in the rendered line. */
segments: Datum[][];
/** Styles to apply to each segment. If fewer styles are specified than the number of segments, they will be re-used. */
styles: Omit<React.SVGProps<SVGPathElement>, 'x' | 'y' | 'children'>[];
/** Override render function which is passed the configured path generator as input. */
children?: (renderProps: {
index: number;
segment: { x: number; y: number }[];
styles?: Omit<React.SVGProps<SVGPathElement>, 'x' | 'y' | 'children'>;
}) => React.ReactNode;
/** className applied to path element. */
className?: string;
/** Optionally specify the sample rate for interpolating line segments. */
sampleRate?: number;
} & LinePathConfig<Datum>;

export default function SplitLinePath<Datum>({
children,
className,
curve,
defined,
sampleRate,
segments,
x,
y,
styles,
}: SplitLinePathProps<Datum>) {
// combine data to first draw entire path
const combinedSegments: Datum[] = useMemo(
() => segments.reduce((flat, segmentData) => flat.concat([...segmentData]), []),
[segments],
);

return (
<LinePath data={combinedSegments} defined={defined} curve={curve} x={x} y={y}>
{({ path }) => {
// use entire path to interpolate individual segments
const entirePath = path(combinedSegments);
const computedLineSegments = getSplitLineSegments({
path: entirePath || '',
segments,
sampleRate,
});

return computedLineSegments.map((segment, index) =>
children ? (
children({ index, segment, styles: styles[index] || styles[index % styles.length] })
) : (
<LinePath
key={index}
className={className}
data={segment}
x={(d: Point) => d.x || 0}
y={(d: Point) => d.y || 0}
{...(styles[index] || styles[index % styles.length])}
/>
),
);
}}
</LinePath>
);
}
83 changes: 0 additions & 83 deletions packages/vx-shape/src/shapes/SplitLinePath/index.tsx

This file was deleted.

@@ -1,17 +1,23 @@
import memoize from 'lodash/memoize';

const MEASUREMENT_ELEMENT_ID = '__vx_splitpath_svg_path_measurement_id';
const SVG_NAMESPACE_URL = 'http://www.w3.org/2000/svg';

export interface GetLineSegmentsConfig<Datum> {
/** Full path `d` attribute to be broken up. */
/** Full path `d` attribute to be broken up into `n` segments. */
path: string;
/**
* Array of length `n`, where `n` is the number of resulting line segments.
* For each segment of length `m`, `m / sampleRate` evenly spaced points will be returned.
*/
segments: Datum[][];
/** For each segment of length `m`, `m / sampleRate` evenly spaced points will be returned. */
sampleRate?: number;
}

type LineSegments = { x: number; y: number }[][];

export function getLineSegments<Datum>({
export function getSplitLineSegments<Datum>({
path,
segments,
sampleRate = 0.25,
Expand All @@ -21,13 +27,18 @@ export function getLineSegments<Datum>({

// create a single path element if not done already
if (!pathElement) {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
const svg = document.createElementNS(SVG_NAMESPACE_URL, 'svg');
// not visible
svg.style.opacity = '0';
svg.style.width = '0';
svg.style.height = '0';
// off screen
svg.style.position = 'absolute';
svg.style.top = '-100%';
svg.style.left = '-100%';
pathElement = document.createElementNS('http://www.w3.org/2000/svg', 'path');
// no mouse events
svg.style.pointerEvents = 'none';
pathElement = document.createElementNS(SVG_NAMESPACE_URL, 'path');
pathElement.setAttribute('id', MEASUREMENT_ELEMENT_ID);
svg.appendChild(pathElement);
document.body.appendChild(svg);
Expand All @@ -46,7 +57,7 @@ export function getLineSegments<Datum>({
const coords: { x: number; y: number }[] = [];

for (let i = 0; i < segmentPointCount + sampleRate; i += sampleRate) {
const distance = cumulativeSize * pieceSize + i * pieceSize;
const distance = (cumulativeSize + i) * pieceSize;
const point = pathElement!.getPointAtLength(distance);
coords.push(point);
}
Expand All @@ -63,7 +74,7 @@ export function getLineSegments<Datum>({
}

export default memoize(
getLineSegments,
getSplitLineSegments,
({ path, segments, sampleRate }: GetLineSegmentsConfig<any>) =>
`${path}_${segments.length}_${segments.map(segment => segment.length).join('-')}_${sampleRate}`,
);

0 comments on commit 6bcd74d

Please sign in to comment.