diff --git a/packages/vstory/demo/src/demos/VChartSite/scene5.tsx b/packages/vstory/demo/src/demos/VChartSite/scene5.tsx index ecd17f29..2882ae51 100644 --- a/packages/vstory/demo/src/demos/VChartSite/scene5.tsx +++ b/packages/vstory/demo/src/demos/VChartSite/scene5.tsx @@ -7,6 +7,7 @@ import scene5ChartImage from '../../assets/scene5/chart.png'; import scene5EnText from '../../assets/scene5/text-en.png'; import scene5ZhText from '../../assets/scene5/text-zh.png'; import { easeInOutQuad } from './util'; +import { Matrix } from '@visactor/vutils'; const chartSpec = { type: 'sequence', @@ -1038,6 +1039,15 @@ const chartSpec = { ] }; +const getTransformPointFunc = (offsetX: number, offsetY: number, scaleX: number, scaleY: number) => { + const m = new Matrix().translate(-offsetX, -offsetY).setScale(1 / scaleX, 1 / scaleY); + return (x: number, y: number) => { + const point = { x: 0, y: 0 }; + m.transformPoint({ x, y }, point); + return point; + }; +}; + export const scene5Characters: ICharacterSpec[] = [ { type: 'RectComponent', @@ -1379,3 +1389,52 @@ export const scene5: ISceneSpec = { } ] }; + +// disappear +scene5.actions.forEach(({ characterId, characterActions }) => { + const duration = 700; + + if (characterId !== 'scene5-background-decoration') { + const scaleX = 4; + const scaleY = 4; + const transformPointFunc = getTransformPointFunc(-450, -180, scaleX, scaleY); + + const character = scene5Characters.find(c => c.id === characterId); + if (character) { + const { left, top, width, height } = character.position; + const { x, y } = transformPointFunc(left, top); + const newWidth = width * scaleX; + const newHeight = height * scaleY; + characterActions.push({ + startTime: 5400, + duration, + action: 'style', + payload: { + graphic: { + width: newWidth, + height: newHeight, + x, + y + }, + animation: { + easing: 'easeInOutQuad', + duration + } + } + }); + } + } + + characterActions.push({ + startTime: 5400, + duration, + action: 'disappear', + payload: { + animation: { + easing: 'easeInOutQuad', + duration, + effect: 'fade' + } + } + }); +}); diff --git a/packages/vstory/src/dsl/story-processor/graphic/disappear.ts b/packages/vstory/src/dsl/story-processor/graphic/disappear.ts index 2878050b..9e6aeaf0 100644 --- a/packages/vstory/src/dsl/story-processor/graphic/disappear.ts +++ b/packages/vstory/src/dsl/story-processor/graphic/disappear.ts @@ -12,7 +12,6 @@ export const graphicDisappearProcessor = async ( const { effect } = animation ?? {}; const effects = effect && disappearEffectMap[effect] ? [effect] : Object.keys(disappearEffectMap); - effects.forEach(effect => { if (animation.effect === effect || animation[effect]) { // 获取执行方法 diff --git a/packages/vstory/src/dsl/story-processor/graphic/effect/disappear.ts b/packages/vstory/src/dsl/story-processor/graphic/effect/disappear.ts index 738ed08f..d34d48be 100644 --- a/packages/vstory/src/dsl/story-processor/graphic/effect/disappear.ts +++ b/packages/vstory/src/dsl/story-processor/graphic/effect/disappear.ts @@ -74,12 +74,24 @@ export function scaleOut(graphic: IGraphic, params: IScaleOutParams) { if (!canDoGraphicAnimation(graphic, params)) { return false; } + debugger; const { scale = {} } = params; const ratio = scale.ratio ?? params.ratio ?? 0; + const scaleCenter = scale.scaleCenter ?? params.scaleCenter; const duration = scale.duration ?? params.duration; const easing = scale.easing ?? params.easing; - - graphic.animate().to({ scaleX: ratio, scaleY: ratio }, duration, easing as EasingType); + const originScaleCenter = graphic.attribute.scaleCenter; + if (scaleCenter) { + graphic.setAttributes({ scaleCenter }); + } + graphic + .animate() + .to({ scaleX: ratio, scaleY: ratio }, duration, easing as EasingType) + .onEnd(() => { + if (originScaleCenter) { + graphic.setAttributes({ scaleCenter: originScaleCenter }); + } + }); return true; } @@ -155,7 +167,7 @@ export function commonDisappearEffect( ) { let doAnimation = true; switch (effect) { - case 'shrink': + case 'scale': scaleOut(graphic, params); break; case 'fade': diff --git a/packages/vstory/src/dsl/story-processor/vchart/charts/character/characterAppear.ts b/packages/vstory/src/dsl/story-processor/vchart/charts/character/characterAppear.ts new file mode 100644 index 00000000..fa670d97 --- /dev/null +++ b/packages/vstory/src/dsl/story-processor/vchart/charts/character/characterAppear.ts @@ -0,0 +1,37 @@ +import type { VChart, ISpec } from '@visactor/vchart'; +import type { IChartAppearAction } from '../../../../types/chart/appear'; +import type { ICharacterVisactor } from '../../../../../story/character/visactor/interface'; +import { graphicAppearProcessor } from '../../../graphic/appear'; +import { appearEffectMap } from '../../../graphic/effect/appear'; + +export const characterAppearProcessor = async ( + chartInstance: ICharacterVisactor, + spec: ISpec, + action: IChartAppearAction +) => { + const chart = chartInstance.getGraphicParent(); + const vchart = chart?._vchart; + const instance: VChart = vchart ? vchart : chartInstance; + if (!instance) { + return; + } + + const { animation } = action.payload ?? {}; + const { effect } = animation ?? {}; + + const effects = effect && appearEffectMap[effect] ? [effect] : Object.keys(appearEffectMap); + + effects.forEach(effect => { + instance + .getChart() + .getAllMarks() + .forEach(mark => { + const product = mark.getProduct(); + if (product) { + const graphic = product.getGroupGraphicItem(); + const appearEffect = appearEffectMap[effect]; + appearEffect(graphic, animation); + } + }); + }); +}; diff --git a/packages/vstory/src/dsl/story-processor/vchart/charts/character/characterDisappear.ts b/packages/vstory/src/dsl/story-processor/vchart/charts/character/characterDisappear.ts new file mode 100644 index 00000000..6108d863 --- /dev/null +++ b/packages/vstory/src/dsl/story-processor/vchart/charts/character/characterDisappear.ts @@ -0,0 +1,26 @@ +import VChart, { ISpec } from '@visactor/vchart'; +import { IChartAppearAction } from '../../../../types/chart/appear'; +import { ICharacterVisactor } from '../../../../../story/character/visactor/interface'; +import { graphicDisappearProcessor } from '../../../graphic/disappear'; + +export const characterDisappearProcessor = async ( + chartInstance: ICharacterVisactor, + spec: ISpec, + action: IChartAppearAction +) => { + const chart = chartInstance.getGraphicParent(); + const vchart = chart?._vchart; + const instance: VChart = vchart ? vchart : chartInstance; + + if (!instance) { + return; + } + // Group Disappear + // @ts-ignore + graphicDisappearProcessor(chartInstance, spec, action); + + // 隐藏group + chart.setAttributes({ + visible: false + }); +}; diff --git a/packages/vstory/src/dsl/story-processor/vchart/charts/character/index.ts b/packages/vstory/src/dsl/story-processor/vchart/charts/character/index.ts new file mode 100644 index 00000000..622b939a --- /dev/null +++ b/packages/vstory/src/dsl/story-processor/vchart/charts/character/index.ts @@ -0,0 +1,10 @@ +import { characterAppearProcessor } from './characterAppear'; +import { characterDisappearProcessor } from './characterDisappear'; + +export { characterDisappearProcessor } from './characterDisappear'; +export { characterAppearProcessor } from './characterAppear'; + +export const characterProcessorMap = { + appear: characterAppearProcessor, + disappear: characterDisappearProcessor +}; diff --git a/packages/vstory/src/dsl/story-processor/vchart/marks/rect/appear.ts b/packages/vstory/src/dsl/story-processor/vchart/marks/rect/appear.ts index 6d698767..361649e5 100644 --- a/packages/vstory/src/dsl/story-processor/vchart/marks/rect/appear.ts +++ b/packages/vstory/src/dsl/story-processor/vchart/marks/rect/appear.ts @@ -1,6 +1,5 @@ -import VChart, { ISpec } from '@visactor/vchart'; +import type { VChart, ISpec } from '@visactor/vchart'; import { merge } from '@visactor/vutils'; -import { getAllSeriesMarksByMarkType } from '../../utils'; import { IChartAppearAction } from '../../../../types/chart/appear'; import { transformRectAppear } from './transformRectAppear'; import { ICharacterVisactor } from '../../../../../story/character/visactor/interface';