diff --git a/docs/assets/examples/en/character/poptip.md b/docs/assets/examples/en/character/poptip.md new file mode 100644 index 00000000..103c6062 --- /dev/null +++ b/docs/assets/examples/en/character/poptip.md @@ -0,0 +1,184 @@ +--- +category: examples +group: character +title: poptip +keywords: poptip +order: 1-0 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vstory/poptip.gif +--- + +# PopTip Element + +`PopTip` is an annotation element used to add a bubble at a specific position to display detailed information. The design of `PopTip` is flexible and diverse, supporting the display of tips in different directions. This means developers can choose the direction of the bubble display, such as top, bottom, left, or right, based on specific needs and interface design, ensuring that the tip information does not obstruct important interface elements and users can easily access the information they need. + +Moreover, `PopTip` can be customized, such as adjusting colors, fonts, sizes, etc., to maintain consistency with the overall interface style. This makes `PopTip` a very practical tool widely used in scenarios such as data visualization, form filling, navigation tips, providing users with a richer and more user-friendly interactive experience. + +## Code Demo + +```javascript livedemo template=vstory +// 注册所有需要的内容 +VStory.registerAll(); +// 注册PopTip +VStory.registerPopTip(); +VStory.registerPopTipAction(); + +const story = new VStory.Story(null, { dom: CONTAINER_ID, background: '#18253A' }); +const player = new VStory.Player(story); +story.init(player); + +const panelStyle = { + shadowColor: 'rgba(0, 0, 0, 0.1)', + shadowBlur: 10, + shadowOffsetX: 4, + shadowOffsetY: 4, + fill: 'white', + cornerRadius: 4, + size: 9 +}; +const commonStyle = { + content: '$123,45', + position: 'tl', + padding: { top: 6, bottom: 6, left: 6, right: 6 }, + contentStyle: { + fontSize: 12, + fill: '#08979c' + } +}; + +const p1 = { + ...commonStyle, + panel: { + ...panelStyle + } +}; +const p2 = { + ...commonStyle, + triangleMode: 'concise', + panel: { + ...panelStyle, + cornerRadius: 0 + } +}; +const p3 = { + ...commonStyle, + triangleMode: 'concise', + panel: { + ...panelStyle, + fill: false, + stroke: 'white', + cornerRadius: 0, + size: 0 + } +}; +const p4 = { + ...commonStyle, + position: 'top', + panel: { + ...panelStyle, + square: true, + cornerRadius: 100, + size: 12 + } +}; + +const p5 = { + content: '123,45', + padding: { top: 3, bottom: 3, left: 12, right: 6 }, + position: 'tl', + contentStyle: { + fontSize: 12, + fill: '#08979c' + }, + panel: { + ...panelStyle, + cornerRadius: [0, 20, 20, 0] + }, + logoSymbol: { + symbolType: 'circle', + fill: 'red', + size: 'auto' + }, + logoText: '$', + logoTextStyle: { + fill: 'white', + fontSize: 12 + } +}; + +const p6 = { + content: '123,45', + position: 'tl', + padding: { top: 3, bottom: 3, left: 13, right: 8 }, + contentStyle: { + fontSize: 12, + fill: '#08979c' + }, + panel: { + ...panelStyle, + cornerRadius: [0, 0, 6, 0], + cornerType: 'bevel', + size: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [20, 'auto'], + cornerType: 'bevel' + }, + logoText: '🤡', + logoTextStyle: { + fill: 'white', + fontSize: 12 + } +}; + +[p1, p2, p3, p4, p5, p6].forEach((item, index) => { + story.addCharacter( + { + type: 'PopTip', + id: `poptip-${index}`, + zIndex: 1, + position: { + top: 100 + Math.floor(index / 3) * 120, + left: 50 + (index % 3) * 120 + }, + options: { + graphic: item + } + }, + { + sceneId: 'defaultScene', + actions: [ + { + startTime: 0, + action: 'appear', + payload: [ + { + animation: { + duration: 300, + easing: 'quadOut', + wave: 0.3 + } + } + ] + }, + { + startTime: 1000, + action: 'disappear', + payload: { + animation: { + duration: 300, + easing: 'aIn3' + } + } + } + ] + } + ); +}); + +player.play(1); + +window['story'] = story; +window['vstory'] = story; +``` diff --git a/docs/assets/examples/en/character/story-label-item.md b/docs/assets/examples/en/character/story-label-item.md new file mode 100644 index 00000000..82a26c9e --- /dev/null +++ b/docs/assets/examples/en/character/story-label-item.md @@ -0,0 +1,156 @@ +--- +category: examples +group: character +title: story-label-item +keywords: story-label-item +order: 1-0 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vstory/label-item.gif +--- + +# Narrative Label Element + +`story-label-item` is a labeling element specifically designed to add explanatory text or information at specific locations. Unlike traditional ways of displaying information directly around the target, `story-label-item` connects the explanation to its corresponding target element through an additional connecting line. This design allows the label to be flexibly placed within a larger area around the target, without being limited to the edges of the target. + +This flexibility not only enhances the aesthetics of the interface but also effectively avoids information overlap or obstruction, ensuring that users can clearly see the labeled content while browsing. Specifically, `story-label-item` can choose the best position to display the label based on the layout and design requirements of the interface, whether it is above, below, to the left, or to the right of the target, or even further away, as long as it clearly points to the target through the connecting line. + +Furthermore, `story-label-item` supports various styles and customization options. Developers can adjust its appearance according to specific application scenarios to ensure coordination with the overall design style. This makes `story-label-item` a very practical tool, widely used in data visualization, user instructions, interactive design, and many other fields, providing users with a more intuitive and friendly information delivery experience. + +## Code Demo + +```javascript livedemo template=vstory +// 注册所有需要的内容 +VStory.registerAll(); +// 注册PopTip +VStory.registerLabelItem(); +VStory.registerLabelItemAction(); + +const story = new VStory.Story(null, { dom: CONTAINER_ID, background: '#18253A' }); +const player = new VStory.Player(story); +story.init(player); + +const l1 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor' +}; +const l2 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor', + titleBottom: 'this is the VStory label', + titleBottomStyle: { + fontSize: 10 + } +}; +const l3 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleSpace: [6, 6], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 12, + fill: 'black' + }, + titleTopPanelStyle: { + fill: 'white', + visible: true, + padding: { top: 3, bottom: 3 } + } +}; + +const l4 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleSpace: [6, 6], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 12, + fill: 'black' + }, + titleBottom: 'this is the VStory label', + titleBottomStyle: { + fontSize: 10, + fill: 'black' + }, + titleTopPanelStyle: { + fill: 'white', + visible: true, + padding: { top: 3, bottom: 3 } + }, + titleBottomPanelStyle: { + fill: 'white', + visible: true, + padding: { top: 3, bottom: 6 } + } +}; + +const l5 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 12 + }, + titleTopPanelStyle: { + stroke: 'white', + visible: true + // padding: { top: 3, bottom: 3 } + }, + theme: 'simple' +}; + +[l1, l2, l3, l4, l5, l1, l2, l3, l4, l5].forEach((item, index) => { + story.addCharacter( + { + type: 'LabelItem', + id: `label-item-${index}`, + zIndex: 1, + position: { + top: 100 + Math.floor(index / 3) * 100, + left: 50 + (index % 3) * 230 + }, + options: { + graphic: item + } + }, + { + sceneId: 'defaultScene', + actions: [ + { + startTime: 0, + action: 'appear', + payload: [ + { + animation: { + duration: 1000, + easing: 'cubicIn', + symbolStartOuterType: Math.floor(index / 5) === 0 ? 'scale' : 'clipRange', + titleType: Math.floor(index / 5) === 0 ? 'move' : 'typewriter', + titlePanelType: index === 4 ? 'stroke' : 'scale' + } + } + ] + }, + { + startTime: 2000, + action: 'disappear', + payload: { + animation: { + duration: 700, + easing: 'cubicIn', + mode: Math.floor(index / 5) === 0 ? 'default' : 'scale' + } + } + } + ] + } + ); +}); + +player.play(1); + +window['story'] = story; +window['vstory'] = story; +``` diff --git a/docs/assets/examples/en/works-show/unit-infographic.md b/docs/assets/examples/en/infographic/unit-infographic.md similarity index 97% rename from docs/assets/examples/en/works-show/unit-infographic.md rename to docs/assets/examples/en/infographic/unit-infographic.md index 81ccb6bc..6a6d047e 100644 --- a/docs/assets/examples/en/works-show/unit-infographic.md +++ b/docs/assets/examples/en/infographic/unit-infographic.md @@ -1,17 +1,17 @@ --- category: examples -group: works-show +group: infographic title: unit-infographic keywords: unit-infographic order: 1-0 cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vstory/unit-infographic.png --- -# `Unit Visualization Infographic` Work Display +# Showcase of `Unit Infographic` -This work is a unit visualization infographic work, showing VStory's ability in making infographic templates. +This work is a unit visualization infographic showcasing VStory's ability to create infographic templates. -## Code Demonstration +## Code Demo ```javascript livedemo template=vstory // 注册所有需要的内容 diff --git a/docs/assets/examples/en/works-show/annotation-show.md b/docs/assets/examples/en/works-show/annotation-show.md new file mode 100644 index 00000000..fb2cd902 --- /dev/null +++ b/docs/assets/examples/en/works-show/annotation-show.md @@ -0,0 +1,542 @@ +--- +category: examples +group: works-show +title: annotation-show +keywords: annotation-show +order: 1-0 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vstory/annotation-works.gif +--- + +# Showcase of `Annotation Capability` + +This showcase demonstrates the annotation capabilities animation provided by VStory, showcasing a variety of annotation components and animation abilities. + +## Code Demo + +```javascript livedemo template=vstory +// 注册所有需要的内容 +VStory.registerAll(); +// 注册Label +VStory.registerLabelItem(); +VStory.registerLabelItemAction(); +// 注册PopTip +VStory.registerPopTip(); +VStory.registerPopTipAction(); + +const story = new VStory.Story(null, { dom: CONTAINER_ID, width: 2000 / 2, height: 800 / 2, background: '#ebecf0', scaleX: 0.5, scaleY: 0.5 }); +const player = new VStory.Player(story); +story.init(player); + +const perSceneDuring = 3000; + +story.addCharacter({ + type: 'Rect', + id: `background`, + zIndex: 0, + position: { + left: 0, + top: 0, + width: 1080, + height: 720 + }, + options: { + graphic: { + fill: '#18253A', + }, + text: { + text: 'ANIMATE 1', + fontSize: 80, + fill: 'white', + textAlign: 'center', + fontWeight: 'bolder', + textBaseline: 'middle' + } + } +}, { + sceneId: 'defaultScene', + actions: [ + { + action: 'appear', + startTime: 0, + payload: [ + { + animation: { + duration: 300, + easing: 'linear', + effect: 'fade' + } + } + ] + }, + { + action: 'style', + startTime: perSceneDuring, + payload: [ + { + animation: { + duration: 200, + easing: 'linear', + }, + graphic: { + fill: '#2E6670', + }, + text: { + text: 'ANIMATE 2', + } + } + ] + } + ] +}); + +const panelStyle = { + shadowColor: 'rgba(0, 0, 0, 0.1)', + shadowBlur: 10, + shadowOffsetX: 4, + shadowOffsetY: 4, + fill: 'white', + cornerRadius: 8, + size: 18 +}; +const commonStyle = { + content: 'Hello Vis', + position: 'right', + padding: { top: 16, bottom: 16, left: 16, right: 16 }, + contentStyle: { + fontSize: 22, + fill: '#1F4C4B' + } +}; + +const poptipList = [ + { + x: 180, y: 130, type: 'PopTip', + options: { + ...commonStyle, + position: 'bl', + triangleMode: 'concise', + panel: { + ...panelStyle, + cornerRadius: 0 + } + } + }, + { + x: 180, y: 130, type: 'PopTip', + options: { + ...commonStyle, + position: 'tr', + contentStyle: { + fontSize: 16, + fill: 'white' + }, + triangleMode: 'concise', + panel: { + ...panelStyle, + cornerRadius: 0, + fill: 'red', + } + } + }, + { + x: 400, y: 100, type: 'PopTip', + options: { + ...commonStyle, + panel: { + ...panelStyle, + size: 0 + } + } + }, + { + x: 630, y: 100, type: 'PopTip', + options: { + ...commonStyle, + position: 'right', + contentStyle: { + fontSize: 22, + fill: 'white', + fontWeight: 'bolder' + }, + panel: { + ...panelStyle, + fill: 'red', + cornerRadius: 0, + size: 0 + } + } + }, + { + x: 850, y: 100, type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 23, right: 18 }, + position: 'right', + panel: { + ...panelStyle, + cornerRadius: [0, 0, 6, 0], + cornerType: 'bevel', + size: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [36, 'auto'], + cornerType: 'bevel' + }, + logoText: '🤡', + logoTextStyle: { + fill: 'white', + fontSize: 26 + } + } + }, + + + { + x: 120, y: 280, type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 23, right: 18 }, + position: 'bl', + panel: { + ...panelStyle, + cornerType: 'bevel', + size: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [36, 'auto'], + cornerType: 'bevel' + }, + logoText: '🤡', + logoTextStyle: { + fill: 'white', + fontSize: 26 + } + } + }, + { + x: 470, y: 280, type: 'PopTip', + options: { + ...commonStyle, + position: 'top', + panel: { + ...panelStyle + } + } + }, + { + x: 850, y: 240, type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 26, right: 12 }, + content: '123,45', + position: 'right', + panel: { + ...panelStyle, + cornerRadius: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [30, 'auto'] + }, + logoText: '¥', + logoTextStyle: { + fill: 'white', + fontSize: 28 + } + } + }, + + + { + x: 120, y: 460, type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 33, right: 18 }, + content: '123,45', + position: 'bl', + panel: { + ...panelStyle, + cornerRadius: [0, 100, 100, 0] + }, + logoSymbol: { + symbolType: 'circle', + fill: 'red', + size: 'auto' + }, + logoText: '¥', + logoTextStyle: { + fill: 'white', + fontSize: 28 + } + } + }, + { + x: 500, y: 560, type: 'PopTip', + options: { + ...commonStyle, + content: 'Hi 👋', + position: 'bottom', + panel: { + ...panelStyle, + square: true, + cornerRadius: 100, + size: 12 + } + } + }, + { + x: 860, y: 520, type: 'PopTip', + options: { + ...commonStyle, + contentStyle: { + fontSize: 22, + fill: 'wihte' + }, + triangleMode: 'concise', + panel: { + ...panelStyle, + fill: false, + stroke: 'white', + cornerRadius: 0, + size: 0 + } + } + }, + + + { + x: 270, y: 630, type: 'PopTip', + options: { + ...commonStyle, + panel: { + ...panelStyle, + cornerRadius: 100, + size: 0 + } + } + }, + { + x: 630, y: 630, type: 'PopTip', + options: { + ...commonStyle, + panel: { + ...panelStyle + } + } + }, +]; + +poptipList.forEach((item, i) => { + story.addCharacter({ + type: item.type, + id: `${item.type}-${i}`, + zIndex: 10, + position: { + left: item.x, + top: item.y, + }, + options: { + graphic: item.options + } + }, { + sceneId: 'defaultScene', + actions: [ + { + startTime: 300, + action: 'appear', + payload: [ + { + animation: { + duration: 300, + easing: 'quadOut', + wave: 0.3 + } + } + ] + }, + { + startTime: perSceneDuring / 3 * 2, + action: 'disappear', + payload: { + animation: { + duration: 300, + easing: 'aIn3' + } + } + }, + { + startTime: perSceneDuring + 500, + action: 'appear', + payload: [ + { + animation: { + duration: 300, + easing: 'quadOut', + } + } + ] + }, + { + startTime: perSceneDuring + perSceneDuring / 3 * 2, + action: 'disappear', + payload: { + animation: { + duration: 300, + easing: 'aIn3' + } + } + }, + ] + }) +}) + +const labelList = [ + { + x: 900, y: 360, + options: { + contentOffsetX: -300, + contentOffsetY: -100, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 22, + } + } + }, + { + x: 100, y: 670, + options: { + contentOffsetX: 300, + contentOffsetY: -100, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor', + titleBottom: 'this is the VStory label', + titleTopStyle: { + fontSize: 22, + }, + titleBottomStyle: { + fontSize: 16 + } + } + }, + { + x: 500, y: 560, + options: { + contentOffsetX: 300, + contentOffsetY: -100, + titleSpace: [6, 6], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 22, + fill: 'black' + }, + titleTopPanelStyle: { + fill: 'white', + visible: true, + padding: { top: 3, bottom: 3 } + } + } + }, + { + x: 500, y: 560, + options: { + contentOffsetX: -300, + contentOffsetY: -130, + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 22 + }, + titleTopPanelStyle: { + stroke: 'white', + visible: true + }, + theme: 'simple' + } + } +] + + +labelList.forEach((label, index) => { + story.addCharacter( + { + type: 'LabelItem', + id: `label-item-${index}`, + zIndex: 100, + position: { + top: label.y, + left: label.x + }, + options: { + graphic: label.options + } + }, + { + sceneId: 'defaultScene', + actions: [ + { + startTime: 300, + action: 'appear', + payload: [ + { + animation: { + duration: 1000, + easing: 'cubicIn', + symbolStartOuterType: 'scale', + titleType: 'typewriter', + titlePanelType: label.options.theme === 'simple' ? 'stroke' : 'scale' + } + } + ] + }, + { + startTime: perSceneDuring / 3 * 2, + action: 'disappear', + payload: { + animation: { + duration: 700, + easing: 'cubicIn', + mode: 'default' + } + } + }, + { + startTime: perSceneDuring, + action: 'appear', + payload: [ + { + animation: { + duration: 1000, + easing: 'cubicIn', + symbolStartOuterType: 'clipRange', + titleType: 'move', + titlePanelType: label.options.theme === 'simple' ? 'stroke' : 'scale' + } + } + ] + }, + { + startTime: perSceneDuring + perSceneDuring / 3 * 2, + action: 'disappear', + payload: { + animation: { + duration: 700, + easing: 'cubicIn', + mode: 'scale' + } + } + } + ] + } + ); +}) + +player.play(1); + +window['story'] = story; +window['vstory'] = story; +``` diff --git a/docs/assets/examples/menu.json b/docs/assets/examples/menu.json index a23b295d..62e3d726 100644 --- a/docs/assets/examples/menu.json +++ b/docs/assets/examples/menu.json @@ -15,13 +15,6 @@ "en": "Visualize History" } }, - { - "path": "unit-infographic", - "title": { - "zh": "单元可视化信息图示例", - "en": "Unit Infographic Example" - } - }, { "path": "unit-gun-death", "title": { @@ -35,6 +28,13 @@ "zh": "多图表join", "en": "charts join" } + }, + { + "path": "annotation-show", + "title": { + "zh": "标注展示", + "en": "annotation show" + } } ] }, @@ -117,6 +117,20 @@ "en": "wave scatter" } }, + { + "path": "poptip", + "title": { + "zh": "标注-PopTip", + "en": "annotation-PopTip" + } + }, + { + "path": "story-label-item", + "title": { + "zh": "标注-StoryLabelItem", + "en": "annotation StoryLabelItem" + } + }, { "path": "vchart", "title": { @@ -179,6 +193,13 @@ "en": "infographic templates" }, "children": [ + { + "path": "unit-infographic", + "title": { + "zh": "单元可视化信息图示例", + "en": "Unit Infographic Example" + } + }, { "path": "line-chart-leftRight", "title": { diff --git a/docs/assets/examples/zh/character/poptip.md b/docs/assets/examples/zh/character/poptip.md new file mode 100644 index 00000000..81800d2b --- /dev/null +++ b/docs/assets/examples/zh/character/poptip.md @@ -0,0 +1,184 @@ +--- +category: examples +group: character +title: poptip +keywords: poptip +order: 1-0 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vstory/poptip.gif +--- + +# PopTip元素 + +`PopTip` 是一个标注元素,用于在某个位置上添加一个气泡,显示数据的详细信息,`PopTip` 的设计灵活多样,支持在不同方向上展示提示信息。这意味着开发者可以根据具体的需求和界面设计选择气泡的显示方向,例如上方、下方、左侧或右侧,从而确保提示信息不会遮挡重要的界面元素,并且用户能够轻松获取所需的信息。 + +此外,`PopTip` 还可以定制化,例如调整颜色、字体、大小等,以便与整体界面风格保持一致。这使得 `PopTip` 成为一种非常实用的工具,广泛应用于数据可视化、表单填写、导航提示等场景,为用户提供更为丰富和友好的交互体验。 + +## 代码演示 + +```javascript livedemo template=vstory +// 注册所有需要的内容 +VStory.registerAll(); +// 注册PopTip +VStory.registerPopTip(); +VStory.registerPopTipAction(); + +const story = new VStory.Story(null, { dom: CONTAINER_ID, background: '#18253A' }); +const player = new VStory.Player(story); +story.init(player); + +const panelStyle = { + shadowColor: 'rgba(0, 0, 0, 0.1)', + shadowBlur: 10, + shadowOffsetX: 4, + shadowOffsetY: 4, + fill: 'white', + cornerRadius: 4, + size: 9 +}; +const commonStyle = { + content: '$123,45', + position: 'tl', + padding: { top: 6, bottom: 6, left: 6, right: 6 }, + contentStyle: { + fontSize: 12, + fill: '#08979c' + } +}; + +const p1 = { + ...commonStyle, + panel: { + ...panelStyle + } +}; +const p2 = { + ...commonStyle, + triangleMode: 'concise', + panel: { + ...panelStyle, + cornerRadius: 0 + } +}; +const p3 = { + ...commonStyle, + triangleMode: 'concise', + panel: { + ...panelStyle, + fill: false, + stroke: 'white', + cornerRadius: 0, + size: 0 + } +}; +const p4 = { + ...commonStyle, + position: 'top', + panel: { + ...panelStyle, + square: true, + cornerRadius: 100, + size: 12 + } +}; + +const p5 = { + content: '123,45', + padding: { top: 3, bottom: 3, left: 12, right: 6 }, + position: 'tl', + contentStyle: { + fontSize: 12, + fill: '#08979c' + }, + panel: { + ...panelStyle, + cornerRadius: [0, 20, 20, 0] + }, + logoSymbol: { + symbolType: 'circle', + fill: 'red', + size: 'auto' + }, + logoText: '$', + logoTextStyle: { + fill: 'white', + fontSize: 12 + } +}; + +const p6 = { + content: '123,45', + position: 'tl', + padding: { top: 3, bottom: 3, left: 13, right: 8 }, + contentStyle: { + fontSize: 12, + fill: '#08979c' + }, + panel: { + ...panelStyle, + cornerRadius: [0, 0, 6, 0], + cornerType: 'bevel', + size: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [20, 'auto'], + cornerType: 'bevel' + }, + logoText: '🤡', + logoTextStyle: { + fill: 'white', + fontSize: 12 + } +}; + +[p1, p2, p3, p4, p5, p6].forEach((item, index) => { + story.addCharacter( + { + type: 'PopTip', + id: `poptip-${index}`, + zIndex: 1, + position: { + top: 100 + Math.floor(index / 3) * 120, + left: 50 + (index % 3) * 120 + }, + options: { + graphic: item + } + }, + { + sceneId: 'defaultScene', + actions: [ + { + startTime: 0, + action: 'appear', + payload: [ + { + animation: { + duration: 300, + easing: 'quadOut', + wave: 0.3 + } + } + ] + }, + { + startTime: 1000, + action: 'disappear', + payload: { + animation: { + duration: 300, + easing: 'aIn3' + } + } + } + ] + } + ); +}); + +player.play(1); + +window['story'] = story; +window['vstory'] = story; +``` diff --git a/docs/assets/examples/zh/character/story-label-item.md b/docs/assets/examples/zh/character/story-label-item.md new file mode 100644 index 00000000..8c4ba716 --- /dev/null +++ b/docs/assets/examples/zh/character/story-label-item.md @@ -0,0 +1,156 @@ +--- +category: examples +group: character +title: story-label-item +keywords: story-label-item +order: 1-0 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vstory/label-item.gif +--- + +# 叙事Label元素 + +`story-label-item` 是一种标注元素,专门用于在特定位置添加解释性文本或说明信息。与传统的直接在目标周围展示信息的方式不同,`story-label-item` 通过一条额外的连接线,将说明与其对应的目标元素连接起来。这种设计使得标注可以灵活地放置在目标周围的较大范围内,而不必局限于紧贴目标的边缘。 + +这种灵活性不仅提高了界面的美观性,还能有效避免信息重叠或遮挡,确保用户在浏览时可以清晰地看到标注内容。具体来说,`story-label-item` 可以根据界面的布局和设计需求,选择最佳的位置展示标注,无论是在目标的上方、下方、左侧还是右侧,甚至是在更远的地方,只需通过连接线清楚地指向目标即可。 + +此外,`story-label-item` 还支持多种样式和定制选项,开发者可以根据具体的应用场景调整其外观,以确保与整体设计风格的协调。这使得 `story-label-item` 成为一种非常实用的工具,广泛应用于数据可视化、用户说明、交互设计等多个领域,为用户提供更为直观和友好的信息传递体验。 + +## 代码演示 + +```javascript livedemo template=vstory +// 注册所有需要的内容 +VStory.registerAll(); +// 注册PopTip +VStory.registerLabelItem(); +VStory.registerLabelItemAction(); + +const story = new VStory.Story(null, { dom: CONTAINER_ID, background: '#18253A' }); +const player = new VStory.Player(story); +story.init(player); + +const l1 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor' +}; +const l2 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor', + titleBottom: 'this is the VStory label', + titleBottomStyle: { + fontSize: 10 + } +}; +const l3 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleSpace: [6, 6], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 12, + fill: 'black' + }, + titleTopPanelStyle: { + fill: 'white', + visible: true, + padding: { top: 3, bottom: 3 } + } +}; + +const l4 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleSpace: [6, 6], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 12, + fill: 'black' + }, + titleBottom: 'this is the VStory label', + titleBottomStyle: { + fontSize: 10, + fill: 'black' + }, + titleTopPanelStyle: { + fill: 'white', + visible: true, + padding: { top: 3, bottom: 3 } + }, + titleBottomPanelStyle: { + fill: 'white', + visible: true, + padding: { top: 3, bottom: 6 } + } +}; + +const l5 = { + contentOffsetX: 200, + contentOffsetY: -60, + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 12 + }, + titleTopPanelStyle: { + stroke: 'white', + visible: true + // padding: { top: 3, bottom: 3 } + }, + theme: 'simple' +}; + +[l1, l2, l3, l4, l5, l1, l2, l3, l4, l5].forEach((item, index) => { + story.addCharacter( + { + type: 'LabelItem', + id: `label-item-${index}`, + zIndex: 1, + position: { + top: 100 + Math.floor(index / 3) * 100, + left: 50 + (index % 3) * 230 + }, + options: { + graphic: item + } + }, + { + sceneId: 'defaultScene', + actions: [ + { + startTime: 0, + action: 'appear', + payload: [ + { + animation: { + duration: 1000, + easing: 'cubicIn', + symbolStartOuterType: Math.floor(index / 5) === 0 ? 'scale' : 'clipRange', + titleType: Math.floor(index / 5) === 0 ? 'move' : 'typewriter', + titlePanelType: index === 4 ? 'stroke' : 'scale' + } + } + ] + }, + { + startTime: 2000, + action: 'disappear', + payload: { + animation: { + duration: 700, + easing: 'cubicIn', + mode: Math.floor(index / 5) === 0 ? 'default' : 'scale' + } + } + } + ] + } + ); +}); + +player.play(1); + +window['story'] = story; +window['vstory'] = story; +``` diff --git a/docs/assets/examples/zh/works-show/unit-infographic.md b/docs/assets/examples/zh/infographic/unit-infographic.md similarity index 99% rename from docs/assets/examples/zh/works-show/unit-infographic.md rename to docs/assets/examples/zh/infographic/unit-infographic.md index d58d7dd9..0afcf6c9 100644 --- a/docs/assets/examples/zh/works-show/unit-infographic.md +++ b/docs/assets/examples/zh/infographic/unit-infographic.md @@ -1,6 +1,6 @@ --- category: examples -group: works-show +group: infographic title: unit-infographic keywords: unit-infographic order: 1-0 diff --git a/docs/assets/examples/zh/works-show/annotation-show.md b/docs/assets/examples/zh/works-show/annotation-show.md new file mode 100644 index 00000000..c20f985a --- /dev/null +++ b/docs/assets/examples/zh/works-show/annotation-show.md @@ -0,0 +1,542 @@ +--- +category: examples +group: works-show +title: annotation-show +keywords: annotation-show +order: 1-0 +cover: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/vstory/annotation-works.gif +--- + +# `标注能力` 作品展示 + +该作品展示了VStory提供的标注能力动画,展示丰富的标注组件,以及动画能力。 + +## 代码演示 + +```javascript livedemo template=vstory +// 注册所有需要的内容 +VStory.registerAll(); +// 注册Label +VStory.registerLabelItem(); +VStory.registerLabelItemAction(); +// 注册PopTip +VStory.registerPopTip(); +VStory.registerPopTipAction(); + +const story = new VStory.Story(null, { dom: CONTAINER_ID, width: 2000 / 2, height: 800 / 2, background: '#ebecf0', scaleX: 0.5, scaleY: 0.5 }); +const player = new VStory.Player(story); +story.init(player); + +const perSceneDuring = 3000; + +story.addCharacter({ + type: 'Rect', + id: `background`, + zIndex: 0, + position: { + left: 0, + top: 0, + width: 1080, + height: 720 + }, + options: { + graphic: { + fill: '#18253A', + }, + text: { + text: 'ANIMATE 1', + fontSize: 80, + fill: 'white', + textAlign: 'center', + fontWeight: 'bolder', + textBaseline: 'middle' + } + } +}, { + sceneId: 'defaultScene', + actions: [ + { + action: 'appear', + startTime: 0, + payload: [ + { + animation: { + duration: 300, + easing: 'linear', + effect: 'fade' + } + } + ] + }, + { + action: 'style', + startTime: perSceneDuring, + payload: [ + { + animation: { + duration: 200, + easing: 'linear', + }, + graphic: { + fill: '#2E6670', + }, + text: { + text: 'ANIMATE 2', + } + } + ] + } + ] +}); + +const panelStyle = { + shadowColor: 'rgba(0, 0, 0, 0.1)', + shadowBlur: 10, + shadowOffsetX: 4, + shadowOffsetY: 4, + fill: 'white', + cornerRadius: 8, + size: 18 +}; +const commonStyle = { + content: 'Hello Vis', + position: 'right', + padding: { top: 16, bottom: 16, left: 16, right: 16 }, + contentStyle: { + fontSize: 22, + fill: '#1F4C4B' + } +}; + +const poptipList = [ + { + x: 180, y: 130, type: 'PopTip', + options: { + ...commonStyle, + position: 'bl', + triangleMode: 'concise', + panel: { + ...panelStyle, + cornerRadius: 0 + } + } + }, + { + x: 180, y: 130, type: 'PopTip', + options: { + ...commonStyle, + position: 'tr', + contentStyle: { + fontSize: 16, + fill: 'white' + }, + triangleMode: 'concise', + panel: { + ...panelStyle, + cornerRadius: 0, + fill: 'red', + } + } + }, + { + x: 400, y: 100, type: 'PopTip', + options: { + ...commonStyle, + panel: { + ...panelStyle, + size: 0 + } + } + }, + { + x: 630, y: 100, type: 'PopTip', + options: { + ...commonStyle, + position: 'right', + contentStyle: { + fontSize: 22, + fill: 'white', + fontWeight: 'bolder' + }, + panel: { + ...panelStyle, + fill: 'red', + cornerRadius: 0, + size: 0 + } + } + }, + { + x: 850, y: 100, type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 23, right: 18 }, + position: 'right', + panel: { + ...panelStyle, + cornerRadius: [0, 0, 6, 0], + cornerType: 'bevel', + size: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [36, 'auto'], + cornerType: 'bevel' + }, + logoText: '🤡', + logoTextStyle: { + fill: 'white', + fontSize: 26 + } + } + }, + + + { + x: 120, y: 280, type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 23, right: 18 }, + position: 'bl', + panel: { + ...panelStyle, + cornerType: 'bevel', + size: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [36, 'auto'], + cornerType: 'bevel' + }, + logoText: '🤡', + logoTextStyle: { + fill: 'white', + fontSize: 26 + } + } + }, + { + x: 470, y: 280, type: 'PopTip', + options: { + ...commonStyle, + position: 'top', + panel: { + ...panelStyle + } + } + }, + { + x: 850, y: 240, type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 26, right: 12 }, + content: '123,45', + position: 'right', + panel: { + ...panelStyle, + cornerRadius: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [30, 'auto'] + }, + logoText: '¥', + logoTextStyle: { + fill: 'white', + fontSize: 28 + } + } + }, + + + { + x: 120, y: 460, type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 33, right: 18 }, + content: '123,45', + position: 'bl', + panel: { + ...panelStyle, + cornerRadius: [0, 100, 100, 0] + }, + logoSymbol: { + symbolType: 'circle', + fill: 'red', + size: 'auto' + }, + logoText: '¥', + logoTextStyle: { + fill: 'white', + fontSize: 28 + } + } + }, + { + x: 500, y: 560, type: 'PopTip', + options: { + ...commonStyle, + content: 'Hi 👋', + position: 'bottom', + panel: { + ...panelStyle, + square: true, + cornerRadius: 100, + size: 12 + } + } + }, + { + x: 860, y: 520, type: 'PopTip', + options: { + ...commonStyle, + contentStyle: { + fontSize: 22, + fill: 'wihte' + }, + triangleMode: 'concise', + panel: { + ...panelStyle, + fill: false, + stroke: 'white', + cornerRadius: 0, + size: 0 + } + } + }, + + + { + x: 270, y: 630, type: 'PopTip', + options: { + ...commonStyle, + panel: { + ...panelStyle, + cornerRadius: 100, + size: 0 + } + } + }, + { + x: 630, y: 630, type: 'PopTip', + options: { + ...commonStyle, + panel: { + ...panelStyle + } + } + }, +]; + +poptipList.forEach((item, i) => { + story.addCharacter({ + type: item.type, + id: `${item.type}-${i}`, + zIndex: 10, + position: { + left: item.x, + top: item.y, + }, + options: { + graphic: item.options + } + }, { + sceneId: 'defaultScene', + actions: [ + { + startTime: 300, + action: 'appear', + payload: [ + { + animation: { + duration: 300, + easing: 'quadOut', + wave: 0.3 + } + } + ] + }, + { + startTime: perSceneDuring / 3 * 2, + action: 'disappear', + payload: { + animation: { + duration: 300, + easing: 'aIn3' + } + } + }, + { + startTime: perSceneDuring + 500, + action: 'appear', + payload: [ + { + animation: { + duration: 300, + easing: 'quadOut', + } + } + ] + }, + { + startTime: perSceneDuring + perSceneDuring / 3 * 2, + action: 'disappear', + payload: { + animation: { + duration: 300, + easing: 'aIn3' + } + } + }, + ] + }) +}) + +const labelList = [ + { + x: 900, y: 360, + options: { + contentOffsetX: -300, + contentOffsetY: -100, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 22, + } + } + }, + { + x: 100, y: 670, + options: { + contentOffsetX: 300, + contentOffsetY: -100, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor', + titleBottom: 'this is the VStory label', + titleTopStyle: { + fontSize: 22, + }, + titleBottomStyle: { + fontSize: 16 + } + } + }, + { + x: 500, y: 560, + options: { + contentOffsetX: 300, + contentOffsetY: -100, + titleSpace: [6, 6], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 22, + fill: 'black' + }, + titleTopPanelStyle: { + fill: 'white', + visible: true, + padding: { top: 3, bottom: 3 } + } + } + }, + { + x: 500, y: 560, + options: { + contentOffsetX: -300, + contentOffsetY: -130, + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 22 + }, + titleTopPanelStyle: { + stroke: 'white', + visible: true + }, + theme: 'simple' + } + } +] + + +labelList.forEach((label, index) => { + story.addCharacter( + { + type: 'LabelItem', + id: `label-item-${index}`, + zIndex: 100, + position: { + top: label.y, + left: label.x + }, + options: { + graphic: label.options + } + }, + { + sceneId: 'defaultScene', + actions: [ + { + startTime: 300, + action: 'appear', + payload: [ + { + animation: { + duration: 1000, + easing: 'cubicIn', + symbolStartOuterType: 'scale', + titleType: 'typewriter', + titlePanelType: label.options.theme === 'simple' ? 'stroke' : 'scale' + } + } + ] + }, + { + startTime: perSceneDuring / 3 * 2, + action: 'disappear', + payload: { + animation: { + duration: 700, + easing: 'cubicIn', + mode: 'default' + } + } + }, + { + startTime: perSceneDuring, + action: 'appear', + payload: [ + { + animation: { + duration: 1000, + easing: 'cubicIn', + symbolStartOuterType: 'clipRange', + titleType: 'move', + titlePanelType: label.options.theme === 'simple' ? 'stroke' : 'scale' + } + } + ] + }, + { + startTime: perSceneDuring + perSceneDuring / 3 * 2, + action: 'disappear', + payload: { + animation: { + duration: 700, + easing: 'cubicIn', + mode: 'scale' + } + } + } + ] + } + ); +}) + +player.play(1); + +window['story'] = story; +window['vstory'] = story; +``` diff --git a/docs/assets/guide/en/tutorial_docs/Getting_Started.md b/docs/assets/guide/en/tutorial_docs/Getting_Started.md index 330c0623..b34338ce 100644 --- a/docs/assets/guide/en/tutorial_docs/Getting_Started.md +++ b/docs/assets/guide/en/tutorial_docs/Getting_Started.md @@ -20,7 +20,7 @@ yarn add @visactor/vstory ### Using CDN -You can also get the built VStory file through CDN. Add the following code to the ` diff --git a/docs/assets/guide/zh/tutorial_docs/Getting_Started.md b/docs/assets/guide/zh/tutorial_docs/Getting_Started.md index e7fc1290..57310ae3 100644 --- a/docs/assets/guide/zh/tutorial_docs/Getting_Started.md +++ b/docs/assets/guide/zh/tutorial_docs/Getting_Started.md @@ -20,7 +20,7 @@ yarn add @visactor/vstory ### 使用 CDN -你还可以通过 CDN 获取构建好的 VShart 文件。将以下代码添加到 HTML 文件的 ` diff --git a/packages/vstory-player/src/processor/component/common/style.ts b/packages/vstory-player/src/processor/component/common/style.ts index 2e9f2938..360eac43 100644 --- a/packages/vstory-player/src/processor/component/common/style.ts +++ b/packages/vstory-player/src/processor/component/common/style.ts @@ -72,6 +72,11 @@ export class CommonStyleActionProcessor extends ActionProcessorItem { } } if (text && textStyle) { + // TODO 鲁棒性,考虑更兼容的方式 + // 特殊处理textConfig + if (textStyle.text && (text.attribute as any).textConfig) { + textStyle.textConfig = [{ ...((text.attribute as any).textConfig || [])[0], text: textStyle.text }]; + } text.animate().to(textStyle, duration, easing as EasingType); } } diff --git a/packages/vstory/demo/src/App.tsx b/packages/vstory/demo/src/App.tsx index db267d88..3993adc1 100644 --- a/packages/vstory/demo/src/App.tsx +++ b/packages/vstory/demo/src/App.tsx @@ -33,6 +33,7 @@ import { Pie1 } from './demos/arrange/Pie1'; import { UnitTemplate2 } from './demos/templates/unit-template2'; import { PopTipAnimate } from './demos/component/poptip'; import { LabelItemAnimate } from './demos/component/label-item'; +import { LabelWorks } from './demos/works/label'; type MenusType = ( | { @@ -136,6 +137,10 @@ const App = () => { name: 'VScreen', component: VScreen }, + { + name: 'LabelComponent', + component: LabelWorks + }, { name: 'SomeCharts', component: SomeCharts diff --git a/packages/vstory/demo/src/demos/works/label.tsx b/packages/vstory/demo/src/demos/works/label.tsx new file mode 100644 index 00000000..afb4aa4f --- /dev/null +++ b/packages/vstory/demo/src/demos/works/label.tsx @@ -0,0 +1,600 @@ +import React, { createRef, useEffect } from 'react'; +import { Player, Story, initVR, registerGraphics, registerCharacters } from '../../../../../vstory-core/src'; +import { registerVComponentAction, registerVChartAction } from '../../../../../vstory-player/src'; +import { encodeToVideo } from '../../../../../vstory-player/src/encode'; +import { registerAll } from '../../../../src'; +import { + registerLabelItem, + registerLabelItemAction, + registerPopTip, + registerPopTipAction +} from '../../../../../vstory-external/src'; + +registerAll(); +registerLabelItem(); +registerLabelItemAction(); +registerPopTip(); +registerPopTipAction(); + +export const LabelWorks = () => { + const id = 'LabelWorks'; + + useEffect(() => { + const container = document.getElementById(id); + const canvas = document.createElement('canvas'); + container?.appendChild(canvas); + + const story = new Story(null, { + canvas, + // canvas的宽高,设置后仅对canvas大小生效,不影响内容,如果内容过大会被裁剪 + width: 1080 / 2, + height: 720 / 2, + background: 'transparent', + // 对内容的缩放,不影响canvas的宽高 + scaleX: 0.5, + scaleY: 0.5 + }); + const player = new Player(story); + story.init(player); + + const perSceneDuring = 3000; + + story.addCharacter( + { + type: 'Rect', + id: `background`, + zIndex: 0, + position: { + left: 0, + top: 0, + width: 1080, + height: 720 + }, + options: { + graphic: { + fill: '#18253A' + }, + text: { + text: 'ANIMATE 1', + fontSize: 80, + fill: 'white', + textAlign: 'center', + fontWeight: 'bolder', + textBaseline: 'middle' + } + } + }, + { + sceneId: 'defaultScene', + actions: [ + { + action: 'appear', + startTime: 0, + payload: [ + { + animation: { + duration: 300, + easing: 'linear', + effect: 'fade' + } + } + ] + }, + { + action: 'style', + startTime: perSceneDuring, + payload: [ + { + animation: { + duration: 200, + easing: 'linear' + }, + graphic: { + fill: '#2E6670' + }, + text: { + text: 'ANIMATE 2' + } + } + ] + }, + { + action: 'disappear', + startTime: perSceneDuring * 2, + payload: [ + { + animation: { + duration: 300, + easing: 'linear' + } + } + ] + } + ] + } + ); + + const panelStyle = { + shadowColor: 'rgba(0, 0, 0, 0.1)', + shadowBlur: 10, + shadowOffsetX: 4, + shadowOffsetY: 4, + fill: 'white', + cornerRadius: 8, + size: 18 + }; + const commonStyle = { + content: 'Hello Vis', + position: 'right', + padding: { top: 16, bottom: 16, left: 16, right: 16 }, + contentStyle: { + fontSize: 22, + fill: '#1F4C4B' + } + }; + + const poptipList = [ + { + x: 180, + y: 130, + type: 'PopTip', + options: { + ...commonStyle, + position: 'bl', + triangleMode: 'concise', + panel: { + ...panelStyle, + cornerRadius: 0 + } + } + }, + { + x: 180, + y: 130, + type: 'PopTip', + options: { + ...commonStyle, + position: 'tr', + contentStyle: { + fontSize: 16, + fill: 'white' + }, + triangleMode: 'concise', + panel: { + ...panelStyle, + cornerRadius: 0, + fill: 'red' + } + } + }, + { + x: 400, + y: 100, + type: 'PopTip', + options: { + ...commonStyle, + panel: { + ...panelStyle, + size: 0 + } + } + }, + { + x: 630, + y: 100, + type: 'PopTip', + options: { + ...commonStyle, + position: 'right', + contentStyle: { + fontSize: 22, + fill: 'white', + fontWeight: 'bolder' + }, + panel: { + ...panelStyle, + fill: 'red', + cornerRadius: 0, + size: 0 + } + } + }, + { + x: 850, + y: 100, + type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 23, right: 18 }, + position: 'right', + panel: { + ...panelStyle, + cornerRadius: [0, 0, 6, 0], + cornerType: 'bevel', + size: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [36, 'auto'], + cornerType: 'bevel' + }, + logoText: '🤡', + logoTextStyle: { + fill: 'white', + fontSize: 26 + } + } + }, + + { + x: 120, + y: 280, + type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 23, right: 18 }, + position: 'bl', + panel: { + ...panelStyle, + cornerType: 'bevel', + size: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [36, 'auto'], + cornerType: 'bevel' + }, + logoText: '🤡', + logoTextStyle: { + fill: 'white', + fontSize: 26 + } + } + }, + { + x: 470, + y: 280, + type: 'PopTip', + options: { + ...commonStyle, + position: 'top', + panel: { + ...panelStyle + } + } + }, + { + x: 850, + y: 240, + type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 26, right: 12 }, + content: '123,45', + position: 'right', + panel: { + ...panelStyle, + cornerRadius: 0 + }, + logoSymbol: { + symbolType: 'rect', + fill: 'red', + size: [30, 'auto'] + }, + logoText: '¥', + logoTextStyle: { + fill: 'white', + fontSize: 28 + } + } + }, + + { + x: 120, + y: 460, + type: 'PopTip', + options: { + ...commonStyle, + padding: { top: 16, bottom: 16, left: 33, right: 18 }, + content: '123,45', + position: 'bl', + panel: { + ...panelStyle, + cornerRadius: [0, 100, 100, 0] + }, + logoSymbol: { + symbolType: 'circle', + fill: 'red', + size: 'auto' + }, + logoText: '¥', + logoTextStyle: { + fill: 'white', + fontSize: 28 + } + } + }, + { + x: 500, + y: 560, + type: 'PopTip', + options: { + ...commonStyle, + content: 'Hi 👋', + position: 'bottom', + panel: { + ...panelStyle, + square: true, + cornerRadius: 100, + size: 12 + } + } + }, + { + x: 860, + y: 520, + type: 'PopTip', + options: { + ...commonStyle, + contentStyle: { + fontSize: 22, + fill: 'wihte' + }, + triangleMode: 'concise', + panel: { + ...panelStyle, + fill: false, + stroke: 'white', + cornerRadius: 0, + size: 0 + } + } + }, + + { + x: 270, + y: 630, + type: 'PopTip', + options: { + ...commonStyle, + panel: { + ...panelStyle, + cornerRadius: 100, + size: 0 + } + } + }, + { + x: 630, + y: 630, + type: 'PopTip', + options: { + ...commonStyle, + panel: { + ...panelStyle + } + } + } + ]; + + poptipList.forEach((item, i) => { + story.addCharacter( + { + type: item.type, + id: `${item.type}-${i}`, + zIndex: 10, + position: { + left: item.x, + top: item.y + }, + options: { + graphic: item.options + } + }, + { + sceneId: 'defaultScene', + actions: [ + { + startTime: 300, + action: 'appear', + payload: [ + { + animation: { + duration: 300, + easing: 'quadOut', + wave: 0.3 + } + } + ] + }, + { + startTime: (perSceneDuring / 3) * 2, + action: 'disappear', + payload: { + animation: { + duration: 300, + easing: 'aIn3' + } + } + }, + { + startTime: perSceneDuring + 500, + action: 'appear', + payload: [ + { + animation: { + duration: 300, + easing: 'quadOut' + } + } + ] + }, + { + startTime: perSceneDuring + (perSceneDuring / 3) * 2, + action: 'disappear', + payload: { + animation: { + duration: 300, + easing: 'aIn3' + } + } + } + ] + } + ); + }); + + const labelList = [ + { + x: 900, + y: 360, + options: { + contentOffsetX: -300, + contentOffsetY: -100, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 22 + } + } + }, + { + x: 100, + y: 670, + options: { + contentOffsetX: 300, + contentOffsetY: -100, + titleSpace: [0, 3], + titleTop: 'Powered By VisActor', + titleBottom: 'this is the VStory label', + titleTopStyle: { + fontSize: 22 + }, + titleBottomStyle: { + fontSize: 16 + } + } + }, + { + x: 500, + y: 560, + options: { + contentOffsetX: 300, + contentOffsetY: -100, + titleSpace: [6, 6], + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 22, + fill: 'black' + }, + titleTopPanelStyle: { + fill: 'white', + visible: true, + padding: { top: 3, bottom: 3 } + } + } + }, + { + x: 500, + y: 560, + options: { + contentOffsetX: -300, + contentOffsetY: -130, + titleTop: 'Powered By VisActor', + titleTopStyle: { + fontSize: 22 + }, + titleTopPanelStyle: { + stroke: 'white', + visible: true + }, + theme: 'simple' + } + } + ]; + + labelList.forEach((label, index) => { + story.addCharacter( + { + type: 'LabelItem', + id: `label-item-${index}`, + zIndex: 100, + position: { + top: label.y, + left: label.x + }, + options: { + graphic: label.options + } + }, + { + sceneId: 'defaultScene', + actions: [ + { + startTime: 300, + action: 'appear', + payload: [ + { + animation: { + duration: 1000, + easing: 'cubicIn', + symbolStartOuterType: 'scale', + titleType: 'typewriter', + titlePanelType: label.options.theme === 'simple' ? 'stroke' : 'scale' + } + } + ] + }, + { + startTime: (perSceneDuring / 3) * 2, + action: 'disappear', + payload: { + animation: { + duration: 700, + easing: 'cubicIn', + mode: 'default' + } + } + }, + { + startTime: perSceneDuring, + action: 'appear', + payload: [ + { + animation: { + duration: 1000, + easing: 'cubicIn', + symbolStartOuterType: 'clipRange', + titleType: 'move', + titlePanelType: label.options.theme === 'simple' ? 'stroke' : 'scale' + } + } + ] + }, + { + startTime: perSceneDuring + (perSceneDuring / 3) * 2, + action: 'disappear', + payload: { + animation: { + duration: 700, + easing: 'cubicIn', + mode: 'scale' + } + } + } + ] + } + ); + }); + + player.play(0); + + return () => { + story.release(); + }; + }, []); + + return
; +};