diff --git a/packages/vstory-animate/__tests__/unit/index.test.ts b/packages/vstory-animate/__tests__/unit/index.test.ts index a59b1e43..a66aaa0b 100644 --- a/packages/vstory-animate/__tests__/unit/index.test.ts +++ b/packages/vstory-animate/__tests__/unit/index.test.ts @@ -1,7 +1,9 @@ import { BarBounce } from '../../src/customAnimates/bar-bounce'; import { BarLeap } from '../../src/customAnimates/bar-leap'; +import { PieLeap } from '../../src/customAnimates/pie-leap'; -describe('custom bar animates', () => { + +describe('custom animates', () => { function bindMockTarget(animate: BarBounce | BarLeap) { const target = { attribute: { ...animate.getFromProps() }, @@ -16,6 +18,7 @@ describe('custom bar animates', () => { return target; } + it('should not crash when BarBounce receives a null from rect', () => { const animate = new BarBounce(null, { x: 20, x1: 60, y: 10, y1: 110 }, 1000, 'linear' as any, {}); const out: Record = {}; @@ -86,4 +89,17 @@ describe('custom bar animates', () => { expect(pathProxy.clear).toHaveBeenCalled(); expect(pathProxy.moveTo).toHaveBeenCalled(); }); + + it('should not crash when PieLeap receives a null from arc', () => { + const animate = new PieLeap(null, { x: 40, y: 60, innerRadius: 20, outerRadius: 80 }, 1000, 'linear' as any, {}); + const out: Record = {}; + + animate.onUpdate(false, 0.5, out); + + expect(animate.getFromProps()).toMatchObject({ x: 540, y: -440, innerRadius: 20, outerRadius: 50 }); + expect(animate.getEndProps()).toMatchObject({ x: 40, y: 60, innerRadius: 20, outerRadius: 80 }); + expect(Number.isFinite(out.x)).toBe(true); + expect(Number.isFinite(out.y)).toBe(true); + expect(Number.isFinite(out.outerRadius)).toBe(true); + }); }); diff --git a/packages/vstory-animate/src/customAnimates/pie-leap.ts b/packages/vstory-animate/src/customAnimates/pie-leap.ts index cefbcd60..f7ae13a5 100644 --- a/packages/vstory-animate/src/customAnimates/pie-leap.ts +++ b/packages/vstory-animate/src/customAnimates/pie-leap.ts @@ -1,6 +1,20 @@ import type { EasingType } from '@visactor/vrender'; import { ACustomAnimate, generatorPathEasingFunc } from '@visactor/vrender'; +interface IPieLeapAnimateProps { + y?: number; + x?: number; + innerRadius?: number; + outerRadius?: number; +} + +interface INormalizedPieLeapAnimateProps extends IPieLeapAnimateProps { + y: number; + x: number; + innerRadius: number; + outerRadius: number; +} + export const pieLeap1Str = 'M0,0 C0,0.301 0.256,1.032 0.607,1.033 0.763,1.033 0.752,0.983 0.86,0.983 0.978,0.983 0.972,1 1,1'; export const pieLeap2Str = @@ -9,6 +23,26 @@ export const pieLeap2Str = const pieLeap1 = generatorPathEasingFunc(pieLeap1Str); const pieLeap2 = generatorPathEasingFunc(pieLeap2Str); +function normalizePieLeapProps( + arc?: IPieLeapAnimateProps | null, + fallback?: IPieLeapAnimateProps | null +): INormalizedPieLeapAnimateProps { + const source = arc ?? {}; + const ref = fallback ?? {}; + + const innerRadius = source.innerRadius ?? ref.innerRadius ?? 0; + const outerRadius = source.outerRadius ?? ref.outerRadius ?? innerRadius; + + return { + ...ref, + ...source, + x: source.x ?? ref.x ?? 0, + y: source.y ?? ref.y ?? 0, + innerRadius, + outerRadius + }; +} + export class PieLeap extends ACustomAnimate<{ y: number; x: number; innerRadius: number; outerRadius: number }> { static label: string = 'pie-leap'; static delayPerTime: number = 50; @@ -17,19 +51,21 @@ export class PieLeap extends ACustomAnimate<{ y: number; x: number; innerRadius: declare valid: boolean; constructor( - from: { y: number; x: number; innerRadius: number; outerRadius: number }, - to: { y: number; x: number; innerRadius: number; outerRadius: number }, + from: { y: number; x: number; innerRadius: number; outerRadius: number } | null, + to: { y: number; x: number; innerRadius: number; outerRadius: number } | null, duration: number, easing: EasingType, params: any ) { + const target = normalizePieLeapProps(to, from); + const start = normalizePieLeapProps(from, target); const f = { - y: from.y - 500, - x: from.x + 500, - innerRadius: from.innerRadius, - outerRadius: (from.innerRadius + from.outerRadius) / 2 + y: start.y - 500, + x: start.x + 500, + innerRadius: start.innerRadius, + outerRadius: (start.innerRadius + start.outerRadius) / 2 }; - super(f, to, duration, easing, params); + super(f, target, duration, easing, params); } getEndProps(): Record {