From 45e1db5b3a903e21b59ef1781227332e890a406c Mon Sep 17 00:00:00 2001 From: Andy Richardson Date: Thu, 18 Aug 2022 15:57:47 +0100 Subject: [PATCH] Add snap ends option --- src/interpolatePath.js | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/interpolatePath.js b/src/interpolatePath.js index 07ea01d..4c59688 100644 --- a/src/interpolatePath.js +++ b/src/interpolatePath.js @@ -310,19 +310,30 @@ export function pathCommandsFromString(d) { * * @param {Object[]} aCommandsInput Array of path commands * @param {Object[]} bCommandsInput Array of path commands - * @param {Function} excludeSegment a function that takes a start command object and + * @param {(Function|Object)} interpolateOptions + * @param {Function} interpolateOptions.excludeSegment a function that takes a start command object and * end command object and returns true if the segment should be excluded from splitting. + * @param {Boolean} interpolateOptions.snapEndsToInput a boolean indicating whether end of input should + * be sourced from input argument or computed. * @returns {Function} Interpolation function that maps t ([0, 1]) to an array of path commands. */ export function interpolatePathCommands( aCommandsInput, bCommandsInput, - excludeSegment + interpolateOptions ) { // make a copy so we don't mess with the input arrays let aCommands = aCommandsInput == null ? [] : aCommandsInput.slice(); let bCommands = bCommandsInput == null ? [] : bCommandsInput.slice(); + const { excludeSegment, snapEndsToInput } = + typeof interpolateOptions === "object" + ? interpolateOptions + : { + excludeSegment: interpolateOptions, + snapEndsToInput: false, + }; + // both input sets are empty, so we don't interpolate if (!aCommands.length && !bCommands.length) { return function nullInterpolator() { @@ -384,7 +395,7 @@ export function interpolatePathCommands( return function pathCommandInterpolator(t) { // at 1 return the final value without the extensions used during interpolation - if (t === 1) { + if (t === 1 && snapEndsToInput) { return bCommandsInput == null ? [] : bCommandsInput; } @@ -423,14 +434,25 @@ export function interpolatePathCommands( * * @param {String} a The `d` attribute for a path * @param {String} b The `d` attribute for a path - * @param {Function} excludeSegment a function that takes a start command object and + * @param {(Function|Object)} interpolateOptions + * @param {Function} interpolateOptions.excludeSegment a function that takes a start command object and * end command object and returns true if the segment should be excluded from splitting. + * @param {Boolean} interpolateOptions.snapEndsToInput a boolean indicating whether end of input should + * be sourced from input argument or computed. * @returns {Function} Interpolation function that maps t ([0, 1]) to a path `d` string. */ -export default function interpolatePath(a, b, excludeSegment) { +export default function interpolatePath(a, b, interpolateOptions) { let aCommands = pathCommandsFromString(a); let bCommands = pathCommandsFromString(b); + const { excludeSegment, snapEndsToInput } = + typeof interpolateOptions === "object" + ? interpolateOptions + : { + excludeSegment: interpolateOptions, + snapEndsToInput: false, + }; + if (!aCommands.length && !bCommands.length) { return function nullInterpolator() { return ''; @@ -445,8 +467,8 @@ export default function interpolatePath(a, b, excludeSegment) { return function pathStringInterpolator(t) { // at 1 return the final value without the extensions used during interpolation - if (t === 1) { - return b == null ? '' : b; + if (t === 1 && snapEndsToInput) { + return b == null ? "" : b; } const interpolatedCommands = commandInterpolator(t);