Skip to content

Instantly share code, notes, and snippets.

@valtism
Created April 8, 2024 03:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save valtism/80d8d7d6f3ae58c29d274210bda7990c to your computer and use it in GitHub Desktop.
Save valtism/80d8d7d6f3ae58c29d274210bda7990c to your computer and use it in GitHub Desktop.
A more performant version of Visx's `<SplitLinePath>`. See https://github.com/airbnb/visx/issues/1591
import { LinePath, line } from "@visx/shape";
import { SplitLinePathProps } from "@visx/shape/lib/shapes/SplitLinePath";
import { Fragment } from "react";
type PerformantSplitLinePathRenderer = (renderProps: {
index: number;
path: string;
styles?: Omit<React.SVGProps<SVGPathElement>, "x" | "y" | "children">;
}) => React.ReactNode;
type PerformantSplitLinePathProps<Datum> = Omit<
SplitLinePathProps<Datum>,
"children"
> & { children?: PerformantSplitLinePathRenderer };
// A more performant version of Visx's <SplitLinePath>
export function PerformantSplitLinePath<Datum>({
children,
className,
curve,
defined,
segments,
x,
y,
styles,
}: PerformantSplitLinePathProps<Datum>) {
const path = line<Datum>({ x, y, defined, curve });
const paths = segments.map((segment, index, segments) => {
const isLastSegment = index === segments.length - 1;
const segmentIncludingStartOfNextSegment = isLastSegment
? segment
: segment.concat(segments[index + 1][0]);
return path(segmentIncludingStartOfNextSegment) || "";
});
return (
<g>
{paths.map((path, index) =>
children ? (
<Fragment key={index}>
{children({
index,
path,
styles: styles[index] || styles[index % styles.length],
})}
</Fragment>
) : (
<LinePath
key={index}
className={className}
d={path}
{...(styles[index] || styles[index % styles.length])}
/>
),
)}
</g>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment