diff --git a/.trae/documents/auto-flow.solo.md b/.trae/documents/auto-flow.solo.md deleted file mode 100644 index d0825567f1..0000000000 --- a/.trae/documents/auto-flow.solo.md +++ /dev/null @@ -1,34 +0,0 @@ -# Auto Flow(串行编排)Solo 使用说明 - -- 入口文件:`./.trae/jobs/auto-flow.md` -- 流程:分支预检查 → 自动化测试 → Rush 变更日志 → 创建 PR - -## 参数 -- `baseBranch`:默认 `develop` -- `lang`:`zh|en`,默认 `zh` -- `labels`:默认 `[changelog, test]` -- `topic`:可选;用于 PR 标题优化(未提供时用当前分支名) -- `message`:可选;作为 PR body 摘要 -- `bumpType`:默认 `auto` -- `notCommit`:默认 `true` -- `head`:可选;未提供时自动推导当前分支 - -## 前置 -- 若需自动创建 PR 或聚合 Issue 标题,请先设置 `GITHUB_TOKEN`(参考 `./.trae/github-token.local.md`) - -## 使用(Solo) -- 在聊天中发起:“执行 Auto Flow(.trae/jobs/auto-flow.md)”,可附加: - - `topic: feature-legend` - - `message: 'docs: chore(trae): add auto-flow'` - - `mode: browser`(默认以浏览器创建 PR,输出可复制内容与 compare URL) - - (可选)`openBrowser: true`(自动打开浏览器) - -## 输出 -- `autotest_report`:`./.trae/jobs/autotest.report.local.md` -- `rush_change_entries`:`common/changes/**` -- `pr_url`:PR 链接(若已创建) - -## 人工检查 -- 单测后检查报告与覆盖率摘要 -- 变更日志后检查 `common/changes/**` -- PR 前检查标题与正文信息;如需补充 body,请人工完善后再创建 diff --git a/.trae/documents/auto-test.solo.md b/.trae/documents/auto-test.solo.md deleted file mode 100644 index 1508ed6f56..0000000000 --- a/.trae/documents/auto-test.solo.md +++ /dev/null @@ -1,60 +0,0 @@ -# Autotest(差异驱动单元测试生成)Solo 使用说明 - -- 入口文件:`./.trae/jobs/auto-test.md` -- 作用:根据 `develop...HEAD` 的代码差异,自动生成/更新测试用例与快照,并运行覆盖率与报告 - -## 参数 -- `sinceBranch`:默认 `develop` -- `project`:默认 `auto`(自动识别变更包);可指定如 `@visactor/vchart` -- `mode`:`full`(默认) -- `noSnapshot`:是否跳过快照,默认 `false` -- `onlyNew`:仅生成新的自动化区块,默认 `false` -- `reportFormat`:`md|json`,默认 `md` -- `applyManualOverrides`:应用人工覆写,默认 `true` -- `replaceAutogen`:允许替换已有 `autogen:` 块,默认 `false` -- `dryRun`:仅预览不写文件,默认 `false` -- `preview`:是否预览模式,默认 `false` -- `stopOnError`:遇错停止,默认 `true` -- `focusChangedOnly`:仅聚焦变更,默认 `true` -- `snapshotStrategy`:`combined`(默认) -- `tempReportPath`:默认 `./.trae/output/autotest.report.local.md` -- `mockDefaults`:默认 `time=fixed(2020-01-01T00:00:00Z)`、`random=seed(42)` - -## 使用(Solo) -- 最简:在聊天中发起“执行 Auto Test Job(.trae/jobs/auto-test.md)” -- 指定包:`project: '@visactor/vchart'` -- 指定输出格式:`reportFormat: 'json'` - -## 输出 -- `test_files`:新增/更新的 `.test.ts` -- `snapshots`:快照文件 -- `coverage_report`:覆盖率摘要 -- `manual_nodes`:需人工处理的用例占位 -- `temp_markdown_report`:临时报告(默认写入 `./.trae/output/autotest.report.local.md`) - -## 成功标准 -- `tests_generated_for_changed_exports` -- `compile_without_errors` -- `coverage_increase_or_maintained` - -## 人工覆写示例 -```yaml -manual_overrides: - - target: packages/vchart/src/util/color.ts#parseColor - mocks: - date: fixed(2020-01-01T00:00:00Z) - random: seed(42) - inputs: - - { args: ['#ff0000'], desc: '基本路径' } - - { args: ['invalid'], desc: '异常路径' } - asserts: - - { expect: 'toEqual', value: { r: 255, g: 0, b: 0 } } -``` - -## 运行与诊断 -- 我会自动执行 `rush run -p -s test` 与 `test-cov` -- TypeScript 诊断与覆盖率结果会写入临时报告以便复核 - -## 注意事项 -- 若差异范围为空,建议指定 `project` 以运行目标包测试 -- 对低覆盖模块,建议补充手动测试并复跑 Auto Test 以提升覆盖率 diff --git a/.trae/documents/changelog-rush-smart.solo.md b/.trae/documents/changelog-rush-smart.solo.md deleted file mode 100644 index 6d6819b84e..0000000000 --- a/.trae/documents/changelog-rush-smart.solo.md +++ /dev/null @@ -1,24 +0,0 @@ -# Changelog(Rush 智能变更日志)Solo 使用说明 - -- 入口文件:`./.trae/jobs/changelog-rush-smart.md` -- 作用:对齐并增强 `change-all.ts`,生成 Rush 变更条目(`common/changes/**`) - -## 参数 -- `sinceBranch`:默认 `develop` -- `message`:可选;若为空自动生成富摘要 -- `bumpType`:`auto|major|minor|patch`,默认 `auto` -- `notCommit`:是否跳过 `git commit`,默认 `true` -- `githubToken`:可选,聚合 Issue 标题时需要 - -## 使用(Solo) -- 在聊天中发起:“执行 Changelog Job(.trae/jobs/changelog-rush-smart.md)”,可附加: - - `message: 'docs: chore(trae): add auto-flow'` - - `bumpType: patch` - -## 输出 -- `rush_change_entries`:新增的变更条目路径集合 -- `computed_bump_type`:自动判定的 bump 类型 -- `final_message`:最终用于 `rush change` 的消息 - -## 人工检查 -- 复核 `common/changes/**` 的内容(包名、类型、comment),必要时重新执行并覆盖 `message/bumpType` diff --git a/.trae/documents/create-branch.solo.md b/.trae/documents/create-branch.solo.md deleted file mode 100644 index 2e1f20ac18..0000000000 --- a/.trae/documents/create-branch.solo.md +++ /dev/null @@ -1,20 +0,0 @@ -# Create Branch Job(Solo 使用说明) - -- 入口文件:`./.trae/jobs/create-branch.md` -- 适用场景:需要在本地通过 Job 统一创建开发分支 - -## 参数 -- `baseBranch`:默认 `develop` -- `branchPrefix`:默认 `chore/trae` -- `topic`:必填,主题描述(例如 `feature-legend`) -- `useDateSuffix`:是否追加日期后缀,默认 `true` - -## 使用(Solo) -- 在聊天中发起:“执行 Create Branch Job(.trae/jobs/create-branch.md)”,并传入: - - `topic: feature-legend` - -## 输出 -- `branch_name`:生成的分支名 - -## 人工检查 -- 执行完成后:`git status` 确认当前分支与工作树状态 diff --git a/.trae/documents/pr-create.solo.md b/.trae/documents/pr-create.solo.md deleted file mode 100644 index d3e0f8c9ef..0000000000 --- a/.trae/documents/pr-create.solo.md +++ /dev/null @@ -1,52 +0,0 @@ -# PR 创建 Job(Solo 使用说明) - -- 入口文件:`./.trae/jobs/pr-create.md` -- 作用:依据仓库 PR 模版生成正文并创建 PR - -## 参数 -- `base`:默认 `develop` -- `head`:可选;未提供时自动推导当前分支 -- `title`:必填;PR 标题 -- `lang`:`zh|en`,默认 `zh` -- `labels`:可选标签数组 -- `draft`:是否草稿,默认 `false` -- `useGhCli`:是否使用 `gh` 创建,默认 `true` -- `mode`:`auto|gh|rest|browser`(默认 `auto`,优先浏览器免安装) -- `localBodyFile`:是否生成本地可复制正文文件(默认 `false`) -- `openBrowser`:是否自动打开 compare URL(默认 `true`) -- `commitBeforeCreate`:创建 PR 前是否自动提交未提交变更(默认 `false`) -- `commitMessage`:自动提交的 commit 消息(默认 `chore: auto commit before pr`) -- `commitAllowEmpty`:是否允许空提交(默认 `false`) -- `pushAfterCommit`:提交后是否自动推送当前分支(默认 `true`) -- `commitMessageStrategy`:提交信息生成策略(`auto|topic|manual`,默认 `auto`) - - `auto`:按变更内容自动判定类型(`docs|test|chore`)、作用域(包名或顶层目录),主题取 `message` 首行或自动摘要 - - `topic`:主题优先使用 `title`/外层 `topic` - - `manual`:使用 `commitMessage` - -## 前置(登录/令牌) -- 优先方案:使用 GitHub CLI(`gh`)并已登录 → 不需要额外令牌 -- 备选方案:无 `gh` 时提供 `GITHUB_TOKEN`(参见 `./.trae/github-token.local.md`) -- 兜底方案:生成浏览器 compare URL,使用你浏览器的登录态手动创建 PR - -## 使用(Solo) -- 在聊天中发起:“执行 PR Job(.trae/jobs/pr-create.md)”,并传: - - `title: '[Auto] feature-legend'` - - (可选)`head: chore/trae-feature-legend-20251222-1030` - - (可选)`mode: auto|gh|rest|browser`(默认 `auto`) - - (可选)`localBodyFile: true|false`(默认 `false`) - - (可选)`openBrowser: true|false`(默认 `true`) - - (可选)`commitBeforeCreate: true`、`commitMessage: 'chore: auto commit before pr'`、`pushAfterCommit: true` - - (可选)`commitMessageStrategy: auto` - -## 正文准备 -- 若 `message` 已包含摘要与关联信息,可直接作为 body -- 若需要补充,请先人工完善 body 文本,再执行创建(不生成临时文件) - -## 输出 -- `pr_url`:创建的 PR 链接(`gh/rest`) -- `compare_url`:浏览器 compare 页面(`browser`) -- `generated_title`:建议标题(便于复制) -- `generated_body_preview`:建议正文(便于复制) - -## 人工检查 -- 提交前检查标题、关联链接与 Changelog 摘要是否完整 diff --git a/.trae/jobs/README.md b/.trae/jobs/README.md deleted file mode 100644 index 3eef56aedd..0000000000 --- a/.trae/jobs/README.md +++ /dev/null @@ -1,80 +0,0 @@ -# 通过说明文件驱动执行 - -## 目的 - -- 不依赖“工作流模版”概念,仅在仓库中放置一个说明文件,描述任务与参数;我将按说明执行并回传报告。 - -## 放置位置 - -- 目录:`.trae/jobs/` -- 文件:建议使用 `*.request.md` 或 `*.request.json`,便于版本化与审阅。 - -## 通用字段 - -- `Task`:任务标识,例如 `Auto Test (diff-with-develop)`。 -- `Parameters`:运行参数,例如 `sinceBranch`、`project`、`mode`、`noSnapshot`、`onlyNew`、`reportFormat`、`tempReportPath`。 -- `ExecutionHints`(可选):执行提示,如是否跳过快照、是否仅分析、不写补丁、选择包。 -- `StepsOverride`(可选):覆盖默认执行步骤的命令或动作(如自定义 diff 命令)。 - -## 示例(Markdown 请求) - -``` -# Task -Auto Test (diff-with-develop) - -# Parameters -sinceBranch: develop -project: '' -mode: full -noSnapshot: false -onlyNew: false -reportFormat: md - -# ExecutionHints -- skipWrite: false -- stopOnError: true - -# StepsOverride -- git fetch --all --prune -- git diff --name-status --diff-filter=AMR develop...HEAD -- rush run -s test -- rush run -s test-cov -``` - -## 使用方式 - -- 推荐入口文件:`.trae/jobs/auto-test.md`(已提供,含参数、步骤、人工覆写与成功标准) -- 最简用法(默认参数):在聊天中发起“执行 Auto Test Job(.trae/jobs/auto-test.md)”。 -- 可选覆盖参数:`project=@visactor/vchart-theme`、`reportFormat=json`、`replaceAutogen=true` 等。 -- 我将按 `.trae/jobs/auto-test.md` 的步骤顺序执行:采集差异、分析缺口、生成/更新测试(含函数级注释)、运行覆盖率、生成报告、插入人工节点。 - -## 结果与报告 - -- 报告以 `reportFormat` 指定(`md` 或 `json`)。 -- 默认临时报告写入 `./.trae/output/autotest.report.local.md`(可通过 `tempReportPath` 覆盖)。 -- 我会附带执行日志摘要、受影响包、生成/跳过的测试、覆盖率与人工节点清单。 - -## 旧方案清理 - -- 旧的“工作流模版”文件与文档已移除: - - `.trae/workflows/autotest.diff-with-develop.json` - - `docs/autotest-workflow.md` -- 现仅保留 Job 文件方案(`.trae/jobs/auto-test.md`)。 - -## 默认参数(参考) - -- `sinceBranch=develop` -- `project=auto`(自动按 diff 识别变更包) -- `mode=full` -- `noSnapshot=false` -- `onlyNew=false` -- `reportFormat=md` -- `applyManualOverrides=true` -- `replaceAutogen=false` -- `dryRun=false` -- `preview=false` -- `stopOnError=true` -- `focusChangedOnly=false` -- `snapshotStrategy=combined` -- `tempReportPath=./.trae/output/autotest.report.local.md` -- `mockDefaults: time=fixed(2020-01-01T00:00:00Z), random=seed(42)` diff --git a/.trae/jobs/auto-flow.md b/.trae/jobs/auto-flow.md deleted file mode 100644 index 015eb762bf..0000000000 --- a/.trae/jobs/auto-flow.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -job: release-prep-pipeline -intent: prepare-release -version: v1 -domain: pipeline -runner: trae-solo -parameters: - baseBranch: develop - lang: zh - labels: - - changelog - - test - topic: '' - message: '' - bumpType: auto - notCommit: true - head: '' - mode: auto - commitBeforeFlow: true - commitAllowEmpty: false - pushAfterCommit: true - commitMessageStrategy: auto - enforceCommit: true - commitRetry: 1 -required_parameters: [] -outputs: - - autotest_report - - rush_change_entries - - pr_url -success_criteria: - - flow_completed ---- - -# Auto Flow Job(分支 → 单测 → 变更日志 →PR 串行编排) - -## 参数检查 - -- 分支参数 `head` 可选:若未提供,将通过 `git rev-parse --abbrev-ref HEAD` 推导当前分支 -- 建议提供 `topic` 以优化 PR 标题;未提供时将回退为当前分支名 - -## 步骤 - -1. 分支预检查 - -- 运行 `git rev-parse --abbrev-ref HEAD` 获取当前分支作为 `head` -- 确认当前分支不是 `main`/`develop`,且工作树状态符合提交规范 -- 人工检查点:如不在开发分支,请先自行创建并切换到正确分支 - - 1.1 自动提交未提交变更(当 `commitBeforeFlow==true`) - -- 检查工作树:`git status --porcelain` -- 若存在未提交变更: - - `git add --all` - - 生成提交信息(按 `commitMessageStrategy`): - - `auto`:类型 `chore`;作用域为顶层或包名(如 `vchart`);主题为 `sync changes before Auto Flow` - - 最终示例:`chore(vchart): sync changes before Auto Flow` - - 运行 `git commit {{#commitAllowEmpty}}--allow-empty{{/commitAllowEmpty}} -m ""` - - 若 `pushAfterCommit==true`:`git push -u origin {{head}}` - - 提交后校验(当 `enforceCommit==true`): - - 运行 `git status --porcelain`,若非空则视为失败;进行最多 `commitRetry` 次重试(`git add --all && git commit -m ''`),仍失败则中止流程并提示处理 -- 若 `commitBeforeFlow==false` 且存在未提交变更:直接失败并提示先完成提交 - -2. 运行差异驱动单测 - -- 执行 Job:`.trae/jobs/auto-test.md` -- 传参:`sinceBranch={{baseBranch}}`(其余沿用默认) -- 接收输出:`autotest_report=.trae/output/autotest.report.local.md` -- 人工检查点:打开临时报告,确认新增/更新测试与覆盖率 - -3. 生成 Rush 变更日志 - -- 执行 Job:`.trae/jobs/changelog-rush-smart.md` -- 传参:`sinceBranch={{baseBranch}}`、`message={{message}}`、`bumpType={{bumpType}}`、`notCommit={{notCommit}}` -- 接收输出:`rush_change_entries` -- 人工检查点:检查 `common/changes/**` 条目与摘要 - -4. 创建 PR - -- 执行 Job:`.trae/jobs/pr-create.md` -- 传参: - - `base={{baseBranch}}` - - `head={{head}}` - - `title='[Auto] {{topic || head}}'` - - `lang={{lang}}` - - `labels={{labels}}` - - `message={{message}}`(用于正文摘要) - - `bumpType={{bumpType}}` - - `mode={{mode}}`(auto 优先 gh → token → 浏览器 URL) - - `commitBeforeCreate=false`(已在 1.1 阶段完成自动提交) -- 接收输出:`pr_url` -- 人工检查点:最终确认并提交 - -5. 完成 - -- 标记 `flow_completed`,返回 `autotest_report`、`rush_change_entries` 与 `pr_url` diff --git a/.trae/jobs/auto-test.md b/.trae/jobs/auto-test.md deleted file mode 100644 index 4d556199ee..0000000000 --- a/.trae/jobs/auto-test.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -job: unit-test-autogen -intent: generate-unit-tests-from-diff -version: v1 -domain: testing -runner: trae-solo -parameters: - sinceBranch: develop - project: auto - mode: full - noSnapshot: false - onlyNew: false - reportFormat: md - applyManualOverrides: true - replaceAutogen: true - dryRun: false - preview: false - stopOnError: true - focusChangedOnly: false - snapshotStrategy: combined - tempReportPath: .trae/output/autotest.report.local.md - mockDefaults: - time: fixed(2020-01-01T00:00:00Z) - random: seed(42) -constraints: - framework: jest-ts-jest - layout: __tests__/*.test.ts - comments: function-level-jsdoc -outputs: - - test_files - - snapshots - - coverage_report - - manual_nodes - - temp_markdown_report -success_criteria: - - tests_generated_for_changed_exports - - compile_without_errors - - coverage_increase_or_maintained -manual_overrides: [] ---- - -# Auto Test Job(差异驱动单元测试自动生成) - -## 步骤 - -1. 差异采集 - -- 运行 `git fetch --all --prune` -- 运行 `git diff --name-status --diff-filter=AMR {{sinceBranch}}...HEAD` -- 对每个变更文件,运行 `git diff --unified=0 {{sinceBranch}}...HEAD ` 获取行级差异 - -2. 影响分析 - -- 识别导出符号、类型签名与逻辑分支;在包内搜索已有 `__tests__` 及缺口 - -3. 测试生成 - -- 在 `__tests__` 下创建或更新 `.test.ts` 文件;为每个 `describe/it` 添加函数级注释(JSDoc,说明目的、前置/输入、断言点) -- 策略: - - 纯函数/工具:正常/边界/异常分支 - - 主题 JSON:`toMatchSnapshot()` + 关键字段断言(颜色、字体、间距) - - 转换器:代表性输入,断言输出结构与关键键值;必要时增量快照 -- Mock/Spy:固定时间与随机数;隔离外部依赖(网络/FS) -- 自动化区块命名规则: - - `describe('autogen:/::')` - - `it('autogen::')` - -4. 放置与命名 - -- `src/foo.ts` → `__tests__/foo.test.ts`;若已有则增量插入新的自动化区块 -- 导入路径优先使用公开 API(例如 `src/index.ts`) - -5. 执行与覆盖率 - -- 若指定 `project`:`rush run -p {{project}} -s test` 与 `test-cov` -- 未指定则按变更包批量执行上述命令 - -6. 诊断与报告 - -- TypeScript 诊断:收集编译错误并在报告中标注阻断项 -- 报告输出(`{{reportFormat}}`):列出变更文件 → 新增/更新测试 → 通过/失败 → 覆盖率增量 → 人工节点清单 -- 临时报告写入:将本次执行结果以 Markdown 形式写入 `{{tempReportPath}}` - - - 必含内容: - - 变更摘要(文件列表与关键行级片段定位) - - 新增/更新测试用例与断言点说明 - - 运行结果(套件/用例通过统计、覆盖率摘要、TS 诊断) - - 重点一致性问题与潜在错误点(类型/注释一致性、契约风险、默认值依赖、测试桩稳定性) - - 建议与后续动作(文档补充、契约确认、健壮性增强) - - 示例结构: - - ```md - # Autotest 临时报告 - - ## 变更摘要 - - ## 行级差异(关键片段) - - ## 新增/更新的测试 - - ## 运行结果 - - ## 一致性与潜在风险(重点) - - ## 建议与后续动作 - ``` - -7. 人工节点与二次执行 - -- 初次生成时对不明确 Mock/快照的用例插入占位并标记:`it('autogen:MANUAL_REQUIRED:')` 与 `test.skip(...)` -- 二次执行流程: - - 在本文件 `manual_overrides` 段中添加结构化覆写策略(见下例)或直接编辑测试文件中的占位并移除 `skip` - - 默认不覆盖人工命名块(不含 `autogen:` 前缀);仅增量生成缺失的自动化区块 - - 若 `replaceAutogen=true`,允许替换已有 `autogen:` 区块 - -## manual_overrides 示例 - -```yaml -manual_overrides: - - target: packages/vchart-theme/src/foo.ts#exportedFn - mocks: - date: fixed(2020-01-01T00:00:00Z) - random: seed(42) - external: "jest.mock('@pkg/bar', () => ({ /* ... */ }))" - inputs: - - { args: [1, 2], desc: '正常路径' } - - { args: [null], desc: '异常路径' } - asserts: - - { expect: 'toEqual', value: { ok: true } } -``` - -## 执行(Solo 模式) - -- 最简用法(使用默认参数):在聊天中发起“执行 Auto Test Job(.trae/jobs/auto-test.md)”。 -- 可选覆盖参数示例:`project=@visactor/vchart-theme`、`reportFormat=json`、`replaceAutogen=true`。 -- 我将按上述步骤顺序执行,并返回报告与人工节点处理结果。 -- 临时报告路径可通过 `tempReportPath` 覆盖,默认:`.trae/output/autotest.report.local.md`。 diff --git a/.trae/jobs/changelog-rush-smart.md b/.trae/jobs/changelog-rush-smart.md deleted file mode 100644 index fbbde29082..0000000000 --- a/.trae/jobs/changelog-rush-smart.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -job: generate-rush-changes-smart -intent: rush-change-smart -version: v1 -domain: release -runner: trae-solo -parameters: - sinceBranch: develop - message: '' - bumpType: auto - notCommit: true - githubToken: '' -required_parameters: [] -outputs: - - rush_change_entries - - computed_bump_type - - final_message -success_criteria: - - rush_changes_generated - - commitlint_passed -manual_overrides: [] ---- - -# Changelog Job(智能 Rush 变更日志生成) - -## 参数检查 - -- 无必填参数,均有默认值 -- 如需“关联 Issue 标题”自动聚合,请提供 `githubToken` - -## 步骤 - -1. 采集差异与提交 - -- 运行 `git diff --name-only {{sinceBranch}}...HEAD`,按文件路径映射到变更包 -- 运行 `git log --pretty=%H:::%s {{sinceBranch}}...HEAD`,收集提交主题 - -2. 自动判定 bumpType(可被参数覆盖) - -- 规则: - - 含 `BREAKING CHANGE` 或 `!` → `major` - - 含 `feat` → `minor` - - 其余(`fix|perf|refactor|docs|chore|test`)→ `patch` -- 若 `parameters.bumpType != auto`,则使用显式值 -- 将结果写入输出:`computed_bump_type` - -3. 构建富消息(可被参数覆盖) - -- 若 `parameters.message` 为空: - - 提取关键提交的主题(优先 `feat`/`fix`)形成“提交概览” - - 从提交中解析 `#`,调用 GitHub API 读取 Issue 标题(需 `githubToken`),形成“关联 Issue” - - 构建最终消息:首行摘要 + 提交概览 + 关联 Issue + 影响包 -- 将最终消息写入输出:`final_message` - -4. 提交信息校验 - -- 使用 `common/autoinstallers/lint/commitlint.config.js` 与本地 `commitlint` 执行校验 -- 命令:`echo "{{final_message}}" | commitlint --config common/autoinstallers/lint/commitlint.config.js` - -5. 生成 Rush 变更条目 - -- 执行 `rush change --bulk --bump-type '{{computed_bump_type}}' --message '{{final_message}}'` -- 输出文件位于 `common/changes/**`,收集为 `rush_change_entries` - -6. 可选提交 - -- 若 `notCommit != true`: - - 运行 `git add --all` - - 运行 `git commit -m 'docs: update changlog of rush'` - -7. 人工检查点 - -- 展示 `rush_change_entries`:路径、包名、bumpType、摘要 -- 如摘要需细化,编辑 `parameters.message` 或在二次执行中通过 `manual_overrides` 指定 - -## manual_overrides 示例 - -```yaml -manual_overrides: - - bumpType: minor - message: 'feat(core): 新增交互缩放配置,修复事件抛出问题 (#123)' -``` diff --git a/.trae/jobs/create-branch.md b/.trae/jobs/create-branch.md deleted file mode 100644 index 7fc334ff4c..0000000000 --- a/.trae/jobs/create-branch.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -job: create-dev-branch -intent: gitflow-create-branch -version: v1 -domain: git -runner: trae-solo -parameters: - baseBranch: develop - branchPrefix: chore/trae - topic: '' - useDateSuffix: true -required_parameters: - - topic -outputs: - - branch_name -success_criteria: - - branch_created - - clean_working_tree ---- - -# Create Branch Job(创建开发分支) - -## 参数检查 - -- 必填参数:`topic` -- 若未提供:请在执行入口中补充 `topic`(示例:`topic: perf-legend-opt`),再继续后续步骤。 - -## 步骤 - -1. 同步基础分支 - -- 运行 `git fetch --all --prune` -- 运行 `git checkout {{baseBranch}} && git pull origin {{baseBranch}}` - -2. 生成分支名 - -- 命名规则:`{{branchPrefix}}-{{topic}}-{{YYYYMMDD-HHMM}}` -- 将生成的分支名写入输出:`branch_name` - -3. 创建分支 - -- 运行 `git checkout -b {{branch_name}}` - -4. 人工检查点 - -- 运行 `git status` 并确认: - - 当前分支为 `{{branch_name}}` - - 工作树干净或仅包含预期改动 - -## 结果 - -- 成功则输出 `branch_name`,并保证后续任务在该分支上执行。 diff --git a/.trae/jobs/pr-create.md b/.trae/jobs/pr-create.md deleted file mode 100644 index 5843884e99..0000000000 --- a/.trae/jobs/pr-create.md +++ /dev/null @@ -1,167 +0,0 @@ ---- -job: create-pr -intent: github-pr -version: v1 -domain: github -runner: trae-solo -parameters: - base: develop - head: '' - title: '' - lang: zh - labels: [] - draft: false - useGhCli: true - mode: auto # auto|gh|rest|browser - localBodyFile: false - openBrowser: true - commitBeforeCreate: false - commitMessage: '' - commitAllowEmpty: false - pushAfterCommit: true - commitMessageStrategy: auto # auto|topic|manual -required_parameters: - - title -inputs: - autotestReport: .trae/output/autotest.report.local.md - rushChangesDir: common/changes - bumpType: '' - message: '' -outputs: - - pr_url - - compare_url - - generated_title - - generated_body_preview -success_criteria: - - pr_created ---- - -# PR Job(根据模版创建 Pull Request) - -## 参数检查 - -- 必填参数:`title` -- 分支参数 `head` 可选:若未提供,将在执行阶段通过 `git rev-parse --abbrev-ref HEAD` 推导当前分支 - -## 步骤 - -1. 提交未提交的变更并推送(可选) - -- 获取 `head`:若未提供,通过 `git rev-parse --abbrev-ref HEAD` 推导 -- 检查工作树:`git status --porcelain` -- 若存在未提交变更且 `commitBeforeCreate == true`: - - 运行 `git add --all` - - 生成提交信息(按 `commitMessageStrategy`): - - `auto`: - - 类型判定:包含 `docs/` → `docs`;包含 `__tests__`/`*.test.*` → `test`;否则 → `chore` - - 作用域:变更路径为 `packages//...` 时取 ``;否则取顶层目录(如 `docs`、`tools`、`common`、`.trae`) - - 主题:若提供 `message` 则使用其首行摘要;否则生成 `sync changes before PR ( files)` 并附加关键作用域 - - 结果示例:`chore(vchart,tools): sync changes before PR (5 files)` - - `topic`:使用 `title` 或外层 `topic` 作为主题,类型与作用域同上 - - `manual`:使用显式 `commitMessage` - - 运行 `git commit {{#commitAllowEmpty}}--allow-empty{{/commitAllowEmpty}} -m "{{}}"` - - 若 `pushAfterCommit == true`:运行 `git push -u origin {{head}}` -- 人工检查点: - - 若存在未提交变更但未开启自动提交,请先人工完成提交与推送再继续创建 PR - -2. 选择 PR 模版 - -- 当 `{{lang}} == zh`:使用 `.github/PULL_REQUEST_TEMPLATE/pr_cn.md` -- 否则使用 `.github/PULL_REQUEST_TEMPLATE.md` - -3. 准备正文 - -- 若已提供完整 `message`(摘要)与必要信息(关联链接等),可直接使用作为 PR body -- 若需要补充人工内容:提示用户完善 body 文本后再继续(不生成临时文件) - -- 生成可复制内容: -- `generated_title = [Auto] {{title || (topic || head)}}` -- 生成完整 PR 正文预览(Markdown 代码块),基于 `.github/PULL_REQUEST_TEMPLATE/pr_cn.md` 自动填充: - - 勾选项:`{{branch_type_checks}}`(如:新功能、Workflow 等) - - 关联:`{{issue_links}}`、`{{related_pr_links}}`、`{{bugserver_ids}}` - - 背景与方案:`{{background_solution}}`(从 `message` 与上下文生成) - - Changelog 表:`{{changelog_en}}` 与 `{{changelog_zh}}`(解析 `common/changes/**`) - - 自测勾选项:`{{self_check_items}}` - - Summary 与 Walkthrough:`{{summary_text}}`、`{{walkthrough_text}}`(包含分支、模板来源、测试摘要) -- 代码块示例结构: - - ```markdown - ### 🤔 这个分支是... - - - [x] 新功能 - - [x] Workflow - - ### 🔗 相关 issue 链接 - - {{issue_links}} - - ### 🔗 相关的 PR 链接 - - {{related_pr_links}} - - ### 🐞 Bugserver 用例 id - - {{bugserver_ids}} - - ### 💡 问题的背景&解决方案 - - {{background_solution}} - - ### 📝 Changelog - - | Language | Changelog | - | ---------- | ---------------- | - | 🇺🇸 English | {{changelog_en}} | - | 🇨🇳 Chinese | {{changelog_zh}} | - - ### ☑️ 自测 - - {{self_check_items}} - - --- - - ### 🚀 Summary - - {{summary_text}} - - ### 🔍 Walkthrough - - {{walkthrough_text}} - ``` - -- 若 `localBodyFile=true`:以完整代码块形式写入 `./.trae/output/pr.body.local.md`(被忽略提交) - -4. 人工检查点 - -- 若 body 需要补充,请人工完成后继续(不生成临时文件) - -5. 创建 PR - -- 模式选择: - - - `auto`:优先使用 `gh`(若已安装并登录);其次使用 `GITHUB_TOKEN` 的 REST;最后提供浏览器 URL 手动创建 - - `gh`:使用 GitHub CLI 创建(需本机已登录) - - `rest`:使用 `GITHUB_TOKEN` 调用 REST API 创建 - - `browser`:生成 compare URL,打开浏览器页面手动确认 - -- 检测与执行: - - 若未提供 `head`:先运行 `git rev-parse --abbrev-ref HEAD` 以推导当前分支 - - 检测 `gh`:`command -v gh` 成功则执行: - - `gh pr create --base {{base}} --title "{{title}}" --body "{{message}}" --head {{head}} {{#labels}}--label {{labels}}{{/labels}} {{#draft}}--draft{{/draft}}` - - 若无 `gh` 而存在 `GITHUB_TOKEN`:使用 REST API `POST /repos/{owner}/{repo}/pulls`,body 使用 `{{message}}` - - 否则生成 compare URL: - - `compare_url = https://github.com/VisActor/VChart/compare/{{base}}...{{head}}?expand=1` - - 输出 `generated_title` 与以完整 Markdown 代码块格式的 `generated_body_preview`,便于直接复制到 PR 页面;若 `openBrowser=true` 在 macOS 运行 `open {{compare_url}}` - -6. 结果 - -- 返回 `pr_url`,并在成功标准中标记为 `pr_created` -- 在 `browser` 模式:返回 `compare_url`、`generated_title` 与完整的 `generated_body_preview` - (其中 `generated_body_preview` 为包含所有模板栏目且已自动填充的 Markdown 代码块) - -## 额外提示 - -- 自动创建 PR 有三种方式: - - 本机已登录 `gh`:无需额外令牌(SSH 仅用于 git 操作,API 权限由 `gh` 登录提供) - - 本机无 `gh`:提供 `GITHUB_TOKEN` 用 REST API 创建 - - 两者都不可用:生成 compare URL,使用浏览器登录后手动创建 diff --git a/.trae/skills/auto-flow/SKILL.md b/.trae/skills/auto-flow/SKILL.md new file mode 100755 index 0000000000..3c19275e2e --- /dev/null +++ b/.trae/skills/auto-flow/SKILL.md @@ -0,0 +1,90 @@ +--- +name: auto-flow +description: 'Orchestrates a complete, standardized workflow for preparing a pull request in the VChart project. Use this skill to run a sequence of tasks: automated testing, changelog generation, smart commit, PR body creation, and PR submission. It provides a fixed 5-step process with manual checkpoints, ensuring quality and consistency for every contribution.' +--- + +# PR 准备全流程编排 (auto-flow) + +## 概述 + +本技能是一个固定的五步编排工作流,旨在自动化 `VChart` 项目从代码变更到创建 Pull Request 的整个准备过程。它将一系列独立的子技能(测试、变更日志、提交、PR 内容生成、PR 创建)串联成一个连贯的、带有人工检查点的流程。 + +## 前置条件 + +- **环境**: 必须在配置了 Rush、Git 的有效工作区中执行。 +- **依赖与凭证**: 所有被编排的子技能所需的前置条件都必须满足,特别是 `pr-create-from-body` 技能需要的 `GITHUB_TOKEN` 或 `gh` CLI。 + +## 输入参数 + +本技能的流程是固定的,不通过参数选择执行步骤。它会按顺序执行所有五个步骤。 + +| 参数 | 类型 | 是否必填 | 默认值 | 描述 | +| ------------- | ------- | -------- | ------------ | -------------------------------------------------------------------- | +| `baseBranch` | string | 否 | `develop` | 整个流程所围绕的基准分支,用于差异计算和 PR 目标。 | +| `topic` | string | 否 | (空) | 用于优化 PR 标题的可选主题。 | +| `message` | string | 否 | (空) | 用于 `changelog` 和 `commit` 的自定义消息。 | +| `bumpType` | string | 否 | `auto` | Rush 变更日志的版本升级类型。 | +| `head` | string | 否 | (空) | 当前开发分支。如果为空,将自动推导。 | +| `labels` | array | 否 | `[changelog, test]` | 附加到最终 PR 的标签。 | + +## 输出与成功标准 + +- **主要输出**: + - `autotest_report`: 单元测试报告文件路径。 + - `rush_change_entries`: 生成的 Rush 变更条目列表。 + - `commit_message`: 创建的提交信息。 + - `pr_url`: 最终创建的 Pull Request 链接。 +- **成功标准**: + - `flow_step_completed`: 流程中的每一步或整个流程已成功完成。 + +## 执行步骤 + +本技能按固定顺序依次执行以下子技能,并在每一步之间设置人工检查点: + +1. **差异驱动单测** + - **执行**: `auto-test` 技能。 + - **目的**: 为代码变更生成并运行单元测试。 + - **检查点**: Agent 会返回测试报告路径。**你需要检查报告中的测试覆盖率和结果,确认无误后指示 Agent 继续。** + +2. **生成 Rush 变更日志** + - **执行**: `changelog-rush-smart` 技能。 + - **目的**: 根据提交历史创建 `common/changes/**` 下的变更条目。 + - **检查点**: Agent 会提示已生成变更条目。**你需要检查这些文件的内容是否准确反映了你的变更,然后指示 Agent 继续。** + +3. **智能提交** + - **执行**: `commit-smart` 技能。 + - **目的**: 将所有变更(代码、测试、changelog 文件)创建一个符合规范的 Git 提交并推送到远程。 + - **检查点**: Agent 会返回生成的提交信息和推送结果。**你需要确认提交信息是正确的,然后指示 Agent 继续。** + +4. **生成 PR 正文** + - **执行**: `pr-body-generate` 技能。 + - **目的**: 自动填充 PR 模板,生成包含所有上下文信息的 PR 正文。 + - **检查点**: Agent 会返回生成的 PR 正文预览和本地文件路径。**你应审阅正文内容,确保其完整和准确(可在此步之后手动修改文件),然后指示 Agent 继续。** + +5. **创建 PR** + - **执行**: `pr-create-from-body` 技能。 + - **目的**: 使用上一步生成的正文文件,在 GitHub 上创建 Pull Request。 + - **检查点**: Agent 会返回最终的 PR 链接。**你需要访问链接确认 PR 是否按预期创建。** + +## 何时使用 / 边界 + +- **使用时机**: + - 当你完成一个功能或修复,准备发起一个完整的、高质量的 Pull Request 时,这是推荐的标准化流程。 + - 特别适用于发布前准备工作,确保所有检查项(测试、changelog)都已完成。 +- **边界**: + - 此技能是一个编排层,它不执行实际工作,而是调用其他技能。因此,它的成功依赖于所有子技能的正确配置和执行。 + - 流程中的任何一步失败,整个流程都会中断,并报告失败的步骤和原因。 + +## 使用示例 + +> **你**: “启动 `auto-flow` 流程,为我的新功能做发布准备。” +> +> **Agent**: *(执行 `auto-test`)* “第一步:测试已完成,报告位于 `.../autotest.report.local.md`。请检查后告诉我是否继续。” +> +> **你**: *(检查报告后)* “继续。” +> +> **Agent**: *(执行 `changelog-rush-smart`)* “第二步:变更日志已生成。请检查 `common/changes/` 目录。确认无误后,请告诉我是否继续。” +> +> **你**: “继续。” +> +> **Agent**: *(继续执行后续步骤,并在每一步后请求确认)* diff --git a/.trae/skills/auto-flow/docs/USAGE.md b/.trae/skills/auto-flow/docs/USAGE.md new file mode 100755 index 0000000000..c4da10d50f --- /dev/null +++ b/.trae/skills/auto-flow/docs/USAGE.md @@ -0,0 +1,53 @@ +# 使用说明:auto-flow + +本技能将创建 Pull Request 的所有准备工作(测试、变更日志、提交、生成正文、创建 PR)串联成一个标准化的五步流程。 + +## 何时使用 + +- **发布准备**: 当你完成一个功能或修复,准备发起一个完整的、高质量的 Pull Request 时,使用此技能可以确保所有检查项都已完成。 +- **标准化贡献**: 团队成员可以使用此流程来确保所有贡献都遵循相同的质量标准。 + +## 流程与人工检查点 + +本技能是一个带有“门禁”的流水线,每一步完成后都会暂停,等待你的确认: + +1. **自动测试**: 技能首先为你的代码变更生成并运行测试。 + * **你需要**: 检查测试报告,确认覆盖率和测试结果符合预期。 + +2. **生成变更日志**: 接着,它会为你的提交创建 `changelog` 文件。 + * **你需要**: 检查 `common/changes/` 目录下生成的文件内容是否准确。 + +3. **智能提交**: 然后,所有变更会被打包成一个规范的 Git 提交并推送。 + * **你需要**: 确认自动生成的提交信息是正确的。 + +4. **生成 PR 正文**: 技能会自动填充 PR 模板。 + * **你需要**: 审阅生成的 PR 正文,可选择在本地修改 `.md` 文件。 + +5. **创建 PR**: 最后,使用准备好的正文创建 PR。 + * **你需要**: 访问返回的 PR 链接,做最终确认。 + +## 示例对话 + +> **你**: “启动 `auto-flow` 流程,为我的新功能做发布准备。” +> +> **Agent**: (执行第一步) “第一步:测试已完成,报告位于 `.../autotest.report.local.md`。请检查后告诉我是否继续。” +> +> **你**: (检查后) “继续。” +> +> **Agent**: (执行第二步) “第二步:变更日志已生成。请检查 `common/changes/` 目录。确认无误后,请告诉我是否继续。” +> +> **你**: “继续。” +> +> *... (Agent 会继续执行后续步骤,并在每一步后请求确认)* + +## 关键参数 + +- `baseBranch`: PR 的目标分支,默认为 `develop`。 +- `topic`: 用于生成 PR 标题,建议提供。 +- `message`: 用于 `changelog` 和 `commit` 的自定义消息。 + +## 注意事项 + +- **凭证**: 确保 `GITHUB_TOKEN` 或 `gh` CLI 已正确配置,否则最后一步会失败。 +- **顺序固定**: 本技能的五个步骤是固定的,不能跳过或重排。 +- **失败中断**: 流程中任何一步失败都会导致整个流程中断。 diff --git a/.trae/skills/auto-test/SKILL.md b/.trae/skills/auto-test/SKILL.md new file mode 100755 index 0000000000..b8bb2996b8 --- /dev/null +++ b/.trae/skills/auto-test/SKILL.md @@ -0,0 +1,65 @@ +--- +name: auto-test +description: 'Automates unit testing for incremental code changes in the VChart project. Use this skill to automatically generate and run tests for your modifications against a base branch (default: develop). It identifies changes, creates/updates Jest test cases and snapshots, and provides a coverage report. This skill requires a functional Rush and Git environment.' +--- + +# 差异驱动的单元测试 (auto-test) + +## 概述 + +本技能用于对 `VChart` 项目中指定基准分支与当前 `HEAD` 之间的代码差异,自动生成、更新和执行单元测试。它能够处理已提交和未提交的变更,并生成一份详细的测试报告。 + +## 前置条件 + +- **环境**: 必须在配置了 Rush 和 Git 的有效工作区中执行。 +- **GitHub 凭证 (可选)**: 某些高级功能可能需要有效的 `GITHUB_TOKEN` 或已登录的 `gh` CLI。 + +## 输入参数 + +| 参数 | 类型 | 默认值 | 描述 | +| -------------------- | ------- | --------------------------------- | ---------------------------------------------------------- | +| `sinceBranch` | string | `develop` | 用于差异计算的基准分支。 | +| `project` | string | `auto` | 要测试的 Rush 项目,`auto` 表示自动识别变更所属的项目。 | +| `mode` | string | `full` | 测试模式。 | +| `noSnapshot` | boolean | `false` | 是否跳过快照测试。 | +| `reportFormat` | string | `md` | 生成报告的格式 (`md` 或 `json`)。 | +| `tempReportPath` | string | `.trae/output/autotest.report.local.md` | 临时报告的输出路径。 | +| `replaceAutogen` | boolean | `false` | 是否允许替换已有的 `autogen:` 测试块。 | +| `includeWorkingTree` | boolean | `true` | 是否包含工作树(未提交的)的变更。 | + +## 输出与成功标准 + +- **主要输出**: + - `test_files`: 生成或更新的测试文件列表。 + - `snapshots`: 生成或更新的快照文件。 + - `coverage_report`: 覆盖率报告摘要。 + - `manual_nodes`: 提示需要人工介入的测试点。 + - `temp_markdown_report`: 本地生成的 Markdown 格式临时报告。 +- **成功标准**: + - `tests_generated_for_changed_exports`: 已为所有变更的导出项生成测试。 + - `compile_without_errors`: 生成的测试代码编译无误。 + - `coverage_increase_or_maintained`: 代码覆盖率持平或有所提升。 + +## 执行步骤 + +1. **差异采集**: Agent 会使用 `git diff` 和 `git status` 命令,识别出从 `{{sinceBranch}}` 到当前 `HEAD` 的所有已提交和未提交的文件与代码行级变更。 +2. **影响分析**: 分析变更内容,识别出哪些导出函数、类型或逻辑分支受到了影响,并检查 `__tests__` 目录下是否存在对应的测试缺口。 +3. **测试生成**: + - 在受影响模块的 `__tests__` 目录下创建或更新测试文件 (`*.test.ts`)。 + - 为纯函数、UI 组件、工具函数等生成不同策略的测试用例,并附带说明性注释。 + - 对不确定的 Mock 或断言,会生成带 `test.skip` 和 `MANUAL_REQUIRED` 标记的占位符。 +4. **执行与覆盖率分析**: + - 根据 `project` 参数,运行 `rush run test` 和 `rush run test-cov` 命令。 + - 收集测试结果和覆盖率数据。 +5. **报告生成**: + - 将所有变更、测试生成情况、运行结果、覆盖率变化及潜在风险点汇总成一份报告,并保存到 `{{tempReportPath}}`。 + +## 何时使用 / 边界 + +- **使用时机**: + - 在完成一部分代码开发后,需要快速验证变更的正确性并补充单元测试时。 + - 在准备提交代码前,确保所有改动都被测试覆盖。 + - 作为持续集成流程的一部分,用于自动化回归测试。 +- **边界**: + - 此技能专注于单元测试,无法替代集成测试或端到端测试。 + - 对于复杂的业务逻辑或需要精细 Mock 的场景,生成的测试用例可能需要人工调整。 diff --git a/.trae/skills/auto-test/docs/USAGE.md b/.trae/skills/auto-test/docs/USAGE.md new file mode 100755 index 0000000000..cb2d7bc0e3 --- /dev/null +++ b/.trae/skills/auto-test/docs/USAGE.md @@ -0,0 +1,36 @@ +# 使用说明:auto-test + +本技能根据代码增量自动生成单元测试,确保变更得到充分验证。 + +## 何时使用 + +- **编码后**: 开发了新功能或修复了缺陷后,运行此技能可快速为你的变更生成测试用例。 +- **提交前**: 在 `git commit` 之前,使用此技能确保所有改动都已被测试覆盖,满足合入标准。 +- **CI/CD**: 可作为自动化流水线的一环,对每次提交进行回归测试。 + +## 示例对话 + +**场景一:对所有变更运行测试** + +> **你**: “帮我运行 `auto-test`,检查下我最近的改动。” +> +> **Agent**: (执行技能) “测试已完成,报告位于 `./.trae/output/autotest.report.local.md`。新增测试 `X` 个,覆盖率提升 `Y%`。请查阅报告确认。” + +**场景二:仅测试特定包** + +> **你**: “为 `@visactor/vchart` 项目执行 `auto-test`。” +> +> **Agent**: (将测试范围限定在指定包内执行) “已完成对 `@visactor/vchart` 的测试。报告已生成。” + +## 关键参数 + +- `sinceBranch`: 定义进行比较的基准分支,默认为 `develop`。 +- `project`: 指定要测试的 Rush 项目。`auto` 会自动识别变更影响的包;你也可以明确指定,如 `'@visactor/vchart'`。 +- `reportFormat`: 输出报告的格式,支持 `md` (默认) 和 `json`。 +- `tempReportPath`: 测试报告的本地输出路径,默认为 `./.trae/output/autotest.report.local.md`。 + +## 注意事项 + +- 此技能专注于单元测试,不能完全替代集成测试或端到端测试。 +- 自动生成的测试可能需要人工干预,特别是在涉及复杂模拟(Mock)或特定业务逻辑的场景中。 +- 执行前请确保 `rush` 依赖已正确安装。 diff --git a/.trae/skills/changelog-rush-smart/SKILL.md b/.trae/skills/changelog-rush-smart/SKILL.md new file mode 100755 index 0000000000..a5a7a5a4a6 --- /dev/null +++ b/.trae/skills/changelog-rush-smart/SKILL.md @@ -0,0 +1,56 @@ +--- +name: changelog-rush-smart +description: 'Generates standardized changelog entries for a Rush-based monorepo like VChart. Use this skill to create changelog files based on Git commits since a base branch (default: develop). It intelligently determines the version bump type, aggregates commit messages, and can enrich them with linked GitHub issue titles if a GITHUB_TOKEN is provided.' +--- + +# 智能 Rush 变更日志 (changelog-rush-smart) + +## 概述 + +本技能依据自 `develop` 分支以来的 Git 提交历史,为 `VChart` 项目自动生成符合 Rush 规范的变更日志条目。它能智能地推断版本变更类型(major/minor/patch),并聚合提交信息来创建消息内容。 + +## 前置条件 + +- **Rush 环境**: 项目依赖 `rush` 已正确安装。 +- **GitHub Token (可选)**: 若想自动拉取并聚合关联 Issue 的标题,需在环境中配置 `GITHUB_TOKEN`。 + +## 输入参数 + +| 参数 | 类型 | 是否必填 | 默认值 | 描述 | +| ------------- | ------ | -------- | --------- | ---------------------------------------------------------- | +| `sinceBranch` | string | 否 | `develop` | 用于差异计算的基准分支。 | +| `bumpType` | string | 否 | `auto` | 版本变更类型 (`auto`, `major`, `minor`, `patch`)。`auto` 会根据提交信息自动推断。 | +| `message` | string | 否 | (空) | 手动指定的变更摘要。如果为空,将根据提交记录自动生成。 | +| `notCommit` | boolean| 否 | `true` | 是否在生成变更条目后自动执行 `git commit`。 | +| `githubToken` | string | 否 | (空) | 用于访问 GitHub API 以获取 Issue 标题的个人访问令牌。 | + +## 输出与成功标准 + +- **主要输出**: + - `rush_change_entries`: 生成的 Rush 变更条目文件路径列表(位于 `common/changes/**`)。 + - `computed_bump_type`: 最终采纳的版本变更类型。 + - `final_message`: 用于生成变更条目的最终消息文本。 +- **成功标准**: + - `rush_changes_generated`: 变更条目已成功生成。 + - `commitlint_passed`: 生成的消息摘要符合 `commitlint` 规范。 + +## 执行步骤 + +1. **采集差异与提交**: Agent 会收集从 `{{sinceBranch}}` 到 `HEAD` 的文件变更和提交记录。 +2. **判定版本变更类型 (`bumpType`)**: + - Agent 会分析提交信息中的关键字(如 `BREAKING CHANGE`, `feat`, `fix` 等)来自动判断版本变更级别。 + - 如果用户显式提供了 `bumpType` 参数,则优先使用用户指定的值。 +3. **构建变更消息**: + - 如果 `message` 参数为空,Agent 会智能地从提交历史中提取关键信息,并(在有 `githubToken` 的情况下)拉取关联 Issue 的标题,共同构成一条内容丰富的变更消息。 +4. **生成 Rush 变更条目**: + - Agent 会执行 `rush change` 命令,使用上一步确定的 `bumpType` 和消息,为每个受影响的包生成对应的变更文件。 +5. **(可选)提交变更**: 如果 `notCommit` 未设置为 `true`,Agent 会将新生成的变更文件添加到 Git 暂存区并创建一个提交。 + +## 何时使用 / 边界 + +- **使用时机**: + - 在完成一个或多个功能的开发、即将发起 Pull Request 之前,用于生成标准的 `changelog` 条目。 + - 当你需要遵循 `VChart` 项目的版本发布流程,为你的变更创建记录时。 +- **边界**: + - 此技能只负责生成 `common/changes/**` 下的变更文件,它本身不执行版本发布 (`rush publish`)。 + - 自动生成的消息质量依赖于良好、规范的 Git 提交历史。 diff --git a/.trae/skills/changelog-rush-smart/docs/USAGE.md b/.trae/skills/changelog-rush-smart/docs/USAGE.md new file mode 100755 index 0000000000..17b724bf85 --- /dev/null +++ b/.trae/skills/changelog-rush-smart/docs/USAGE.md @@ -0,0 +1,35 @@ +# 使用说明:changelog-rush-smart + +本技能用于根据 Git 提交记录为 Rush monorepo 项目智能生成变更日志。 + +## 何时使用 + +- **PR 前**: 在发起 Pull Request 之前,使用此技能为你的变更生成标准的 `changelog` 条目。 +- **发布准备**: 作为 `auto-flow` 编排的一部分,在 `auto-test` 之后自动执行,确保版本历史的完整性。 + +## 示例对话 + +**场景一: 自动生成** + +> **你**: “请为我最近的提交生成 changelog。” +> +> **Agent**: (执行技能) “变更日志已生成。`bumpType` 被自动判断为 `patch`。文件已创建于 `common/changes/` 目录。” + +**场景二: 手动指定类型和消息** + +> **你**: “执行 `changelog-rush-smart`,`bumpType` 设为 `minor`,并使用消息 '新增图表系列,支持交互式图例'。” +> +> **Agent**: (使用指定参数执行) “好的,已使用 `minor` 类型和你的自定义消息生成了变更日志。” + +## 关键参数 + +- `sinceBranch`: 定义比较的基准分支,默认为 `develop`。 +- `bumpType`: 版本变更类型,可以是 `auto`, `major`, `minor`, `patch`。`auto` 会基于提交信息自动推断。 +- `message`: 手动指定的变更摘要。如果留空,将根据提交记录自动生成。 +- `githubToken`: (可选)提供 GitHub 个人访问令牌,以便自动拉取并聚合关联 Issue 的标题。 + +## 注意事项 + +- 自动生成的消息质量高度依赖于规范、清晰的 Git 提交历史。 +- 本技能仅生成 `common/changes/**` 下的文件,不执行 `rush version` 或 `rush publish`。 +- 如果需要自动关联 Issue 标题,请确保 `GITHUB_TOKEN` 已在环境中正确配置。 diff --git a/.trae/skills/commit-smart/SKILL.md b/.trae/skills/commit-smart/SKILL.md new file mode 100755 index 0000000000..bd65815114 --- /dev/null +++ b/.trae/skills/commit-smart/SKILL.md @@ -0,0 +1,58 @@ +--- +name: commit-smart +description: 'Creates a well-formed, intelligent Git commit for all pending changes in the VChart project. Use this skill to bundle your work into a single, clean commit that follows Conventional Commits standards. It automatically determines the commit type and scope, generates a message, and then performs the `git commit` and `git push`. Ideal for finalizing changes before creating a pull request.' +--- + +# 智能提交 (commit-smart) + +## 概述 + +本技能用于将当前工作树中所有未提交的变更(staged 和 unstaged)进行一次智能化的 Git 提交,并可选地推送到远程仓库。它会自动根据文件路径和 `common/changes` 目录下的内容生成符合 Conventional Commits 规范的提交信息。 + +## 前置条件 + +- **Git 环境**: 一个配置好的 Git 环境,且当前位于一个 Git 仓库目录中。 +- **远程分支**: 远程仓库需要存在与本地对应的分支,以便推送。 + +## 输入参数 + +| 参数 | 类型 | 是否必填 | 默认值 | 描述 | +| ----------------------- | ------- | -------- | ------ | -------------------------------------------------------------------- | +| `head` | string | 否 | (空) | 要推送的分支名。如果为空,将自动推导当前所在分支。 | +| `message` | string | 否 | (空) | 手动指定的提交信息。如果提供,将以此为基础生成最终提交。 | +| `commitMessageStrategy` | string | 否 | `auto` | 提交信息的生成策略,目前仅支持 `auto`。 | +| `pushAfterCommit` | boolean | 否 | `true` | 是否在提交后自动执行 `git push`。 | +| `commitAllowEmpty` | boolean | 否 | `false`| 是否允许在没有文件变更时创建一个空提交。 | + +## 输出与成功标准 + +- **主要输出**: + - `commit_message`: 最终生成的完整提交信息。 + - `pushed_branch`: 成功推送到的远程分支名。 +- **成功标准**: + - `commit_created_or_skipped`: 提交被成功创建;或者因为没有变更而安全地跳过。 + +## 执行步骤 + +1. **分支与状态检查**: + - Agent 首先会确定目标分支,如果 `head` 参数未提供,则自动获取当前分支名。 + - 接着,它会检查工作树的状态,如果没有任何变更且 `commitAllowEmpty` 为 `false`,则会跳过后续步骤。 + +2. **生成提交信息**: + - **类型(Type)**: Agent 会根据变更文件的路径(例如 `docs/` -> `docs`, `__tests__/` -> `test`)和 `common/changes/` 下的变更类型来推断。 + - **作用域(Scope)**: 根据文件所在的包(如 `packages/`)或顶层目录来确定。 + - **主题(Subject)**: 优先使用 `message` 参数的首行;如果 `message` 为空,则会尝试从 `common/changes/` 的最新条目中提取 `comment` 作为主题;如果两者都无,则生成一个通用主题,如 `sync changes before PR (N files)`。 + +3. **执行提交与推送**: + - Agent 会运行 `git add --all` 将所有变更添加到暂存区。 + - 然后使用生成的提交信息执行 `git commit`。 + - 如果 `pushAfterCommit` 为 `true`,它会接着执行 `git push -u origin {{head}}` 将提交推送到远程仓库。 + +## 何时使用 / 边界 + +- **使用时机**: + - 在执行了 `auto-test` 和 `changelog-rush-smart` 之后,需要将所有自动生成的文件和你的代码变更一起提交时。 + - 在准备发起 Pull Request 之前的最后一步,用于创建一个干净、规范的提交。 +- **边界**: + - 此技能会提交工作区中 **所有** 的变更,请在执行前确认没有不想被提交的文件。 + - 它不会处理 Git 冲突,执行前请确保分支是干净的。 diff --git a/.trae/skills/commit-smart/docs/USAGE.md b/.trae/skills/commit-smart/docs/USAGE.md new file mode 100755 index 0000000000..d55a1bc8e8 --- /dev/null +++ b/.trae/skills/commit-smart/docs/USAGE.md @@ -0,0 +1,33 @@ +# 使用说明:commit-smart + +本技能用于将所有待处理的变更创建为一个符合规范的 Git 提交,并推送到远程仓库。 + +## 何时使用 + +- **PR 准备**: 在生成了测试和变更日志后,使用此技能将所有相关文件(源代码、测试文件、`changelog` 条目)捆绑成一个原子提交。 +- **快速同步**: 当你想快速将本地所有工作同步到远程分支时,此技能提供了一键式的 `add`, `commit`, 和 `push` 操作。 + +## 示例对话 + +**场景一: 自动提交** + +> **你**: “代码、测试和 changelog 都好了,帮我提交所有变更。” +> +> **Agent**: (执行技能) “好的。已生成提交信息 'feat(vchart): add new interactive features' 并成功推送到 `origin/your-branch`。” + +**场景二: 使用自定义消息** + +> **你**: "执行 `commit-smart`,并使用 'refactor(core): 优化图表渲染性能' 作为提交信息。" +> +> **Agent**: (使用指定消息执行) “提交已创建并推送,提交信息为 'refactor(core): 优化图表渲染性能'。” + +## 关键参数 + +- `head`: 要推送的分支名。如果留空,将自动使用当前分支。 +- `message`: 手动指定的提交信息。若提供,将作为提交主题。否则,将根据 `common/changes/` 内容或文件变更自动生成。 +- `pushAfterCommit`: 是否在提交后自动推送,默认为 `true`。 + +## 注意事项 + +- **危险区域**: 此技能会使用 `git add --all` 命令,将工作目录中 **所有** 未被 `.gitignore` 忽略的变更添加到提交中。请在执行前仔细检查你的工作区,确保没有不想提交的临时文件或改动。 +- 执行前请确保当前分支没有合并冲突,且远程分支已存在。 diff --git a/.trae/skills/create-branch/SKILL.md b/.trae/skills/create-branch/SKILL.md new file mode 100755 index 0000000000..a37811936d --- /dev/null +++ b/.trae/skills/create-branch/SKILL.md @@ -0,0 +1,52 @@ +--- +name: create-branch +description: 'Creates a new development branch in the VChart project following standard naming conventions. Use this skill to start new work on a clean, synchronized branch based on a specified base branch (default: develop). You must provide a `topic` for the branch name.' +--- + +# 创建开发分支 (create-branch) + +## 概述 + +本技能用于在 `VChart` 仓库中,基于指定的基础分支(默认为 `develop`)创建一个符合团队命名规范的、干净的开发分支。 + +## 前置条件 + +- **Git 环境**: 需要一个配置好 git 的环境。 +- **工作树状态**: 为保证分支创建的纯净,建议在干净的工作树上执行。 + +## 输入参数 + +| 参数 | 类型 | 是否必填 | 默认值 | 描述 | +| -------------- | ------- | -------- | -------------- | ---------------------------------------------- | +| `topic` | string | 是 | (无) | 分支主题,用于构成最终的分支名(例如 `perf-legend-opt`)。 | +| `baseBranch` | string | 否 | `develop` | 创建新分支所基于的基础分支。 | +| `branchPrefix` | string | 否 | `chore/trae` | 分支名的前缀。 | +| `useDateSuffix`| boolean | 否 | `true` | 是否在分支名末尾追加日期和时间后缀。 | + +## 输出与成功标准 + +- **主要输出** (`branch_name`): 成功创建并切换到的新分支的完整名称。 +- **成功标准**: + - `branch_created`: 新分支被成功创建。 + - `clean_working_tree`: 执行后工作树保持干净。 + +## 执行步骤 + +1. **同步基础分支**: + - Agent 会首先运行 `git fetch --all --prune` 来获取所有远程更新。 + - 接着,它会切换到 `{{baseBranch}}` 并执行 `git pull` 以确保其为最新状态。 + +2. **生成并创建分支**: + - 根据 `branchPrefix`、`topic` 和 `useDateSuffix` 参数组合生成标准格式的分支名。 + - 执行 `git checkout -b {{branch_name}}` 创建并切换到新分支。 + +3. **状态检查**: + - Agent 会运行 `git status` 检查并确认当前已在新分支上,且工作树是干净的。 + +## 何时使用 / 边界 + +- **使用时机**: + - 当你需要为新功能、修复或任何其他编码任务,在 `VChart` 项目中创建一个新的、遵循团队规范的开发分支时。 +- **边界**: + - 此技能不负责提交任何代码,仅创建和切换分支。 + - 执行前,请确保你的工作区中没有需要保存的未提交变更,因为切换分支可能会导致问题。 diff --git a/.trae/skills/create-branch/docs/USAGE.md b/.trae/skills/create-branch/docs/USAGE.md new file mode 100755 index 0000000000..31512fa496 --- /dev/null +++ b/.trae/skills/create-branch/docs/USAGE.md @@ -0,0 +1,28 @@ +# 使用说明:create-branch + +本技能用于在 `VChart` 项目中快速创建一个符合命名规范的、干净的开发分支。 + +## 何时使用 + +- **开始新任务**: 当你准备开始一个新功能、修复一个 bug 或进行任何需要独立分支的工作时,使用此技能可以确保你从一个与 `develop` 同步的、命名规范的分支开始。 + +## 示例对话 + +> **你**: “我想开始一个关于图例性能优化的工作,请帮我创建一个开发分支。” +> +> **Agent**: “好的,请为你的分支提供一个 `topic`。” +> +> **你**: “topic 是 `perf-legend-opt`” +> +> **Agent**: (执行技能) “分支 `chore/trae-perf-legend-opt-20260105-1130` 已创建并切换成功。你现在可以在这个新分支上开始工作了。” + +## 关键参数 + +- `topic`: **(必填)** 分支的主题,将成为分支名的一部分。例如 `feature-new-axis`。 +- `baseBranch`: 新分支基于哪个分支创建,默认为 `develop`。 +- `branchPrefix`: 分支名的前缀,默认为 `chore/trae`。 + +## 注意事项 + +- **干净的工作区**: 建议在执行此技能前,先提交或储藏你的本地变更,因为 `git checkout` 操作可能会覆盖未提交的改动。 +- 本技能只负责创建和切换分支,不处理任何代码的提交或合并。 diff --git a/.trae/skills/pr-body-generate/SKILL.md b/.trae/skills/pr-body-generate/SKILL.md new file mode 100755 index 0000000000..6dacbc3b91 --- /dev/null +++ b/.trae/skills/pr-body-generate/SKILL.md @@ -0,0 +1,58 @@ +--- +name: pr-body-generate +description: 'Generates a well-formed Pull Request body for the VChart project based on its template. Use this skill to automatically populate the PR body with details like linked issues, changelog entries, self-test checklists, and a code walkthrough. The output is saved to a local file for review and modification before creating the PR.' +--- + +# 生成 PR 正文 (pr-body-generate) + +## 概述 + +本技能用于根据 `VChart` 仓库中预设的 Pull Request 模板,自动生成一份内容丰富、格式规范的 PR 正文。它能够智能地聚合来自 Rush 变更日志、测试报告和 Git 提交历史的信息。 + +## 前置条件 + +- **Git 环境**: 一个配置好的 Git 环境。 +- **本地变更**: 建议在本地已有代码变更和 `common/changes` 变更条目的情况下运行,以生成最完整的 PR 正文。 + +## 输入参数 + +| 参数 | 类型 | 是否必填 | 默认值 | 描述 | +| ---------------- | ------- | -------- | ----------------------------- | -------------------------------------------------------------- | +| `lang` | string | 否 | `zh` | PR 模板的语言 (`zh` 或 `en`)。 | +| `title` | string | 否 | (空) | 用于生成建议 PR 标题的素材。 | +| `head` | string | 否 | (空) | PR 的源分支名。如果为空,将自动推导当前分支。 | +| `labels` | array | 否 | `[]` | 附加到 PR 的标签,会体现在正文的元信息中。 | +| `rushChangesDir` | string | 否 | `common/changes` | Rush 变更日志条目所在的目录。 | +| `localBodyFile` | boolean | 否 | `true` | 是否将生成的正文保存到本地文件。 | +| `autotestReport` | string | 否 | `.trae/output/autotest.report.local.md` | `auto-test` 技能生成的临时报告路径,其内容会被摘要进 PR 正文。 | + +## 输出与成功标准 + +- **主要输出**: + - `generated_title`: 推荐的 PR 标题。 + - `generated_body_preview`: 生成的完整 PR 正文的 Markdown 预览。 + - `generated_body_file`: 本地保存 PR 正文的文件路径(默认为 `.trae/output/pr.body.local.md`)。 +- **成功标准**: + - `body_generated`: PR 正文已成功生成并按需保存到本地文件。 + +## 执行步骤 + +1. **选择模板**: 根据 `lang` 参数,Agent 会选择对应的 PR 模板文件(例如 `.github/PULL_REQUEST_TEMPLATE/pr_cn.md`)。 +2. **填充内容**: Agent 会自动执行以下填充操作: + - **Changelog**: 解析 `{{rushChangesDir}}` 目录下的变更条目,并填充到正文的 Changelog 部分。 + - **自测项**: 如果 `autotestReport` 文件存在,会将其中的测试摘要信息填充到自测/走查部分。 + - **背景与方案**: 基于 `message` 参数(如果提供)和提交历史,生成简要的背景与方案描述。 + - **元信息**: 填充分支、标签等信息。 +3. **输出与保存**: + - Agent 会生成一个建议的 PR 标题。 + - 将完整的 PR 正文以 Markdown 预览形式展示。 + - 如果 `localBodyFile` 为 `true`,会将纯净的 Markdown 正文内容保存到 `.trae/output/pr.body.local.md` 文件中,以便后续步骤使用或人工修改。 + +## 何时使用 / 边界 + +- **使用时机**: + - 在提交代码并生成变更日志之后,创建 PR 之前,用于准备 PR 的描述内容。 + - 作为 `auto-flow` 工作流的一部分,在 `commit-smart` 步骤之后自动调用。 +- **边界**: + - 此技能只生成 PR 正文,不会创建 PR。创建 PR 是 `pr-create-from-body` 技能的职责。 + - 生成内容的丰富程度依赖于前序步骤的产出(如 `changelog` 和 `auto-test` 报告)。 diff --git a/.trae/skills/pr-body-generate/docs/GH_CLI.md b/.trae/skills/pr-body-generate/docs/GH_CLI.md new file mode 100755 index 0000000000..b231442426 --- /dev/null +++ b/.trae/skills/pr-body-generate/docs/GH_CLI.md @@ -0,0 +1,41 @@ +# GitHub CLI (gh) 核心指南 + +GitHub CLI (`gh`) 是 `pr-create-from-body` 技能的备选执行器。当 `GITHUB_TOKEN` 未设置时,技能会尝试使用 `gh` 来创建 Pull Request。 + +## 安装与登录 + +1. **安装**: + * **macOS**: `brew install gh` + * **Windows**: `winget install GitHub.cli` 或 `choco install gh` + +2. **登录**: + * 在终端运行 `gh auth login`。 + * 按照交互式提示操作:选择 `GitHub.com` -> `HTTPS` -> `Login with a web browser`。 + * 浏览器将打开一个页面要求授权。授权后,`gh` 会在本地安全地存储你的凭证。 + +3. **验证**: + * 运行 `gh auth status` 检查你的登录状态和权限。 + +## SSO (单点登录) + +如果目标仓库所属的组织强制使用 SSO,`gh` 在首次访问该组织资源时会自动触发浏览器进行 SSO 授权。只需按提示操作即可。 + +## 使用 + +`pr-create-from-body` 技能在 `mode: auto` 时,会优先检查 `GITHUB_TOKEN`。如果未找到,则会调用本机的 `gh` 命令来创建 PR。 + +**示例命令 (由技能在内部执行):** +```bash +gh pr create \ + --base develop \ + --head your-feature-branch \ + --title "feat: Your great feature" \ + --body-file ./.trae/output/pr.body.local.md +``` + +## 常见问题 + +- **`gh` 命令未找到**: 确保 `gh` 已安装并且其路径已添加到系统的 `PATH` 环境变量中。 +- **403 Forbidden**: + - **权限不足**: 你的 GitHub 账户可能没有对该仓库的写权限。 + - **SSO 问题**: 运行 `gh auth status` 并检查是否已为目标组织授权。如果没有,尝试访问该组织的任一仓库页面,`gh` 可能会自动提示你重新授权。 diff --git a/.trae/skills/pr-body-generate/docs/GITHUB_TOKEN.md b/.trae/skills/pr-body-generate/docs/GITHUB_TOKEN.md new file mode 100755 index 0000000000..0bf6974720 --- /dev/null +++ b/.trae/skills/pr-body-generate/docs/GITHUB_TOKEN.md @@ -0,0 +1,31 @@ +# GitHub Token 核心指南 + +为了让 `pr-body-generate` 和 `pr-create-from-body` 等技能能够与 GitHub 交互(例如,拉取 Issue 标题、创建 PR),你需要一个具有适当权限的个人访问令牌 (Personal Access Token, PAT)。 + +## 获取与配置 + +1. **生成 Token**: + * 前往 GitHub [**Developer settings**](https://github.com/settings/tokens) > **Personal access tokens** > **Fine-grained tokens**。 + * 创建一个新 Token,将其权限范围限定到 `VisActor/VChart` 仓库。 + * **必须权限**: + * `Pull requests`: **Read and write** + * `Contents`: **Read** + +2. **配置环境变量**: + * 将获取到的 Token (通常以 `github_pat_` 开头) 设置为本地环境变量 `GITHUB_TOKEN`。 + * **macOS/Linux**: `export GITHUB_TOKEN="your_token_here"` + * **Windows**: `$env:GITHUB_TOKEN = "your_token_here"` + * 为使其永久生效,请将此命令添加到你的 shell 配置文件中 (如 `.zshrc`, `.bash_profile` 或 PowerShell 的 `$PROFILE`)。 + +## SSO (单点登录) + +如果 `VisActor` 组织开启了 SSO,你的 Token 必须经过授权才能访问组织资源。 + +* **Fine-grained Token**: 在创建时,将 `Resource owner` 设置为 `VisActor` 组织,即可自动关联 SSO。 +* **Classic Token**: 创建后,你可能需要在 Token 列表中找到它,并点击 `Enable SSO` 或 `Configure SSO` 来完成授权。 + +## 安全须知 + +- **最小权限**: 始终为 Token 授予完成任务所需的最小权限。 +- **保护 Token**: 绝不要将 Token 硬编码到代码、提交记录或日志中。环境变量是推荐的安全存储方式。 +- **定期轮换**: 为你的 Token 设置一个合理的过期时间(如 30-90 天),并定期更换。 diff --git a/.trae/skills/pr-body-generate/docs/USAGE.md b/.trae/skills/pr-body-generate/docs/USAGE.md new file mode 100755 index 0000000000..5a8a7c4094 --- /dev/null +++ b/.trae/skills/pr-body-generate/docs/USAGE.md @@ -0,0 +1,36 @@ +# 使用说明:pr-body-generate + +本技能用于自动生成一份内容丰富、格式规范的 Pull Request 正文。 + +## 何时使用 + +- **创建 PR 前**: 在代码提交和 `changelog` 生成之后,使用此技能可以一键生成 PR 的完整描述,节省手动填写模板的时间。 +- **作为流程的一部分**: 在 `auto-flow` 编排中,此技能是创建 PR 之前的关键准备步骤。 + +## 示例对话 + +**场景一: 自动生成正文** + +> **你**: “我已提交了代码和 changelog,现在请帮我生成 PR 正文。” +> +> **Agent**: (执行技能) “PR 正文已生成并保存到 `./.trae/output/pr.body.local.md`。建议标题为 '[Auto] feat: your feature summary'。请审阅内容,然后执行 `pr-create-from-body` 来创建 PR。” + +**场景二: 生成时指定标题和标签** + +> **你**: "执行 `pr-body-generate`,标题是 'feat(vis-component): 新增 Tooltip 组件',标签是 'feature', 'component'。" +> +> **Agent**: (执行技能) “好的,已生成 PR 正文,其中包含了你指定的标签信息,并为你推荐了标题。” + +## 关键参数 + +- `lang`: PR 模板的语言,支持 `zh` (默认) 和 `en`。 +- `title`: 用于生成建议 PR 标题的素材。 +- `rushChangesDir`: Rush 变更日志条目的目录,默认为 `common/changes`。 +- `localBodyFile`: 是否将生成的正文保存到本地文件,默认为 `true`。 +- `autotestReport`: `auto-test` 技能的报告路径,其内容会被摘要进 PR 正文。 + +## 注意事项 + +- **仅生成不创建**: 此技能只负责生成 PR 正文的 `.md` 文件,**不会** 在 GitHub 上创建 PR。创建操作由 `pr-create-from-body` 技能完成。 +- **依赖前序产出**: 生成的正文内容的完整性依赖于之前步骤的产出,例如 `common/changes` 目录下的 `changelog` 文件和 `auto-test` 生成的测试报告。 +- **人工审查**: 自动生成的内容是草稿,强烈建议在执行下一步前,打开本地生成的 `.md` 文件进行审查和必要的修改。 diff --git a/.trae/skills/pr-create-from-body/SKILL.md b/.trae/skills/pr-create-from-body/SKILL.md new file mode 100755 index 0000000000..067639a402 --- /dev/null +++ b/.trae/skills/pr-create-from-body/SKILL.md @@ -0,0 +1,60 @@ +--- +name: pr-create-from-body +description: 'Creates a GitHub Pull Request for the VChart project using a local markdown file as its body. Use this skill as the final step in the PR-creation process, after the PR body has been generated and reviewed. It requires either a `GITHUB_TOKEN` or a logged-in `gh` CLI environment to operate.' +--- + +# 从本地文件创建 PR (pr-create-from-body) + +## 概述 + +本技能用于读取一个本地 Markdown 文件作为 Pull Request 的正文,并在 GitHub 上创建该 PR。它是 `pr-body-generate` 技能的后续步骤,负责将准备好的内容发布出去。 + +## 前置条件 + +- **GitHub 凭证**: 必须在环境中配置 `GITHUB_TOKEN`,或者已安装并登录了 `gh` CLI。 +- **PR 正文文件**: 必须存在一个包含 PR 正文的本地 Markdown 文件。通常由 `pr-body-generate` 技能生成。 +- **分支已推送**: 源分支必须已经推送到远程仓库。 + +## 输入参数 + +| 参数 | 类型 | 是否必填 | 默认值 | 描述 | +| ----------- | ------- | -------- | ---------------------------------- | -------------------------------------------------------------- | +| `title` | string | 是 | (无) | Pull Request 的标题。 | +| `base` | string | 否 | `develop` | PR 的目标分支。 | +| `head` | string | 否 | (空) | PR 的源分支。如果为空,将自动推导当前分支。 | +| `bodyFile` | string | 否 | `./.trae/output/pr.body.local.md` | 包含 PR 正文的本地 Markdown 文件的路径。 | +| `mode` | string | 否 | `auto` | 创建 PR 的方式 (`auto`, `gh`, `rest`)。`auto` 会优先使用 `gh`,其次是 `rest` (基于 `GITHUB_TOKEN`)。 | +| `draft` | boolean | 否 | `false` | 是否将 PR 创建为草稿(Draft)状态。 | +| `labels` | array | 否 | `[]` | 要附加到 PR 的标签列表。 | + +## 输出与成功标准 + +- **主要输出** (`pr_url`): 成功创建的 Pull Request 的 URL。 +- **成功标准** (`pr_created`): Pull Request 已在 GitHub 上成功创建。 + +## 执行步骤 + +1. **参数与环境检查**: + - Agent 会检查 `title` 是否已提供。 + - 确认 `head` 分支,如果未提供则自动检测当前分支。 + - 检查 `bodyFile` 指定的文件是否存在且内容不为空。 + - 根据 `mode` 参数检查 `GITHUB_TOKEN` 或 `gh` CLI 是否可用。 + +2. **(可选)提交变更**: 如果 `commitBeforeCreate` 设置为 `true` 且有未提交的变更,Agent 会先执行一次智能提交(类似于 `commit-smart` 技能)。 + +3. **创建 PR**: + - **gh 模式**: Agent 会使用 `gh pr create` 命令,并通过 `--body-file` 参数直接传入正文文件。 + - **rest 模式**: Agent 会读取 `bodyFile` 的内容,然后通过调用 GitHub REST API (`POST /repos/{owner}/{repo}/pulls`) 来创建 PR。 + - **auto 模式**: 自动选择可用的最佳方式。 + +4. **输出结果**: 如果 PR 创建成功,Agent 会返回该 PR 的 URL。如果失败,则会返回详细的错误信息。 + +## 何时使用 / 边界 + +- **使用时机**: + - 在使用 `pr-body-generate` 生成并(可选地)人工审查了 PR 正文之后,作为发布的最后一步。 + - 当你有一个准备好的 Markdown 文件,并希望用它作为 PR 的描述来快速创建 PR 时。 +- **边界**: + - 此技能强依赖于一个已存在的、内容完备的本地正文文件。 + - 它不会修改 PR 正文内容,只是“按原样”上传。 + - 创建 PR 前,请确保你的 `head` 分支已经包含了所有需要合并的提交,并已推送到远程仓库。 diff --git a/.trae/skills/pr-create-from-body/docs/GH_CLI.md b/.trae/skills/pr-create-from-body/docs/GH_CLI.md new file mode 100755 index 0000000000..b231442426 --- /dev/null +++ b/.trae/skills/pr-create-from-body/docs/GH_CLI.md @@ -0,0 +1,41 @@ +# GitHub CLI (gh) 核心指南 + +GitHub CLI (`gh`) 是 `pr-create-from-body` 技能的备选执行器。当 `GITHUB_TOKEN` 未设置时,技能会尝试使用 `gh` 来创建 Pull Request。 + +## 安装与登录 + +1. **安装**: + * **macOS**: `brew install gh` + * **Windows**: `winget install GitHub.cli` 或 `choco install gh` + +2. **登录**: + * 在终端运行 `gh auth login`。 + * 按照交互式提示操作:选择 `GitHub.com` -> `HTTPS` -> `Login with a web browser`。 + * 浏览器将打开一个页面要求授权。授权后,`gh` 会在本地安全地存储你的凭证。 + +3. **验证**: + * 运行 `gh auth status` 检查你的登录状态和权限。 + +## SSO (单点登录) + +如果目标仓库所属的组织强制使用 SSO,`gh` 在首次访问该组织资源时会自动触发浏览器进行 SSO 授权。只需按提示操作即可。 + +## 使用 + +`pr-create-from-body` 技能在 `mode: auto` 时,会优先检查 `GITHUB_TOKEN`。如果未找到,则会调用本机的 `gh` 命令来创建 PR。 + +**示例命令 (由技能在内部执行):** +```bash +gh pr create \ + --base develop \ + --head your-feature-branch \ + --title "feat: Your great feature" \ + --body-file ./.trae/output/pr.body.local.md +``` + +## 常见问题 + +- **`gh` 命令未找到**: 确保 `gh` 已安装并且其路径已添加到系统的 `PATH` 环境变量中。 +- **403 Forbidden**: + - **权限不足**: 你的 GitHub 账户可能没有对该仓库的写权限。 + - **SSO 问题**: 运行 `gh auth status` 并检查是否已为目标组织授权。如果没有,尝试访问该组织的任一仓库页面,`gh` 可能会自动提示你重新授权。 diff --git a/.trae/skills/pr-create-from-body/docs/GITHUB_TOKEN.md b/.trae/skills/pr-create-from-body/docs/GITHUB_TOKEN.md new file mode 100755 index 0000000000..0bf6974720 --- /dev/null +++ b/.trae/skills/pr-create-from-body/docs/GITHUB_TOKEN.md @@ -0,0 +1,31 @@ +# GitHub Token 核心指南 + +为了让 `pr-body-generate` 和 `pr-create-from-body` 等技能能够与 GitHub 交互(例如,拉取 Issue 标题、创建 PR),你需要一个具有适当权限的个人访问令牌 (Personal Access Token, PAT)。 + +## 获取与配置 + +1. **生成 Token**: + * 前往 GitHub [**Developer settings**](https://github.com/settings/tokens) > **Personal access tokens** > **Fine-grained tokens**。 + * 创建一个新 Token,将其权限范围限定到 `VisActor/VChart` 仓库。 + * **必须权限**: + * `Pull requests`: **Read and write** + * `Contents`: **Read** + +2. **配置环境变量**: + * 将获取到的 Token (通常以 `github_pat_` 开头) 设置为本地环境变量 `GITHUB_TOKEN`。 + * **macOS/Linux**: `export GITHUB_TOKEN="your_token_here"` + * **Windows**: `$env:GITHUB_TOKEN = "your_token_here"` + * 为使其永久生效,请将此命令添加到你的 shell 配置文件中 (如 `.zshrc`, `.bash_profile` 或 PowerShell 的 `$PROFILE`)。 + +## SSO (单点登录) + +如果 `VisActor` 组织开启了 SSO,你的 Token 必须经过授权才能访问组织资源。 + +* **Fine-grained Token**: 在创建时,将 `Resource owner` 设置为 `VisActor` 组织,即可自动关联 SSO。 +* **Classic Token**: 创建后,你可能需要在 Token 列表中找到它,并点击 `Enable SSO` 或 `Configure SSO` 来完成授权。 + +## 安全须知 + +- **最小权限**: 始终为 Token 授予完成任务所需的最小权限。 +- **保护 Token**: 绝不要将 Token 硬编码到代码、提交记录或日志中。环境变量是推荐的安全存储方式。 +- **定期轮换**: 为你的 Token 设置一个合理的过期时间(如 30-90 天),并定期更换。 diff --git a/.trae/skills/pr-create-from-body/docs/USAGE.md b/.trae/skills/pr-create-from-body/docs/USAGE.md new file mode 100755 index 0000000000..6acb1c330e --- /dev/null +++ b/.trae/skills/pr-create-from-body/docs/USAGE.md @@ -0,0 +1,37 @@ +# 使用说明:pr-create-from-body + +本技能用于将在本地准备好的 Pull Request 正文文件发布到 GitHub,完成 PR 的创建。 + +## 何时使用 + +- **发布的最后一步**: 当你已经生成并审查了 PR 正文后,使用此技能来完成最后的创建步骤。 +- **手动创建**: 如果你手动编写了一个 `.md` 文件作为 PR 正文,也可以使用此技能来创建 PR。 + +## 示例对话 + +**场景一: 使用默认正文文件创建 PR** + +> **你**: “PR 正文已经准备好了,现在请帮我用 'feat: add new chart type' 这个标题创建一个 PR。” +> +> **Agent**: (执行技能) “好的。正在读取 `./.trae/output/pr.body.local.md` 的内容... Pull Request 已创建:https://github.com/VisActor/VChart/pull/123” + +**场景二: 创建一个草稿 PR 并添加标签** + +> **你**: “执行 `pr-create-from-body`,标题是 'WIP: refactor data processor',设为草稿模式,并加上 'refactor' 和 'WIP' 标签。” +> +> **Agent**: (执行技能) “已成功创建一个草稿 Pull Request,并添加了指定标签。链接是: ...” + +## 关键参数 + +- `title`: **(必填)** Pull Request 的标题。 +- `base`: PR 的目标分支,默认为 `develop`。 +- `head`: PR 的源分支。如果留空,将自动使用当前分支。 +- `bodyFile`: 包含 PR 正文的本地文件路径,默认为 `./.trae/output/pr.body.local.md`。 +- `mode`: 创建 PR 的方式,`auto` (默认) 会优先尝试 `gh` CLI,失败则回退到使用 `GITHUB_TOKEN` 的 REST API。 +- `draft`: 是否将 PR 创建为草稿状态,默认为 `false`。 + +## 注意事项 + +- **凭证**: 执行前,必须确保 `GITHUB_TOKEN` 环境变量已设置,或 `gh` CLI 已安装并登录。请参阅本技能目录下的 `docs/GITHUB_TOKEN.md` 和 `docs/GH_CLI.md`。 +- **分支推送**: 在创建 PR 之前,请务必确保你的本地分支 (`head`) 已经推送到 GitHub 远程仓库,否则 GitHub 无法找到该分支。 +- **正文文件**: 确认 `bodyFile` 指向的文件存在且内容正确。 diff --git a/common/changes/@visactor/vchart/chore-auto-flow-experience_2025-12-26-07-42.json b/common/changes/@visactor/vchart/chore-auto-flow-experience_2025-12-26-07-42.json new file mode 100644 index 0000000000..dd524f3bdf --- /dev/null +++ b/common/changes/@visactor/vchart/chore-auto-flow-experience_2025-12-26-07-42.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "chore(auto-flow): optimize auto flow", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "lixuef1313@163.com" +} \ No newline at end of file diff --git a/common/changes/@visactor/vchart/fix-heatmap-label_2025-12-26-08-38.json b/common/changes/@visactor/vchart/fix-heatmap-label_2025-12-26-08-38.json new file mode 100644 index 0000000000..13ba46254f --- /dev/null +++ b/common/changes/@visactor/vchart/fix-heatmap-label_2025-12-26-08-38.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: fix default lineWidth for heatmap label\n\n", + "type": "none", + "packageName": "@visactor/vchart" + } + ], + "packageName": "@visactor/vchart", + "email": "dingling112@gmail.com" +} \ No newline at end of file diff --git a/docs/assets/changelog/en/release.md b/docs/assets/changelog/en/release.md index 5f1bcee2bb..66c9e874d6 100644 --- a/docs/assets/changelog/en/release.md +++ b/docs/assets/changelog/en/release.md @@ -1,7 +1,27 @@ -# v2.0.11 - -2025-12-11 - +# v2.0.12 + +2025-12-25 + +**🆕 New Features** + +- **@visactor/vchart**: Support `autoLabelMaxWidth` configuration in `CircleAxis` by @xuefei1313 in https://github.com/VisActor/VChart/pull/4357 +- **@visactor/vchart**: Add support for chart disappear state by @xuefei1313 in https://github.com/VisActor/VChart/pull/4341 +- **@visactor/vchart**: Optimize heatmap shape rendering logic by @xuefei1313 in https://github.com/VisActor/VChart/pull/4377 +- **@visactor/vchart**: Optimize map zoom interaction and add `zoomRate` configuration by @xuefei1313 in https://github.com/VisActor/VChart/pull/4373 + +**🐛 Bug Fixes** + +- **@visactor/vchart**: Fix axis title layout issue by @xuefei1313 in https://github.com/VisActor/VChart/pull/4371 + +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.11...v2.0.12 + +[more detail about v2.0.12](https://github.com/VisActor/VChart/releases/tag/v2.0.12) + + +# v2.0.11 + +2025-12-11 + # v2.0.11 2025-12-11 @@ -21,140 +41,141 @@ **Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.10...v2.0.11 -[more detail about v2.0.11](https://github.com/VisActor/VChart/releases/tag/v2.0.11) - -[more detail about v2.0.11](https://github.com/VisActor/VChart/releases/tag/v2.0.11) - -# v2.0.10 - -2025-11-28 - -**🆕 New Features** - -- **@visactor/vchart**: Enhance boxplot features by @xile611 in https://github.com/VisActor/VChart/pull/4323 - -**🐛 Bug Fixes** - -- **@visactor/vchart**: Upgrade vrender dependency to fix rose chart issues by @xuefei1313 in https://github.com/VisActor/VChart/pull/4315 -- **@visactor/vchart**: Upgrade vrender dependency to fix animation issues by @xuefei1313 in https://github.com/VisActor/VChart/pull/4325 -- **@visactor/vchart**: Fix extension mark update logic by @xile611 in https://github.com/VisActor/VChart/pull/4318 -- **@visactor/vchart**: Fix font family setting issue by @xuefei1313 in https://github.com/VisActor/VChart/pull/4324 -- **@visactor/vchart**: Fix issue with setDimensionIndex by @xuefei1313 in https://github.com/VisActor/VChart/pull/4291 - -**📖 Documentation** - -- **@visactor/vchart**: Add candlestick chart guide by @xuefei1313 in https://github.com/VisActor/VChart/pull/4310 -- **@visactor/vchart**: Add theme development guide by @xuanhun in https://github.com/VisActor/VChart/pull/4322 -- **@visactor/vchart**: Add map rewind guide by @xuefei1313 in https://github.com/VisActor/VChart/pull/4326 -- **@visactor/vchart**: Add 3D registration content to guide by @xuefei1313 in https://github.com/VisActor/VChart/pull/4312 -- **@visactor/vchart**: Fix documentation for common chart option labelLayout by @xuefei1313 in https://github.com/VisActor/VChart/pull/4316 - -**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.9...v2.0.10 - -[more detail about v2.0.10](https://github.com/VisActor/VChart/releases/tag/v2.0.10) - -# v2.0.9 - -2025-11-18 - -**🆕 New Features** - -- **@visactor/react-vchart**: Add export for registerChartResizeZoomPlugin by @xuefei1313 in https://github.com/VisActor/VChart/pull/4286 -- **@visactor/vchart**: Support effect animation by @purpose233 in https://github.com/VisActor/VChart/pull/4299 -- **@visactor/vchart**: Enhance datazoom and fix bugs by @skie1997 in https://github.com/VisActor/VChart/pull/4065 - -**🐛 Bug Fixes** - -- **@visactor/vchart-extension**: Fix the vchart-extension packaged artifacts contained an extra version by @xuefei1313 in https://github.com/VisActor/VChart/pull/4277 -- **@visactor/vchart**: Fix markline auto range by @xuefei1313 in https://github.com/VisActor/VChart/pull/4290 - -**📖 Documentation** - -- **@visactor/vchart**: Fix registerMorph error in example by @xuefei1313 in https://github.com/VisActor/VChart/pull/4285 -- **@visactor/vchart**: Add candlestick demo by @xuefei1313 in https://github.com/VisActor/VChart/pull/4297 - -**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.7...v2.0.9 - -[more detail about v2.0.9](https://github.com/VisActor/VChart/releases/tag/v2.0.9) - -# v2.0.7 - -2025-11-03 - -🆕 New Features - -@visactor/vchart: Support resize zoom chart plugin by @xuefei1313 in https://github.com/VisActor/VChart/pull/4241 -@visactor/vchart: Register transform boxplot by @xile611 in https://github.com/VisActor/VChart/pull/4268 -@visactor/vchart: Add translate-issues workflow configuration by @xuefei1313 in https://github.com/VisActor/VChart/pull/4264 -@visactor/vchart: Add regression-lines in vchart-extension by @xile611 in https://github.com/VisActor/VChart/pull/4245 -@visactor/vchart: Change vrender dependencies, see https://github.com/VisActor/VChart/pull/4224 - -🐛 Bug Fixes - -@visactor/vchart: Fix crosshair not hide by @xile611 in https://github.com/VisActor/VChart/pull/4252 -@visactor/vchart: Fix issue of layout by @xuefei1313 in https://github.com/VisActor/VChart/pull/4249 -@visactor/vchart: Fix logistic regression line by @xile611 in https://github.com/VisActor/VChart/pull/4263 -@visactor/vchart: Fix support regression line for grouped scatter by @xile611 in https://github.com/VisActor/VChart/pull/4248 -@visactor/vchart: Fix check if stackData is empty by @kkxxkk2019 in https://github.com/VisActor/VChart/pull/4244 -@visactor/vchart: Fix issue of waterfall stack total by @xuefei1313 in https://github.com/VisActor/VChart/pull/4243 - -[more detail about v2.0.7](https://github.com/VisActor/VChart/releases/tag/v2.0.7) - -# v2.0.6 - -2025-10-14 - -**What's Changed** - -- fix: fix the issue of legend pager by @xuefei1313 in https://github.com/VisActor/VChart/pull/4212 -- Feat/support calc in formatter by @xuefei1313 in https://github.com/VisActor/VChart/pull/4211 -- Fix/fix error of markline when series no data by @xuefei1313 in https://github.com/VisActor/VChart/pull/4216 -- feat: update bugreport metthod by @xuanhun in https://github.com/VisActor/VChart/pull/4221 -- feat: upgrade vrender to fix animation bug by @xuefei1313 in https://github.com/VisActor/VChart/pull/4222 -- feat: support waterfallType in waterfall chart by @xuefei1313 in https://github.com/VisActor/VChart/pull/4220 -- feat: change vrender dependencies by @xuefei1313 in https://github.com/VisActor/VChart/pull/4224 - -**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.5...v2.0.6 - -[more detail about v2.0.6](https://github.com/VisActor/VChart/releases/tag/v2.0.6) - -# v2.0.5 - -2025-09-19 - -[more detail about v2.0.5](https://github.com/VisActor/VChart/releases/tag/v2.0.5) - -# v2.0.2 - -2025-07-28 - -**🆕 New feature** - -- **@visactor/vchart**: add the afterClearRect hook of render - -**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.1...v2.0.2 - -[more detail about v2.0.2](https://github.com/VisActor/VChart/releases/tag/v2.0.2) - -# v2.0.1 - -2025-07-24 - -**🆕 New feature** - -- **@visactor/vchart**: add config to avoid brush state update. close [#4035](https://github.com/VisActor/VChart/issues/4035) -- **@visactor/vchart**: optimize datazoom animation effect -- **@visactor/vchart**: add the afterClearScreen hook of render - -**🐛 Bug fix** - -- **@visactor/vchart**: fix issue with 3d chart grid -- **@visactor/vchart**: tickData of axis should update when `sampling` is changed, fix [#4059](https://github.com/VisActor/VChart/issues/4059) -- **@visactor/vchart**: only calculate multi layer label items when need, fix [#4056](https://github.com/VisActor/VChart/issues/4056) -- **@visactor/vchart**: fix resize error when remake, and re-normal aniamtion bug, fix [#4070](https://github.com/VisActor/VChart/issues/4070) -- **@visactor/vchart**: fix issue with feishu block and call setenv when create vchart -- **@visactor/vchart**: fix bug of tooltip triggerOff & tooltip lock -- **@visactor/vchart**: fix tooltip throw error when some tooltip processor is undefined, fix [#4044](https://github.com/VisActor/VChart/issues/4044) -- **@visactor/vchart**: fix `textAlign` not works in tooltip.style.titleLabel, fix [#4043](https://github.com/VisActor/VChart/issues/4043) - -[more detail about v2.0.1](https://github.com/VisActor/VChart/releases/tag/v2.0.1) + +[more detail about v2.0.11](https://github.com/VisActor/VChart/releases/tag/v2.0.11) + +[more detail about v2.0.11](https://github.com/VisActor/VChart/releases/tag/v2.0.11) + +# v2.0.10 + +2025-11-28 + +**🆕 New Features** + +- **@visactor/vchart**: Enhance boxplot features by @xile611 in https://github.com/VisActor/VChart/pull/4323 + +**🐛 Bug Fixes** + +- **@visactor/vchart**: Upgrade vrender dependency to fix rose chart issues by @xuefei1313 in https://github.com/VisActor/VChart/pull/4315 +- **@visactor/vchart**: Upgrade vrender dependency to fix animation issues by @xuefei1313 in https://github.com/VisActor/VChart/pull/4325 +- **@visactor/vchart**: Fix extension mark update logic by @xile611 in https://github.com/VisActor/VChart/pull/4318 +- **@visactor/vchart**: Fix font family setting issue by @xuefei1313 in https://github.com/VisActor/VChart/pull/4324 +- **@visactor/vchart**: Fix issue with setDimensionIndex by @xuefei1313 in https://github.com/VisActor/VChart/pull/4291 + +**📖 Documentation** + +- **@visactor/vchart**: Add candlestick chart guide by @xuefei1313 in https://github.com/VisActor/VChart/pull/4310 +- **@visactor/vchart**: Add theme development guide by @xuanhun in https://github.com/VisActor/VChart/pull/4322 +- **@visactor/vchart**: Add map rewind guide by @xuefei1313 in https://github.com/VisActor/VChart/pull/4326 +- **@visactor/vchart**: Add 3D registration content to guide by @xuefei1313 in https://github.com/VisActor/VChart/pull/4312 +- **@visactor/vchart**: Fix documentation for common chart option labelLayout by @xuefei1313 in https://github.com/VisActor/VChart/pull/4316 + +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.9...v2.0.10 + +[more detail about v2.0.10](https://github.com/VisActor/VChart/releases/tag/v2.0.10) + +# v2.0.9 + +2025-11-18 + +**🆕 New Features** + +- **@visactor/react-vchart**: Add export for registerChartResizeZoomPlugin by @xuefei1313 in https://github.com/VisActor/VChart/pull/4286 +- **@visactor/vchart**: Support effect animation by @purpose233 in https://github.com/VisActor/VChart/pull/4299 +- **@visactor/vchart**: Enhance datazoom and fix bugs by @skie1997 in https://github.com/VisActor/VChart/pull/4065 + +**🐛 Bug Fixes** + +- **@visactor/vchart-extension**: Fix the vchart-extension packaged artifacts contained an extra version by @xuefei1313 in https://github.com/VisActor/VChart/pull/4277 +- **@visactor/vchart**: Fix markline auto range by @xuefei1313 in https://github.com/VisActor/VChart/pull/4290 + +**📖 Documentation** + +- **@visactor/vchart**: Fix registerMorph error in example by @xuefei1313 in https://github.com/VisActor/VChart/pull/4285 +- **@visactor/vchart**: Add candlestick demo by @xuefei1313 in https://github.com/VisActor/VChart/pull/4297 + +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.7...v2.0.9 + +[more detail about v2.0.9](https://github.com/VisActor/VChart/releases/tag/v2.0.9) + +# v2.0.7 + +2025-11-03 + +🆕 New Features + +@visactor/vchart: Support resize zoom chart plugin by @xuefei1313 in https://github.com/VisActor/VChart/pull/4241 +@visactor/vchart: Register transform boxplot by @xile611 in https://github.com/VisActor/VChart/pull/4268 +@visactor/vchart: Add translate-issues workflow configuration by @xuefei1313 in https://github.com/VisActor/VChart/pull/4264 +@visactor/vchart: Add regression-lines in vchart-extension by @xile611 in https://github.com/VisActor/VChart/pull/4245 +@visactor/vchart: Change vrender dependencies, see https://github.com/VisActor/VChart/pull/4224 + +🐛 Bug Fixes + +@visactor/vchart: Fix crosshair not hide by @xile611 in https://github.com/VisActor/VChart/pull/4252 +@visactor/vchart: Fix issue of layout by @xuefei1313 in https://github.com/VisActor/VChart/pull/4249 +@visactor/vchart: Fix logistic regression line by @xile611 in https://github.com/VisActor/VChart/pull/4263 +@visactor/vchart: Fix support regression line for grouped scatter by @xile611 in https://github.com/VisActor/VChart/pull/4248 +@visactor/vchart: Fix check if stackData is empty by @kkxxkk2019 in https://github.com/VisActor/VChart/pull/4244 +@visactor/vchart: Fix issue of waterfall stack total by @xuefei1313 in https://github.com/VisActor/VChart/pull/4243 + +[more detail about v2.0.7](https://github.com/VisActor/VChart/releases/tag/v2.0.7) + +# v2.0.6 + +2025-10-14 + +**What's Changed** + +- fix: fix the issue of legend pager by @xuefei1313 in https://github.com/VisActor/VChart/pull/4212 +- Feat/support calc in formatter by @xuefei1313 in https://github.com/VisActor/VChart/pull/4211 +- Fix/fix error of markline when series no data by @xuefei1313 in https://github.com/VisActor/VChart/pull/4216 +- feat: update bugreport metthod by @xuanhun in https://github.com/VisActor/VChart/pull/4221 +- feat: upgrade vrender to fix animation bug by @xuefei1313 in https://github.com/VisActor/VChart/pull/4222 +- feat: support waterfallType in waterfall chart by @xuefei1313 in https://github.com/VisActor/VChart/pull/4220 +- feat: change vrender dependencies by @xuefei1313 in https://github.com/VisActor/VChart/pull/4224 + +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.5...v2.0.6 + +[more detail about v2.0.6](https://github.com/VisActor/VChart/releases/tag/v2.0.6) + +# v2.0.5 + +2025-09-19 + +[more detail about v2.0.5](https://github.com/VisActor/VChart/releases/tag/v2.0.5) + +# v2.0.2 + +2025-07-28 + +**🆕 New feature** + +- **@visactor/vchart**: add the afterClearRect hook of render + +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.1...v2.0.2 + +[more detail about v2.0.2](https://github.com/VisActor/VChart/releases/tag/v2.0.2) + +# v2.0.1 + +2025-07-24 + +**🆕 New feature** + +- **@visactor/vchart**: add config to avoid brush state update. close [#4035](https://github.com/VisActor/VChart/issues/4035) +- **@visactor/vchart**: optimize datazoom animation effect +- **@visactor/vchart**: add the afterClearScreen hook of render + +**🐛 Bug fix** + +- **@visactor/vchart**: fix issue with 3d chart grid +- **@visactor/vchart**: tickData of axis should update when `sampling` is changed, fix [#4059](https://github.com/VisActor/VChart/issues/4059) +- **@visactor/vchart**: only calculate multi layer label items when need, fix [#4056](https://github.com/VisActor/VChart/issues/4056) +- **@visactor/vchart**: fix resize error when remake, and re-normal aniamtion bug, fix [#4070](https://github.com/VisActor/VChart/issues/4070) +- **@visactor/vchart**: fix issue with feishu block and call setenv when create vchart +- **@visactor/vchart**: fix bug of tooltip triggerOff & tooltip lock +- **@visactor/vchart**: fix tooltip throw error when some tooltip processor is undefined, fix [#4044](https://github.com/VisActor/VChart/issues/4044) +- **@visactor/vchart**: fix `textAlign` not works in tooltip.style.titleLabel, fix [#4043](https://github.com/VisActor/VChart/issues/4043) + +[more detail about v2.0.1](https://github.com/VisActor/VChart/releases/tag/v2.0.1) diff --git a/docs/assets/changelog/zh/release.md b/docs/assets/changelog/zh/release.md index 88ff076796..d40e9eaeaf 100644 --- a/docs/assets/changelog/zh/release.md +++ b/docs/assets/changelog/zh/release.md @@ -1,3 +1,22 @@ +# v2.0.12 + +2025-12-25 + +**🆕 新增功能** + +- **@visactor/vchart**: 极坐标轴(CircleAxis)支持 `autoLabelMaxWidth` 配置 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4357 +- **@visactor/vchart**: 新增图表消失(Disappear)状态支持 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4341 +- **@visactor/vchart**: 优化热力图(Heatmap)形状渲染逻辑 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4377 +- **@visactor/vchart**: 优化地图(Map)zoom交互,增加 `zoomRate` 配置 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4373 + +**🐛 问题修复** + +- **@visactor/vchart**: 修复坐标轴标题(Axes Title)的布局问题 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4371 + +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.11...v2.0.12 + +[更多详情请查看 v2.0.12](https://github.com/VisActor/VChart/releases/tag/v2.0.12) + # v2.0.11 2025-12-11 @@ -149,3 +168,4 @@ - **@visactor/vchart**:修复 `tooltip.style.titleLabel` 的 `textAlign` 不生效问题,修复 [#4043](https://github.com/VisActor/VChart/issues/4043) [更多详情请查看 v2.0.1](https://github.com/VisActor/VChart/releases/tag/v2.0.1) + diff --git a/docs/assets/examples/en/area-chart/segment-range-area.md b/docs/assets/examples/en/area-chart/segment-range-area.md index f3d4770360..1fcd3dd428 100644 --- a/docs/assets/examples/en/area-chart/segment-range-area.md +++ b/docs/assets/examples/en/area-chart/segment-range-area.md @@ -97,15 +97,13 @@ const spec = { itemContent: { type: 'text', autoRotate: false, - text: { + style: { text: 'BALANCE AGAINST', - style: { - fontSize: 14, - fontWeight: 'bold', - fill: 'rgba(0,0,0,0.45)', - textAlign: 'center', - textBaseline: 'middle' - } + fontSize: 14, + fontWeight: 'bold', + fill: 'rgba(0,0,0,0.45)', + textAlign: 'center', + textBaseline: 'middle' } }, itemLine: { @@ -121,15 +119,14 @@ const spec = { offsetX: -40, type: 'text', autoRotate: false, - text: { + style: { text: ['BALANCE in', 'FAVOUR of ENGLAND'], - style: { - fontSize: 14, - fontWeight: 'bold', - fill: 'rgba(0,0,0,0.45)', - textAlign: 'left', - textBaseline: 'middle' - } + + fontSize: 14, + fontWeight: 'bold', + fill: 'rgba(0,0,0,0.45)', + textAlign: 'left', + textBaseline: 'middle' } }, itemLine: { diff --git a/docs/assets/examples/en/bar-chart/bar-markPoint.md b/docs/assets/examples/en/bar-chart/bar-markPoint.md index 5f31dadc0a..88ac20432d 100644 --- a/docs/assets/examples/en/bar-chart/bar-markPoint.md +++ b/docs/assets/examples/en/bar-chart/bar-markPoint.md @@ -83,12 +83,7 @@ const spec = { type: 'text', autoRotate: false, text: { - dy: 14, text: '2 mins', - style: { - fill: 'white', - fontSize: 14 - }, labelBackground: { padding: [5, 10, 5, 10], style: { @@ -96,6 +91,11 @@ const spec = { cornerRadius: 5 } } + }, + style: { + dy: 14, + fill: 'white', + fontSize: 14 } }, itemLine: { diff --git a/docs/assets/examples/en/marker/geo-mark-point.md b/docs/assets/examples/en/marker/geo-mark-point.md index f829bd4a3f..1841abfddc 100644 --- a/docs/assets/examples/en/marker/geo-mark-point.md +++ b/docs/assets/examples/en/marker/geo-mark-point.md @@ -17,91 +17,91 @@ option: mapChart#markPoint ## Demo source ```javascript livedemo - const response1 = await fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/map-mark-point.json'); - const dataJson = await response1.json(); - const data = dataJson.features.map(d => d['properties']) - const minValue = Math.min(...data.map(d => d.scores)) - const maxValue = Math.max(...data.map(d => d.scores)) +const response1 = await fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/map-mark-point.json'); +const dataJson = await response1.json(); +const data = dataJson.features.map(d => d['properties']); +const minValue = Math.min(...data.map(d => d.scores)); +const maxValue = Math.max(...data.map(d => d.scores)); +const response2 = await fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/geojson/usa.json'); +const geojson = await response2.json(); +VChart.registerMap('usa', geojson); - const response2 = await fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/geojson/usa.json'); - const geojson = await response2.json(); - VChart.registerMap('usa', geojson); +function sizeScale(value, domain, range) { + const t = (value - domain[0]) / (domain[1] - domain[0]); + const newValue = (range[1] - range[0]) * t + range[0]; + return newValue; +} - function sizeScale(value, domain, range) { - const t = (value - domain[0]) / (domain[1] - domain[0]); - const newValue = (range[1] - range[0]) * t + range[0]; - return newValue; +const spec = { + type: 'map', + title: { + text: 'Opioid Overdose Rates (per 100,000) by Year: 2017' + }, + color: { + type: 'linear', + range: ['rgb(252,250,97)', 'rgb(252,150,134)', 'rgb(87,33,15)'] + }, + area: { + style: { + fill: { + field: 'scores', + scale: 'color', + changeDomain: 'replace' + } } - - const spec = { - type: 'map', - title: { - text: 'Opioid Overdose Rates (per 100,000) by Year: 2017', - }, - color: { - type: 'linear', - range: ['rgb(252,250,97)', 'rgb(252,150,134)', 'rgb(87,33,15)'] - }, - area: { - style: { - fill: { - field: 'scores', - scale: 'color', - changeDomain: 'replace' - } - } - }, - data: [ - { - values: data - } - ], - nameField: 'name', - valueField: 'scores', - nameProperty: 'name', - map: 'usa', - region: [ - { - roam: true, - projection: { - type: 'albersUsa' - } - } - ], - legends: [ - { - visible: true, - type: 'color', - field: 'scores', - orient: 'bottom', - position: 'start', - title: { - visible: true, - text: 'Population' - } - } - ], - markPoint: data.map(d => { - return { - areaName: d.name, - itemLine: { - visible: false, - }, - itemContent: { - type: 'symbol', - autoRotate: false, - offsetX: -10, - offsetY: -5, - symbolStyle: { - size: sizeScale(d.scores, [minValue, maxValue], [20, 40]), - fill: '#FF6347', - symbolType: '' - } - } - } - }) + }, + data: [ + { + values: data + } + ], + nameField: 'name', + valueField: 'scores', + nameProperty: 'name', + map: 'usa', + region: [ + { + roam: true, + projection: { + type: 'albersUsa' + } + } + ], + legends: [ + { + visible: true, + type: 'color', + field: 'scores', + orient: 'bottom', + position: 'start', + title: { + visible: true, + text: 'Population' + } + } + ], + markPoint: data.map(d => { + return { + areaName: d.name, + itemLine: { + visible: false + }, + itemContent: { + type: 'symbol', + autoRotate: false, + offsetX: -10, + offsetY: -5, + style: { + size: sizeScale(d.scores, [minValue, maxValue], [20, 40]), + fill: '#FF6347', + symbolType: + '' + } + } }; + }) +}; const vchart = new VChart(spec, { dom: CONTAINER_ID }); vchart.renderSync(); diff --git a/docs/assets/examples/en/marker/mark-area-range.md b/docs/assets/examples/en/marker/mark-area-range.md index d5b02d3114..ee2370671c 100644 --- a/docs/assets/examples/en/marker/mark-area-range.md +++ b/docs/assets/examples/en/marker/mark-area-range.md @@ -122,13 +122,11 @@ const spec = { offsetY: 0, type: 'image', autoRotate: false, - image: { - style: { - dx: -55, - width: 30, - height: 30, - image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/%E7%AE%AD%E5%A4%B4%20%E4%B8%8B%E9%99%8D.png' - } + style: { + dx: -55, + width: 30, + height: 30, + image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/%E7%AE%AD%E5%A4%B4%20%E4%B8%8B%E9%99%8D.png' } } }, @@ -144,13 +142,11 @@ const spec = { type: 'image', offsetY: 0, autoRotate: false, - image: { - style: { - dx: -50, - width: 30, - height: 30, - image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/%E4%B8%8A%E5%8D%87.png' - } + style: { + dx: -50, + width: 30, + height: 30, + image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/%E4%B8%8A%E5%8D%87.png' } } } diff --git a/docs/assets/examples/en/marker/mark-area-with-label.md b/docs/assets/examples/en/marker/mark-area-with-label.md index 7b4f14e7e1..7301588915 100644 --- a/docs/assets/examples/en/marker/mark-area-with-label.md +++ b/docs/assets/examples/en/marker/mark-area-with-label.md @@ -216,13 +216,11 @@ const spec = { itemContent: { type: 'image', autoRotate: false, - image: { - style: { - dy: -6, - width: 30, - height: 30, - image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/%E7%AE%AD%E5%A4%B4%20%E4%B8%8B%E9%99%8D.png' - } + style: { + dy: -6, + width: 30, + height: 30, + image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/%E7%AE%AD%E5%A4%B4%20%E4%B8%8B%E9%99%8D.png' } } }, @@ -238,14 +236,12 @@ const spec = { itemContent: { type: 'image', autoRotate: false, - image: { - style: { - dy: -6, - dx: 8, - width: 30, - height: 30, - image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/%E4%B8%8A%E5%8D%87.png' - } + style: { + dy: -6, + dx: 8, + width: 30, + height: 30, + image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/%E4%B8%8A%E5%8D%87.png' } } } diff --git a/docs/assets/examples/en/marker/mark-point-basic.md b/docs/assets/examples/en/marker/mark-point-basic.md index cd959b17fe..27051df3a4 100644 --- a/docs/assets/examples/en/marker/mark-point-basic.md +++ b/docs/assets/examples/en/marker/mark-point-basic.md @@ -32,820 +32,819 @@ Data point positioning: - The `itemContent.autoRotate` attribute declares whether the annotation content automatically rotates to the direction parallel to the guide line. - The `itemContent.richText` attribute declares the annotation content style when `itemContent.type: richText`, and can also be applied to other annotation content types. - `targetSymbol` is declared as a prefix mark, used to mark data points and highlight mark points. + ## Demo source ```javascript livedemo - const spec = { - type: 'line', - xField: 'year', - yField: 'population', - axes: [ - { - orient: 'bottom', - type: 'linear', - min: 1868, - max: 2016 - } - ], - markPoint: [ - { - coordinate: { - year: '1878', - population: 100 - }, - itemContent: { - offsetY: -100, - offsetX: 100, - type: 'text', - autoRotate: false, - confine: true, - text: { - text: '1878 population was 148', +const spec = { + type: 'line', + xField: 'year', + yField: 'population', + axes: [ + { + orient: 'bottom', + type: 'linear', + min: 1868, + max: 2016 + } + ], + markPoint: [ + { + coordinate: { + year: '1878', + population: 100 + }, + itemContent: { + offsetY: -100, + offsetX: 100, + type: 'text', + autoRotate: false, + confine: true, + style: { + text: '1878 population was 148' + } + }, + targetSymbol: { + visible: true + }, + itemLine: { + type: 'type-arc', + arcRatio: 0.4, + startSymbol: { + size: 10, + style: { + stroke: '#E8346D', + symbolType: 'triangle' } }, - targetSymbol: { - visible: true, - }, - itemLine: { - type: 'type-arc', - arcRatio: 0.4, - startSymbol: { - size: 10, - style: { - stroke: '#E8346D', - symbolType: 'triangle' - } - }, - line: { - style: { - stroke: '#E8346D' - } + line: { + style: { + stroke: '#E8346D' } } + } + }, + { + coordinate: { + year: '2016', + population: 899447 }, - { - coordinate: { - year: '2016', - population: 899447 - }, - itemContent: { - offsetY: 40, - // offsetX: -200, - type: 'richText', - autoRotate: false, - confine: true, - position: 'insideBottom', - richText: { - style: { - width: 100, - height: 50, - dx: 110, - dy: 10, - textConfig: [ - { - text: '2016\n', - fontWeight: 'bold', - fontSize: 13, - fill: '#E8346D', - fontFamily: 'Times New Roman' - }, - { - text: 'population was 899447', - fontSize: 10, - fill: '#E8346D', - fontFamily: 'Times New Roman' - } - ] + itemContent: { + offsetY: 40, + // offsetX: -200, + type: 'richText', + autoRotate: false, + confine: true, + position: 'insideBottom', + style: { + width: 100, + height: 50, + dx: 110, + dy: 10, + textConfig: [ + { + text: '2016\n', + fontWeight: 'bold', + fontSize: 13, + fill: '#E8346D', + fontFamily: 'Times New Roman' + }, + { + text: 'population was 899447', + fontSize: 10, + fill: '#E8346D', + fontFamily: 'Times New Roman' } + ] + } + }, + itemLine: { + type: 'type-do', + startSymbol: { + size: 24, + style: { + stroke: '#E8346D' } }, - itemLine: { - type: 'type-do', - startSymbol: { - size: 24, - style: { - stroke: '#E8346D' - } - }, - line: { - style: { - stroke: '#E8346D' - } + line: { + style: { + stroke: '#E8346D' } } } - ], - point: { - style: { - visible: false - } - }, - line: { - style: { - lineWidth: 2 - } - }, - title: { - text: 'Population History - Line Chart', - textStyle: { - lineWidth: 3, - fill: '#333', - fontSize: 20, - fontFamily: 'Times New Roman' - } - }, - data: { - id: 'data2', - values: [ - { - census_year: true, - year: 2016, - source: 'CoE', - population: 899447 - }, - { - census_year: true, - year: 2014, - source: 'CoE', - population: 877926 - }, - { - year: 2013, - source: 'CoE 6', - population: 847712 - }, - { - census_year: true, - year: 2012, - source: 'CoE', - population: 817498 - }, - { - year: 2010, - source: 'CoE 6', - population: 797320 - }, - { - census_year: true, - year: 2009, - source: 'CoE', - population: 782439 - }, - { - census_year: true, - year: 2008, - source: 'CoE', - population: 752412 - }, - { - year: 2007, - source: 'CoE 6', - population: 741392 - }, - { - census_year: true, - year: 2005, - source: 'CoE', - population: 712391 - }, - { - year: 2004, - source: 'CoE 6', - population: 698631 - }, - { - year: 2003, - source: 'CoE 6', - population: 684871 - }, - { - year: 2002, - source: 'CoE 6', - population: 671110 - }, - { - year: 2000, - source: 'CoE 6', - population: 652817 - }, - { - census_year: true, - year: 1999, - source: 'CoE', - population: 648284 - }, - { - year: 1998, - source: 'CoE 6', - population: 637625 - }, - { - year: 1997, - source: 'CoE 6', - population: 626965 - }, - { - year: 1995, - source: 'CoE 6', - population: 619870 - }, - { - year: 1994, - source: 'CoE 6', - population: 623435 - }, - { - census_year: true, - year: 1993, - source: 'CoE', - population: 626999 - }, - { - census_year: true, - year: 1992, - source: 'CoE', - population: 618195 - }, - { - census_year: true, - year: 1990, - source: 'CoE', - population: 605538 - }, - { - census_year: true, - year: 1989, - source: 'CoE', - population: 583872 - }, - { - year: 1988, - source: 'CoE', - population: 580061 - }, - { - census_year: true, - year: 1987, - source: 'CoE', - population: 576249 - }, - { - year: 1985, - source: 'CoE 6', - population: 567699 - }, - { - year: 1984, - source: 'CoE 6', - population: 563892 - }, - { - census_year: true, - year: 1983, - source: 'CoE', - population: 560085 - }, - { - census_year: true, - year: 1982, - source: 'CoE 1', - population: 551314 - }, - { - census_year: true, - year: 1980, - source: 'CoE', - population: 505773 - }, - { - census_year: true, - year: 1979, - source: 'CoE', - population: 491359 - }, - { - census_year: true, - year: 1978, - source: 'CoE', - population: 478066 - }, - { - census_year: true, - year: 1977, - source: 'CoE', - population: 471474 - }, - { - census_year: true, - year: 1975, - source: 'CoE', - population: 451635 - }, - { - census_year: true, - year: 1974, - source: 'CoE', - population: 445691 - }, - { - census_year: true, - year: 1973, - source: 'CoE', - population: 442365 - }, - { - census_year: true, - year: 1972, - source: 'CoE', - population: 441530 - }, - { - census_year: true, - year: 1970, - source: 'CoE', - population: 429750 - }, - { - census_year: true, - year: 1969, - source: 'CoE', - population: 422418 - }, - { - census_year: true, - year: 1968, - source: 'CoE', - population: 410105 - }, - { - census_year: true, - year: 1967, - source: 'CoE', - population: 393593 - }, - { - census_year: true, - year: 1965, - source: 'CoE', - population: 371265 - }, - { - census_year: true, - year: 1964, - source: 'CoE 2', - population: 311804 - }, - { - census_year: true, - year: 1963, - source: 'CoE', - population: 303756 - }, - { - census_year: true, - year: 1962, - source: 'CoE', - population: 294967 - }, - { - census_year: true, - year: 1960, - source: 'CoE', - population: 269314 - }, - { - census_year: true, - year: 1959, - source: 'CoE', - population: 260733 - }, - { - census_year: true, - year: 1958, - source: 'CoE', - population: 252131 - }, - { - census_year: true, - year: 1957, - source: 'CoE', - population: 238353 - }, - { - census_year: true, - year: 1955, - source: 'CoE', - population: 209353 - }, - { - census_year: true, - year: 1954, - source: 'CoE', - population: 197836 - }, - { - census_year: true, - year: 1953, - source: 'CoE', - population: 183411 - }, - { - census_year: true, - year: 1952, - source: 'CoE', - population: 169196 - }, - { - census_year: true, - year: 1950, - source: 'CoE', - population: 148861 - }, - { - census_year: true, - year: 1949, - source: 'CoE', - population: 137469 - }, - { - census_year: true, - year: 1948, - source: 'CoE', - population: 126609 - }, - { - census_year: true, - year: 1947, - source: 'CoE', - population: 118541 - }, - { - census_year: true, - year: 1946, - source: 'CoE', - population: 114976 - }, - { - census_year: true, - year: 1945, - source: 'CoE', - population: 111745 - }, - { - census_year: true, - year: 1944, - source: 'CoE', - population: 108416 - }, - { - census_year: true, - year: 1943, - source: 'CoE', - population: 105536 - }, - { - census_year: true, - year: 1942, - source: 'CoE', - population: 96725 - }, - { - census_year: true, - year: 1940, - source: 'CoE', - population: 91723 - }, - { - census_year: true, - year: 1939, - source: 'CoE', - population: 90419 - }, - { - census_year: true, - year: 1938, - source: 'CoE', - population: 88887 - }, - { - census_year: true, - year: 1937, - source: 'CoE', - population: 87034 - }, - { - census_year: true, - year: 1936, - source: 'CoE', - population: 85470 - }, - { - census_year: true, - year: 1935, - source: 'CoE', - population: 82634 - }, - { - census_year: true, - year: 1934, - source: 'CoE', - population: 79773 - }, - { - census_year: true, - year: 1933, - source: 'CoE', - population: 79231 - }, - { - census_year: true, - year: 1932, - source: 'CoE', - population: 78387 - }, - { - census_year: true, - year: 1930, - source: 'CoE', - population: 77557 - }, - { - census_year: true, - year: 1929, - source: 'CoE', - population: 74298 - }, - { - census_year: true, - year: 1928, - source: 'CoE', - population: 69744 - }, - { - census_year: true, - year: 1927, - source: 'CoE', - population: 67083 - }, - { - census_year: true, - year: 1926, - source: 'CoE', - population: 65163 - }, - { - census_year: true, - year: 1925, - source: 'CoE', - population: 65378 - }, - { - census_year: true, - year: 1924, - source: 'CoE', - population: 63160 - }, - { - census_year: true, - year: 1923, - source: 'CoE*', - population: 60000 - }, - { - census_year: true, - year: 1922, - source: 'CoE*', - population: 60000 - }, - { - census_year: true, - year: 1920, - source: 'CoE', - population: 61045 - }, - { - census_year: true, - year: 1919, - source: 'CoE*', - population: 60000 - }, - { - census_year: true, - year: 1918, - source: 'CoE*', - population: 53000 - }, - { - census_year: true, - year: 1917, - source: 'CoE* 4', - population: 51000 - }, - { - census_year: true, - year: 1916, - source: 'CoE', - population: 53846 - }, - { - census_year: true, - year: 1915, - source: 'CoE', - population: 59339 - }, - { - census_year: true, - year: 1914, - source: 'CoE', - population: 72516 - }, - { - census_year: true, - year: 1913, - source: 'CoE', - population: 67243 - }, - { - census_year: true, - year: 1912, - source: 'CoE 5', - population: 53611 - }, - { - year: 1910, - source: 'CoE 6', - population: 23950 - }, - { - census_year: true, - year: 1909, - source: 'CoE*', - population: 23000 - }, - { - census_year: true, - year: 1908, - source: 'CoE', - population: 18500 - }, - { - year: 1907, - source: 'CoE 6', - population: 16294 - }, - { - census_year: true, - year: 1906, - source: 'CoE', - population: 14088 - }, - { - year: 1905, - source: 'CoE 6', - population: 11219 - }, - { - census_year: true, - year: 1904, - source: 'CoE', - population: 8350 - }, - { - census_year: true, - year: 1903, - source: 'CoE', - population: 6995 - }, - { - year: 1902, - source: 'CoE 6', - population: 4811 - }, - { - year: 1900, - source: 'CoE 6', - population: 2419 - }, - { - census_year: true, - year: 1899, - source: 'CoE', - population: 2212 - }, - { - year: 1898, - source: 'CoE 6', - population: 2212 - }, - { - census_year: true, - year: 1897, - source: 'CoE', - population: 2212 - }, - { - year: 1896, - source: 'CoE 6', - population: 1689 - }, - { - census_year: true, - year: 1895, - source: 'CoE', - population: 1165 - }, - { - year: 1894, - source: 'CoE 6', - population: 1010 - }, - { - year: 1893, - source: 'CoE 6', - population: 855 - }, - { - census_year: true, - year: 1892, - source: 'CoE', - population: 700 - }, - { - year: 1891, - source: 'CoE 6', - population: 630 - }, - { - year: 1890, - source: 'CoE 6', - population: 560 - }, - { - year: 1889, - source: 'CoE 6', - population: 490 - }, - { - year: 1888, - source: 'CoE 6', - population: 420 - }, - { - census_year: true, - year: 1887, - source: 'CoE*', - population: 350 - }, - { - year: 1886, - source: 'CoE', - population: 307 - }, - { - census_year: true, - year: 1885, - source: 'CoE', - population: 263 - }, - { - year: 1884, - source: 'CoE 6', - population: 247 - }, - { - year: 1883, - source: 'CoE 6', - population: 230 - }, - { - year: 1882, - source: 'CoE 6', - population: 214 - }, - { - year: 1881, - source: 'CoE 6', - population: 197 - }, - { - year: 1880, - source: 'CoE 6', - population: 181 - }, - { - year: 1879, - source: 'CoE 6', - population: 164 - }, - { - census_year: true, - year: 1878, - source: 'CoE', - population: 148 - } - ].reverse() } - }; + ], + point: { + style: { + visible: false + } + }, + line: { + style: { + lineWidth: 2 + } + }, + title: { + text: 'Population History - Line Chart', + textStyle: { + lineWidth: 3, + fill: '#333', + fontSize: 20, + fontFamily: 'Times New Roman' + } + }, + data: { + id: 'data2', + values: [ + { + census_year: true, + year: 2016, + source: 'CoE', + population: 899447 + }, + { + census_year: true, + year: 2014, + source: 'CoE', + population: 877926 + }, + { + year: 2013, + source: 'CoE 6', + population: 847712 + }, + { + census_year: true, + year: 2012, + source: 'CoE', + population: 817498 + }, + { + year: 2010, + source: 'CoE 6', + population: 797320 + }, + { + census_year: true, + year: 2009, + source: 'CoE', + population: 782439 + }, + { + census_year: true, + year: 2008, + source: 'CoE', + population: 752412 + }, + { + year: 2007, + source: 'CoE 6', + population: 741392 + }, + { + census_year: true, + year: 2005, + source: 'CoE', + population: 712391 + }, + { + year: 2004, + source: 'CoE 6', + population: 698631 + }, + { + year: 2003, + source: 'CoE 6', + population: 684871 + }, + { + year: 2002, + source: 'CoE 6', + population: 671110 + }, + { + year: 2000, + source: 'CoE 6', + population: 652817 + }, + { + census_year: true, + year: 1999, + source: 'CoE', + population: 648284 + }, + { + year: 1998, + source: 'CoE 6', + population: 637625 + }, + { + year: 1997, + source: 'CoE 6', + population: 626965 + }, + { + year: 1995, + source: 'CoE 6', + population: 619870 + }, + { + year: 1994, + source: 'CoE 6', + population: 623435 + }, + { + census_year: true, + year: 1993, + source: 'CoE', + population: 626999 + }, + { + census_year: true, + year: 1992, + source: 'CoE', + population: 618195 + }, + { + census_year: true, + year: 1990, + source: 'CoE', + population: 605538 + }, + { + census_year: true, + year: 1989, + source: 'CoE', + population: 583872 + }, + { + year: 1988, + source: 'CoE', + population: 580061 + }, + { + census_year: true, + year: 1987, + source: 'CoE', + population: 576249 + }, + { + year: 1985, + source: 'CoE 6', + population: 567699 + }, + { + year: 1984, + source: 'CoE 6', + population: 563892 + }, + { + census_year: true, + year: 1983, + source: 'CoE', + population: 560085 + }, + { + census_year: true, + year: 1982, + source: 'CoE 1', + population: 551314 + }, + { + census_year: true, + year: 1980, + source: 'CoE', + population: 505773 + }, + { + census_year: true, + year: 1979, + source: 'CoE', + population: 491359 + }, + { + census_year: true, + year: 1978, + source: 'CoE', + population: 478066 + }, + { + census_year: true, + year: 1977, + source: 'CoE', + population: 471474 + }, + { + census_year: true, + year: 1975, + source: 'CoE', + population: 451635 + }, + { + census_year: true, + year: 1974, + source: 'CoE', + population: 445691 + }, + { + census_year: true, + year: 1973, + source: 'CoE', + population: 442365 + }, + { + census_year: true, + year: 1972, + source: 'CoE', + population: 441530 + }, + { + census_year: true, + year: 1970, + source: 'CoE', + population: 429750 + }, + { + census_year: true, + year: 1969, + source: 'CoE', + population: 422418 + }, + { + census_year: true, + year: 1968, + source: 'CoE', + population: 410105 + }, + { + census_year: true, + year: 1967, + source: 'CoE', + population: 393593 + }, + { + census_year: true, + year: 1965, + source: 'CoE', + population: 371265 + }, + { + census_year: true, + year: 1964, + source: 'CoE 2', + population: 311804 + }, + { + census_year: true, + year: 1963, + source: 'CoE', + population: 303756 + }, + { + census_year: true, + year: 1962, + source: 'CoE', + population: 294967 + }, + { + census_year: true, + year: 1960, + source: 'CoE', + population: 269314 + }, + { + census_year: true, + year: 1959, + source: 'CoE', + population: 260733 + }, + { + census_year: true, + year: 1958, + source: 'CoE', + population: 252131 + }, + { + census_year: true, + year: 1957, + source: 'CoE', + population: 238353 + }, + { + census_year: true, + year: 1955, + source: 'CoE', + population: 209353 + }, + { + census_year: true, + year: 1954, + source: 'CoE', + population: 197836 + }, + { + census_year: true, + year: 1953, + source: 'CoE', + population: 183411 + }, + { + census_year: true, + year: 1952, + source: 'CoE', + population: 169196 + }, + { + census_year: true, + year: 1950, + source: 'CoE', + population: 148861 + }, + { + census_year: true, + year: 1949, + source: 'CoE', + population: 137469 + }, + { + census_year: true, + year: 1948, + source: 'CoE', + population: 126609 + }, + { + census_year: true, + year: 1947, + source: 'CoE', + population: 118541 + }, + { + census_year: true, + year: 1946, + source: 'CoE', + population: 114976 + }, + { + census_year: true, + year: 1945, + source: 'CoE', + population: 111745 + }, + { + census_year: true, + year: 1944, + source: 'CoE', + population: 108416 + }, + { + census_year: true, + year: 1943, + source: 'CoE', + population: 105536 + }, + { + census_year: true, + year: 1942, + source: 'CoE', + population: 96725 + }, + { + census_year: true, + year: 1940, + source: 'CoE', + population: 91723 + }, + { + census_year: true, + year: 1939, + source: 'CoE', + population: 90419 + }, + { + census_year: true, + year: 1938, + source: 'CoE', + population: 88887 + }, + { + census_year: true, + year: 1937, + source: 'CoE', + population: 87034 + }, + { + census_year: true, + year: 1936, + source: 'CoE', + population: 85470 + }, + { + census_year: true, + year: 1935, + source: 'CoE', + population: 82634 + }, + { + census_year: true, + year: 1934, + source: 'CoE', + population: 79773 + }, + { + census_year: true, + year: 1933, + source: 'CoE', + population: 79231 + }, + { + census_year: true, + year: 1932, + source: 'CoE', + population: 78387 + }, + { + census_year: true, + year: 1930, + source: 'CoE', + population: 77557 + }, + { + census_year: true, + year: 1929, + source: 'CoE', + population: 74298 + }, + { + census_year: true, + year: 1928, + source: 'CoE', + population: 69744 + }, + { + census_year: true, + year: 1927, + source: 'CoE', + population: 67083 + }, + { + census_year: true, + year: 1926, + source: 'CoE', + population: 65163 + }, + { + census_year: true, + year: 1925, + source: 'CoE', + population: 65378 + }, + { + census_year: true, + year: 1924, + source: 'CoE', + population: 63160 + }, + { + census_year: true, + year: 1923, + source: 'CoE*', + population: 60000 + }, + { + census_year: true, + year: 1922, + source: 'CoE*', + population: 60000 + }, + { + census_year: true, + year: 1920, + source: 'CoE', + population: 61045 + }, + { + census_year: true, + year: 1919, + source: 'CoE*', + population: 60000 + }, + { + census_year: true, + year: 1918, + source: 'CoE*', + population: 53000 + }, + { + census_year: true, + year: 1917, + source: 'CoE* 4', + population: 51000 + }, + { + census_year: true, + year: 1916, + source: 'CoE', + population: 53846 + }, + { + census_year: true, + year: 1915, + source: 'CoE', + population: 59339 + }, + { + census_year: true, + year: 1914, + source: 'CoE', + population: 72516 + }, + { + census_year: true, + year: 1913, + source: 'CoE', + population: 67243 + }, + { + census_year: true, + year: 1912, + source: 'CoE 5', + population: 53611 + }, + { + year: 1910, + source: 'CoE 6', + population: 23950 + }, + { + census_year: true, + year: 1909, + source: 'CoE*', + population: 23000 + }, + { + census_year: true, + year: 1908, + source: 'CoE', + population: 18500 + }, + { + year: 1907, + source: 'CoE 6', + population: 16294 + }, + { + census_year: true, + year: 1906, + source: 'CoE', + population: 14088 + }, + { + year: 1905, + source: 'CoE 6', + population: 11219 + }, + { + census_year: true, + year: 1904, + source: 'CoE', + population: 8350 + }, + { + census_year: true, + year: 1903, + source: 'CoE', + population: 6995 + }, + { + year: 1902, + source: 'CoE 6', + population: 4811 + }, + { + year: 1900, + source: 'CoE 6', + population: 2419 + }, + { + census_year: true, + year: 1899, + source: 'CoE', + population: 2212 + }, + { + year: 1898, + source: 'CoE 6', + population: 2212 + }, + { + census_year: true, + year: 1897, + source: 'CoE', + population: 2212 + }, + { + year: 1896, + source: 'CoE 6', + population: 1689 + }, + { + census_year: true, + year: 1895, + source: 'CoE', + population: 1165 + }, + { + year: 1894, + source: 'CoE 6', + population: 1010 + }, + { + year: 1893, + source: 'CoE 6', + population: 855 + }, + { + census_year: true, + year: 1892, + source: 'CoE', + population: 700 + }, + { + year: 1891, + source: 'CoE 6', + population: 630 + }, + { + year: 1890, + source: 'CoE 6', + population: 560 + }, + { + year: 1889, + source: 'CoE 6', + population: 490 + }, + { + year: 1888, + source: 'CoE 6', + population: 420 + }, + { + census_year: true, + year: 1887, + source: 'CoE*', + population: 350 + }, + { + year: 1886, + source: 'CoE', + population: 307 + }, + { + census_year: true, + year: 1885, + source: 'CoE', + population: 263 + }, + { + year: 1884, + source: 'CoE 6', + population: 247 + }, + { + year: 1883, + source: 'CoE 6', + population: 230 + }, + { + year: 1882, + source: 'CoE 6', + population: 214 + }, + { + year: 1881, + source: 'CoE 6', + population: 197 + }, + { + year: 1880, + source: 'CoE 6', + population: 181 + }, + { + year: 1879, + source: 'CoE 6', + population: 164 + }, + { + census_year: true, + year: 1878, + source: 'CoE', + population: 148 + } + ].reverse() + } +}; const vchart = new VChart(spec, { dom: CONTAINER_ID }); vchart.renderSync(); diff --git a/docs/assets/examples/en/marker/mark-point-image.md b/docs/assets/examples/en/marker/mark-point-image.md index bbd760268a..9dc7389a88 100644 --- a/docs/assets/examples/en/marker/mark-point-image.md +++ b/docs/assets/examples/en/marker/mark-point-image.md @@ -57,12 +57,10 @@ const spec = { }, itemContent: { type: 'image', - image: { - style: { - dx: -50, - dy: 50, - image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/airplane.png' - } + style: { + dx: -50, + dy: 50, + image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/airplane.png' } } } diff --git a/docs/assets/examples/en/marker/polar-mark-point.md b/docs/assets/examples/en/marker/polar-mark-point.md index 88de4af8b8..51fc09b7b7 100644 --- a/docs/assets/examples/en/marker/polar-mark-point.md +++ b/docs/assets/examples/en/marker/polar-mark-point.md @@ -18,289 +18,289 @@ option: roseChart#markPoint ## Demo source ```javascript livedemo - const spec = { - data: [ - { - id: 'id0', - values: [ - { type: 'MIDNIGHT', value: 1 }, - { type: '1 AM', value: 1 }, - { type: '2 AM', value: 1 }, - { type: '3 AM', value: 1 }, - { type: '4 AM', value: 1 }, - { type: '5 AM', value: 1 }, - { type: '6 AM', value: 1 }, - { type: '7 AM', value: 1 }, - { type: '8 AM', value: 1 }, - { type: '9 AM', value: 1 }, - { type: '10 AM', value: 1 }, - { type: '11 AM', value: 1 }, - { type: 'NOON', value: 1 }, - { type: '13 AM', value: 1 }, - { type: '14 AM', value: 1 }, - { type: '15 AM', value: 1 }, - { type: '16 AM', value: 1 }, - { type: '17 AM', value: 1 }, - { type: '18 AM', value: 1 }, - { type: '19 AM', value: 1 }, - { type: '20 AM', value: 1 }, - { type: '21 AM', value: 1 }, - { type: '22 AM', value: 1 }, - { type: '23 AM', value: 1 }, - ] - }, - { - id: 'id1', - values: [ - { type: 'a', value: 1 } - ] - } - ], - dataIndex: 0, - type: 'rose', - outerRadius: 0.7, - innerRadius: 0.5, - valueField: 'value', - categoryField: 'type', - seriesField: 'type', - startAngle: -97.5, - title: { - text: 'History of Earth in 24-hour clock', - textStyle: { - height: 50, - lineWidth: 2, - fill: '#333', - fontSize: 20, - fontFamily: 'Times New Roman' - }, - subtextStyle: { - character: [ - { - text: '', - fontFamily: 'Times New Roman', - fontSize: 14, - fill: '#333' - } - ] - } +const spec = { + data: [ + { + id: 'id0', + values: [ + { type: 'MIDNIGHT', value: 1 }, + { type: '1 AM', value: 1 }, + { type: '2 AM', value: 1 }, + { type: '3 AM', value: 1 }, + { type: '4 AM', value: 1 }, + { type: '5 AM', value: 1 }, + { type: '6 AM', value: 1 }, + { type: '7 AM', value: 1 }, + { type: '8 AM', value: 1 }, + { type: '9 AM', value: 1 }, + { type: '10 AM', value: 1 }, + { type: '11 AM', value: 1 }, + { type: 'NOON', value: 1 }, + { type: '13 AM', value: 1 }, + { type: '14 AM', value: 1 }, + { type: '15 AM', value: 1 }, + { type: '16 AM', value: 1 }, + { type: '17 AM', value: 1 }, + { type: '18 AM', value: 1 }, + { type: '19 AM', value: 1 }, + { type: '20 AM', value: 1 }, + { type: '21 AM', value: 1 }, + { type: '22 AM', value: 1 }, + { type: '23 AM', value: 1 } + ] + }, + { + id: 'id1', + values: [{ type: 'a', value: 1 }] + } + ], + dataIndex: 0, + type: 'rose', + outerRadius: 0.7, + innerRadius: 0.5, + valueField: 'value', + categoryField: 'type', + seriesField: 'type', + startAngle: -97.5, + title: { + text: 'History of Earth in 24-hour clock', + textStyle: { + height: 50, + lineWidth: 2, + fill: '#333', + fontSize: 20, + fontFamily: 'Times New Roman' + }, + subtextStyle: { + character: [ + { + text: '', + fontFamily: 'Times New Roman', + fontSize: 14, + fill: '#333' + } + ] + } + }, + axes: [ + { + orient: 'angle', + type: 'band', + zIndex: 999, + tick: { + visible: true, + tickSize: 10, + inside: true, + style: { + stroke: '#fff' + // lineWidth: 2, + } + }, + label: { + visible: true, + inside: true, + style: { + fill: '#fff' + } + }, + grid: { + visible: true, + style: { + lineDash: [0], + stroke: '#fff', + lineWidth: 1 }, - axes: [{ - orient: 'angle', - type: 'band', - zIndex: 999, - tick: { - visible: true, - tickSize: 10, - inside: true, - style: { - stroke: '#fff', - // lineWidth: 2, - } - }, - label: { - visible: true, - inside: true, - style: { - fill: '#fff' - } - }, - grid: { - visible: true, - style: { - lineDash: [0], - stroke: '#fff', - lineWidth: 1 - }, - alignWithLabel: false // grid does not align with label - }, - style: { - zIndex: 400, - } - }], - label: { - visible: false, - position: 'inside' - - }, - tooltip: { - visible: false - }, - rose: { - style: { - fill: 'rgb(129, 216, 208)' - } - }, - markLine: [{ - radius: 1.1, - angle: 'MIDNIGHT', - angle1: '3 AM' - }, { - radius: 1.1, - angle: '6 AM', - angle1: '13 AM' - }], - markPoint: [ - { - position: { - x: '50%', - y: '50%' - }, - regionRelative: true, - itemLine: { - visible: false - }, - itemContent: { - type: 'symbol', - symbol: { - style: { - dx: -80, - dy: -40, - size: 60, - symbolType: '', - fill: 'rgb(129, 216, 208)' - } - } - } - }, { - angle: '4 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: 5, - offsetY: -20, - text: { - text: '4: 00 Origin of life' - } - } - }, { - angle: '5 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: 5, - offsetY: -20, - text: { - text: '5: 00 Oldest Fossils' - } - } - }, { - angle: '14 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: 20, - text: { - text: 'Single-Celled Algae(Acritarchs)', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '18 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Sexual Reproduction', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '20 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Seaweeds', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '21 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Trilobites', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '22 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Coal Swamps', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '23 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Humans', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '2 AM', - radius: 1.1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: 10, - offsetY: -20, - text: { - text: 'Meteorite Bombardment 0:00 to 3 am' - } - } - }, { - angle: '10 AM', - radius: 1.1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: 10, - offsetY: 20, - text: { - text: '6:00 to 1: Abundant Banded Iron- Formations' - } - } - }], - }; + alignWithLabel: false // grid does not align with label + }, + style: { + zIndex: 400 + } + } + ], + label: { + visible: false, + position: 'inside' + }, + tooltip: { + visible: false + }, + rose: { + style: { + fill: 'rgb(129, 216, 208)' + } + }, + markLine: [ + { + radius: 1.1, + angle: 'MIDNIGHT', + angle1: '3 AM' + }, + { + radius: 1.1, + angle: '6 AM', + angle1: '13 AM' + } + ], + markPoint: [ + { + position: { + x: '50%', + y: '50%' + }, + regionRelative: true, + itemLine: { + visible: false + }, + itemContent: { + type: 'symbol', + style: { + dx: -80, + dy: -40, + size: 60, + symbolType: + '', + fill: 'rgb(129, 216, 208)' + } + } + }, + { + angle: '4 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: 5, + offsetY: -20, + style: { + text: '4: 00 Origin of life' + } + } + }, + { + angle: '5 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: 5, + offsetY: -20, + style: { + text: '5: 00 Oldest Fossils' + } + } + }, + { + angle: '14 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: 20, + style: { + text: 'Single-Celled Algae(Acritarchs)', + textAlign: 'right' + } + } + }, + { + angle: '18 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Sexual Reproduction', + textAlign: 'right' + } + } + }, + { + angle: '20 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Seaweeds', + textAlign: 'right' + } + } + }, + { + angle: '21 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Trilobites', + textAlign: 'right' + } + } + }, + { + angle: '22 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Coal Swamps', + textAlign: 'right' + } + } + }, + { + angle: '23 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Humans', + textAlign: 'right' + } + } + }, + { + angle: '2 AM', + radius: 1.1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: 10, + offsetY: -20, + style: { + text: 'Meteorite Bombardment 0:00 to 3 am' + } + } + }, + { + angle: '10 AM', + radius: 1.1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: 10, + offsetY: 20, + style: { + text: '6:00 to 1: Abundant Banded Iron- Formations' + } + } + } + ] +}; const vchart = new VChart(spec, { dom: CONTAINER_ID }); vchart.renderSync(); diff --git a/docs/assets/examples/en/storytelling/disappear-animation-gaussion-blur.md b/docs/assets/examples/en/storytelling/disappear-animation-gaussion-blur.md new file mode 100644 index 0000000000..82367bf32d --- /dev/null +++ b/docs/assets/examples/en/storytelling/disappear-animation-gaussion-blur.md @@ -0,0 +1,124 @@ +--- +category: examples +group: storytelling +title: Disappear Animation Gaussian Blur +keywords: animation,morphing,bar,pie,barChart,pieChart,comparison +order: 42-0 +cover: /vchart/preview/disappear-animation-gaussian-blur-2.0.11.gif +option: lineChart#animationAppear +--- + +# Disappear Animation Gaussian Blur Effect + +In custom animation effects, you can implement the Gaussian blur effect by using the `afterStageRender` method. + +## Key configuration + +- callBack: The custom callback function or animation implementation class for the disappear animation, used to execute user-defined disappear effects. + +### Demo source + +```javascript livedemo +// import { vglobal } from '@visactor/vchart'; +const vglobal = VCHART_MODULE.vglobal; + +function applyDownsampleBlur(imageData, radius) { + const { width, height } = imageData; + + const downsample = Math.max(1, Math.floor(radius / 2)); + const smallWidth = Math.floor(width / downsample); + const smallHeight = Math.floor(height / downsample); + + const tempCanvas = vglobal.createCanvas({ + width: smallWidth, + height: smallHeight, + dpr: 1 + }); + const tempCtx = tempCanvas.getContext('2d'); + if (!tempCtx) { + return imageData; + } + + const originalCanvas = vglobal.createCanvas({ + width: width, + height: height, + dpr: 1 + }); + const originalCtx = originalCanvas.getContext('2d'); + if (!originalCtx) { + return imageData; + } + + originalCtx.putImageData(imageData, 0, 0); + + tempCtx.drawImage(originalCanvas, 0, 0, smallWidth, smallHeight); + + tempCtx.filter = `blur(${radius / downsample}px)`; + tempCtx.drawImage(tempCanvas, 0, 0); + tempCtx.filter = 'none'; + + originalCtx.clearRect(0, 0, width, height); + originalCtx.drawImage(tempCanvas, 0, 0, width, height); + + return originalCtx.getImageData(0, 0, width, height); +} + +function gaussianBlurAnimate(canvas, ratio) { + const blurRadius = ratio * 8; + + if (blurRadius <= 0) { + return canvas; + } + + const c = vglobal.createCanvas({ + width: canvas.width, + height: canvas.height, + dpr: vglobal.devicePixelRatio + }); + const ctx = c.getContext('2d'); + if (!ctx) { + return false; + } + + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(canvas, 0, 0); + + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const blurredImageData = applyDownsampleBlur(imageData, blurRadius); + ctx.putImageData(blurredImageData, 0, 0); + + ctx.fillStyle = `rgba(255, 255, 255, ${ratio.toFixed(2)})`; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + return c; +} + +const spec = { + type: 'bar', + data: [ + { + id: 'barData', + values: [ + { month: 'Monday', sales: 22 }, + { month: 'Tuesday', sales: 13 }, + { month: 'Wednesday', sales: 25 }, + { month: 'Thursday', sales: 29 }, + { month: 'Friday', sales: 38 } + ] + } + ], + xField: 'month', + yField: 'sales', + animationDisappear: { + callBack: (stage, canvas, ratio) => gaussianBlurAnimate(canvas, ratio), + duration: 2000 + } +}; + +const vchart = new VChart(spec, { dom: CONTAINER_ID }); +vchart.renderAsync(); + +setInterval(() => { + vchart.runDisappearAnimation(); +}, 4000); +``` diff --git a/docs/assets/examples/en/storytelling/disappear-animation-wipe.md b/docs/assets/examples/en/storytelling/disappear-animation-wipe.md new file mode 100644 index 0000000000..dd0ab7ad57 --- /dev/null +++ b/docs/assets/examples/en/storytelling/disappear-animation-wipe.md @@ -0,0 +1,100 @@ +--- +category: examples +group: storytelling +title: Disappear Animation Wipe +keywords: animation,morphing,bar,pie,barChart,pieChart,comparison +order: 42-0 +cover: /vchart/preview/disappear-animation-wipe-2.0.11.gif +option: lineChart#animationAppear +--- + +# Disappear Animation Wipe Effect + +In custom animation effects, you can implement the wipe animation effect by using the `afterStageRender` method. + +## Key configuration + +- callBack: The custom callback function or animation implementation class for the disappear animation, used to execute user-defined disappear effects. + +### Demo source + +```javascript livedemo +// import { vglobal } from '@visactor/vchart'; +const vglobal = VCHART_MODULE.vglobal; + +function wipeAnimate(canvas, ratio) { + const c = vglobal.createCanvas({ + width: canvas.width, + height: canvas.height, + dpr: vglobal.devicePixelRatio + }); + const ctx = c.getContext('2d'); + if (!ctx) { + return false; + } + + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(canvas, 0, 0); + + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const data = imageData.data; + + const wipePosition = Math.floor(canvas.width * ratio); + + const gradientWidth = Math.min(canvas.width * 0.3, 50); + + for (let y = 0; y < canvas.height; y++) { + for (let x = 0; x < canvas.width; x++) { + const index = (y * canvas.width + x) * 4; + const originalAlpha = data[index + 3]; + const distance = x - wipePosition; + + let newAlpha; + if (distance <= 0) { + newAlpha = 0; + } else if (distance <= gradientWidth) { + const gradientRatio = distance / gradientWidth; + newAlpha = Math.floor(originalAlpha * gradientRatio); + } else { + newAlpha = originalAlpha; + } + + data[index + 3] = newAlpha; + } + } + + ctx.putImageData(imageData, 0, 0); + + return c; +} + +const spec = { + type: 'bar', + data: [ + { + id: 'barData', + values: [ + { month: 'Monday', sales: 22 }, + { month: 'Tuesday', sales: 13 }, + { month: 'Wednesday', sales: 25 }, + { month: 'Thursday', sales: 29 }, + { month: 'Friday', sales: 38 } + ] + } + ], + xField: 'month', + yField: 'sales', + animationDisappear: { + callBack: (stage, canvas, ratio) => wipeAnimate(canvas, ratio), + easing: 'linear', + duration: 2000 + } +}; + +const vchart = new VChart(spec, { dom: CONTAINER_ID }); +vchart.renderAsync(); + +setInterval(() => { + vchart.runDisappearAnimation(); +}, 3000); +``` diff --git a/docs/assets/examples/en/storytelling/disappear-animation.md b/docs/assets/examples/en/storytelling/disappear-animation.md new file mode 100644 index 0000000000..7dd173d0f0 --- /dev/null +++ b/docs/assets/examples/en/storytelling/disappear-animation.md @@ -0,0 +1,101 @@ +--- +category: examples +group: storytelling +title: Disappear Animation +keywords: animation,morphing,bar,pie,barChart,pieChart,comparison +order: 42-0 +cover: /vchart/preview/disappear-animation-2.0.11.gif +option: lineChart#animationAppear +--- + +# Disappear Animation + +User can manually call `vchart.runDisappearAnimation()` method to execute the disappear animation. +The difference between the disappear animation and other animations is that it provides an additional `callBack` parameter to execute user-defined disappear effects. +User can configure the custom interpolation callback function or provide a custom animation implementation class in the `callBack` parameter. + +## Key configuration + +- callBack: The custom callback function or animation implementation class for the disappear animation, used to execute user-defined disappear effects. + +### Demo source + +```javascript livedemo +// import { vglobal } from '@visactor/vchart'; +// import { AStageAnimate } from '@visactor/vrender-animate'; +const vglobal = VCHART_MODULE.vglobal; +const AStageAnimate = VRender.AStageAnimate; + +// custom disappear animation implementation class +class TestStageAnimate extends AStageAnimate { + onUpdate(end, ratio, out) { + super.onUpdate(end, ratio, out); + this.ratio = ratio; + } + + // update the canvas rendering content + afterStageRender(stage, canvas) { + const c = vglobal.createCanvas({ + width: canvas.width, + height: canvas.height, + dpr: vglobal.devicePixelRatio + }); + const ctx = c.getContext('2d'); + if (!ctx) { + return false; + } + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(canvas, 0, 0); + ctx.fillStyle = `rgba(255, 255, 255, ${this.ratio.toFixed(2)})`; + ctx.fillRect(0, 0, canvas.width, canvas.height); + return c; + } +} + +const spec = { + type: 'bar', + data: [ + { + id: 'barData', + values: [ + { month: 'Monday', sales: 22 }, + { month: 'Tuesday', sales: 13 }, + { month: 'Wednesday', sales: 25 }, + { month: 'Thursday', sales: 29 }, + { month: 'Friday', sales: 38 } + ] + } + ], + xField: 'month', + yField: 'sales', + animationDisappear: { + // custom disappear animation callback function + callBack: (stage, canvas, ratio) => { + const c = vglobal.createCanvas({ + width: canvas.width, + height: canvas.height, + dpr: vglobal.devicePixelRatio + }); + const ctx = c.getContext('2d'); + if (!ctx) { + return false; + } + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(canvas, 0, 0); + ctx.fillStyle = `rgba(255, 255, 255, ${ratio.toFixed(2)})`; + ctx.fillRect(0, 0, canvas.width, canvas.height); + return c; + }, + // custom disappear animation class usage + // callBack: TestStageAnimate, + duration: 1000 + } +}; + +const vchart = new VChart(spec, { dom: CONTAINER_ID }); +vchart.renderAsync(); + +setInterval(() => { + vchart.runDisappearAnimation(); +}, 2000); +``` diff --git a/docs/assets/examples/en/vscreen/gauge.md b/docs/assets/examples/en/vscreen/gauge.md index 3a0778c8c9..1dec9bff9b 100644 --- a/docs/assets/examples/en/vscreen/gauge.md +++ b/docs/assets/examples/en/vscreen/gauge.md @@ -134,50 +134,49 @@ const spec = { itemContent: { type: 'richText', autoRotate: false, - richText: { - style: { - width: 40000, - height: 40000, - textAlign: 'left', - textBaseline: 'top', - type: 'rich', - textConfig: [ - { - visible: false, - text: '\n', - fontSize: 12, - fill: '#FFF', - fontWeight: 'normal', - fontFamily: 'D-DIN', - textAlign: 'center', - textBaseline: 'middle' - }, - { - visible: true, - text: 'Profit', - fontSize: 16, - fill: '#FFF', - fontWeight: 'normal', - fontFamily: 'D-DIN', - textAlign: 'center', - textBaseline: 'middle' - }, - { - text: ' ', - fontSize: 8 - }, - { - visible: true, - text: '341.80', - fontSize: 32, - fill: '#FFF', - fontWeight: 'bold', - fontFamily: 'D-DIN', - textAlign: 'center', - textBaseline: 'middle' - } - ] - } + + style: { + width: 40000, + height: 40000, + textAlign: 'left', + textBaseline: 'top', + type: 'rich', + textConfig: [ + { + visible: false, + text: '\n', + fontSize: 12, + fill: '#FFF', + fontWeight: 'normal', + fontFamily: 'D-DIN', + textAlign: 'center', + textBaseline: 'middle' + }, + { + visible: true, + text: 'Profit', + fontSize: 16, + fill: '#FFF', + fontWeight: 'normal', + fontFamily: 'D-DIN', + textAlign: 'center', + textBaseline: 'middle' + }, + { + text: ' ', + fontSize: 8 + }, + { + visible: true, + text: '341.80', + fontSize: 32, + fill: '#FFF', + fontWeight: 'bold', + fontFamily: 'D-DIN', + textAlign: 'center', + textBaseline: 'middle' + } + ] } } } diff --git a/docs/assets/examples/menu.json b/docs/assets/examples/menu.json index aca0bb2d3a..3e719af8f5 100644 --- a/docs/assets/examples/menu.json +++ b/docs/assets/examples/menu.json @@ -126,6 +126,27 @@ "zh": "柱状图、散点图间切换的全局动画", "en": "Global animation for switching between bar charts and scatter plots" } + }, + { + "path": "disappear-animation", + "title": { + "zh": "退场动画", + "en": "Disappear Animation" + } + }, + { + "path": "disappear-animation-gaussion-blur", + "title": { + "zh": "退场动画高斯模糊效果", + "en": "Disappear Animation Gaussian Blur Effect" + } + }, + { + "path": "disappear-animation-wipe", + "title": { + "zh": "退场动画擦除效果", + "en": "Disappear Animation Wipe Effect" + } } ] }, @@ -3295,4 +3316,4 @@ ] } ] -} +} \ No newline at end of file diff --git a/docs/assets/examples/zh/area-chart/segment-range-area.md b/docs/assets/examples/zh/area-chart/segment-range-area.md index 29f4dc408f..3799aea2aa 100644 --- a/docs/assets/examples/zh/area-chart/segment-range-area.md +++ b/docs/assets/examples/zh/area-chart/segment-range-area.md @@ -97,15 +97,13 @@ const spec = { itemContent: { type: 'text', autoRotate: false, - text: { + style: { text: 'BALANCE AGAINST', - style: { - fontSize: 14, - fontWeight: 'bold', - fill: 'rgba(0,0,0,0.45)', - textAlign: 'center', - textBaseline: 'middle' - } + fontSize: 14, + fontWeight: 'bold', + fill: 'rgba(0,0,0,0.45)', + textAlign: 'center', + textBaseline: 'middle' } }, itemLine: { @@ -121,15 +119,13 @@ const spec = { offsetX: -40, type: 'text', autoRotate: false, - text: { + style: { text: ['BALANCE in', 'FAVOUR of ENGLAND'], - style: { - fontSize: 14, - fontWeight: 'bold', - fill: 'rgba(0,0,0,0.45)', - textAlign: 'left', - textBaseline: 'middle' - } + fontSize: 14, + fontWeight: 'bold', + fill: 'rgba(0,0,0,0.45)', + textAlign: 'left', + textBaseline: 'middle' } }, itemLine: { diff --git a/docs/assets/examples/zh/bar-chart/bar-markPoint.md b/docs/assets/examples/zh/bar-chart/bar-markPoint.md index a86ac7a1ae..996c7b6ed9 100644 --- a/docs/assets/examples/zh/bar-chart/bar-markPoint.md +++ b/docs/assets/examples/zh/bar-chart/bar-markPoint.md @@ -83,12 +83,6 @@ const spec = { autoRotate: false, offsetY: -10, text: { - dy: 14, - text: '2分钟', - style: { - fill: 'white', - fontSize: 14 - }, labelBackground: { padding: [5, 10, 5, 10], style: { @@ -96,6 +90,12 @@ const spec = { cornerRadius: 5 } } + }, + style: { + dy: 14, + text: '2分钟', + fill: 'white', + fontSize: 14 } }, itemLine: { diff --git a/docs/assets/examples/zh/marker/geo-mark-point.md b/docs/assets/examples/zh/marker/geo-mark-point.md index 7158055058..748779289b 100644 --- a/docs/assets/examples/zh/marker/geo-mark-point.md +++ b/docs/assets/examples/zh/marker/geo-mark-point.md @@ -17,91 +17,91 @@ option: mapChart#markPoint ## 代码演示 ```javascript livedemo - const response1 = await fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/map-mark-point.json'); - const dataJson = await response1.json(); - const data = dataJson.features.map(d => d['properties']) - const minValue = Math.min(...data.map(d => d.scores)) - const maxValue = Math.max(...data.map(d => d.scores)) +const response1 = await fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/map-mark-point.json'); +const dataJson = await response1.json(); +const data = dataJson.features.map(d => d['properties']); +const minValue = Math.min(...data.map(d => d.scores)); +const maxValue = Math.max(...data.map(d => d.scores)); +const response2 = await fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/geojson/usa.json'); +const geojson = await response2.json(); +VChart.registerMap('usa', geojson); - const response2 = await fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/geojson/usa.json'); - const geojson = await response2.json(); - VChart.registerMap('usa', geojson); +function sizeScale(value, domain, range) { + const t = (value - domain[0]) / (domain[1] - domain[0]); + const newValue = (range[1] - range[0]) * t + range[0]; + return newValue; +} - function sizeScale(value, domain, range) { - const t = (value - domain[0]) / (domain[1] - domain[0]); - const newValue = (range[1] - range[0]) * t + range[0]; - return newValue; +const spec = { + type: 'map', + title: { + text: 'Opioid Overdose Rates (per 100,000) by Year: 2017' + }, + color: { + type: 'linear', + range: ['rgb(252,250,97)', 'rgb(252,150,134)', 'rgb(87,33,15)'] + }, + area: { + style: { + fill: { + field: 'scores', + scale: 'color', + changeDomain: 'replace' + } } - - const spec = { - type: 'map', - title: { - text: 'Opioid Overdose Rates (per 100,000) by Year: 2017', - }, - color: { - type: 'linear', - range: ['rgb(252,250,97)', 'rgb(252,150,134)', 'rgb(87,33,15)'] - }, - area: { - style: { - fill: { - field: 'scores', - scale: 'color', - changeDomain: 'replace' - } - } - }, - data: [ - { - values: data - } - ], - nameField: 'name', - valueField: 'scores', - nameProperty: 'name', - map: 'usa', - region: [ - { - roam: true, - projection: { - type: 'albersUsa' - } - } - ], - legends: [ - { - visible: true, - type: 'color', - field: 'scores', - orient: 'bottom', - position: 'start', - title: { - visible: true, - text: 'Population' - } - } - ], - markPoint: data.map(d => { - return { - areaName: d.name, - itemLine: { - visible: false, - }, - itemContent: { - type: 'symbol', - autoRotate: false, - offsetX: -10, - offsetY: -5, - symbolStyle: { - size: sizeScale(d.scores, [minValue, maxValue], [20, 40]), - fill: '#FF6347', - symbolType: '' - } - } - } - }) + }, + data: [ + { + values: data + } + ], + nameField: 'name', + valueField: 'scores', + nameProperty: 'name', + map: 'usa', + region: [ + { + roam: true, + projection: { + type: 'albersUsa' + } + } + ], + legends: [ + { + visible: true, + type: 'color', + field: 'scores', + orient: 'bottom', + position: 'start', + title: { + visible: true, + text: 'Population' + } + } + ], + markPoint: data.map(d => { + return { + areaName: d.name, + itemLine: { + visible: false + }, + itemContent: { + type: 'symbol', + autoRotate: false, + offsetX: -10, + offsetY: -5, + style: { + size: sizeScale(d.scores, [minValue, maxValue], [20, 40]), + fill: '#FF6347', + symbolType: + '' + } + } }; + }) +}; const vchart = new VChart(spec, { dom: CONTAINER_ID }); vchart.renderSync(); diff --git a/docs/assets/examples/zh/marker/mark-point-basic.md b/docs/assets/examples/zh/marker/mark-point-basic.md index 000523a183..01efb0c7bc 100644 --- a/docs/assets/examples/zh/marker/mark-point-basic.md +++ b/docs/assets/examples/zh/marker/mark-point-basic.md @@ -32,820 +32,820 @@ markArea 支持数据点 和 任意坐标定位方式, 此处展示数据点定 - `itemContent.autoRotate`属性声明为标注内容是否自动旋转至引导线平行的方向. - `itemContent.richText`属性声明为当`itemContent.type: richText`时, 标注内容的样式, 同理也可应用于其他标注内容类型. - `targetSymbol`声明为前置标记,用于标记数据点,突出标记点。 + ## 代码演示 ```javascript livedemo - const spec = { - type: 'line', - xField: 'year', - yField: 'population', - axes: [ - { - orient: 'bottom', - type: 'linear', - min: 1868, - max: 2016 - } - ], - markPoint: [ - { - coordinate: { - year: '1878', - population: 100 - }, - itemContent: { - offsetY: -100, - offsetX: 100, - type: 'text', - autoRotate: false, - confine: true, - text: { - text: '1878 population was 148', +const spec = { + type: 'line', + xField: 'year', + yField: 'population', + axes: [ + { + orient: 'bottom', + type: 'linear', + min: 1868, + max: 2016 + } + ], + markPoint: [ + { + coordinate: { + year: '1878', + population: 100 + }, + itemContent: { + offsetY: -100, + offsetX: 100, + type: 'text', + autoRotate: false, + confine: true, + style: { + text: '1878 population was 148' + } + }, + targetSymbol: { + visible: true + }, + itemLine: { + type: 'type-arc', + arcRatio: 0.4, + startSymbol: { + size: 10, + style: { + stroke: '#E8346D', + symbolType: 'triangle' } }, - targetSymbol: { - visible: true, - }, - itemLine: { - type: 'type-arc', - arcRatio: 0.4, - startSymbol: { - size: 10, - style: { - stroke: '#E8346D', - symbolType: 'triangle' - } - }, - line: { - style: { - stroke: '#E8346D' - } + line: { + style: { + stroke: '#E8346D' } } + } + }, + { + coordinate: { + year: '2016', + population: 899447 }, - { - coordinate: { - year: '2016', - population: 899447 - }, - itemContent: { - offsetY: 40, - // offsetX: -200, - type: 'richText', - autoRotate: false, - confine: true, - position: 'insideBottom', - richText: { - style: { - width: 100, - height: 50, - dx: 110, - dy: 10, - textConfig: [ - { - text: '2016\n', - fontWeight: 'bold', - fontSize: 13, - fill: '#E8346D', - fontFamily: 'Times New Roman' - }, - { - text: 'population was 899447', - fontSize: 10, - fill: '#E8346D', - fontFamily: 'Times New Roman' - } - ] + itemContent: { + offsetY: 40, + // offsetX: -200, + type: 'richText', + autoRotate: false, + confine: true, + position: 'insideBottom', + + style: { + width: 100, + height: 50, + dx: 110, + dy: 10, + textConfig: [ + { + text: '2016\n', + fontWeight: 'bold', + fontSize: 13, + fill: '#E8346D', + fontFamily: 'Times New Roman' + }, + { + text: 'population was 899447', + fontSize: 10, + fill: '#E8346D', + fontFamily: 'Times New Roman' } + ] + } + }, + itemLine: { + type: 'type-do', + startSymbol: { + size: 24, + style: { + stroke: '#E8346D' } }, - itemLine: { - type: 'type-do', - startSymbol: { - size: 24, - style: { - stroke: '#E8346D' - } - }, - line: { - style: { - stroke: '#E8346D' - } + line: { + style: { + stroke: '#E8346D' } } } - ], - point: { - style: { - visible: false - } - }, - line: { - style: { - lineWidth: 2 - } - }, - title: { - text: 'Population History - Line Chart', - textStyle: { - lineWidth: 3, - fill: '#333', - fontSize: 20, - fontFamily: 'Times New Roman' - } - }, - data: { - id: 'data2', - values: [ - { - census_year: true, - year: 2016, - source: 'CoE', - population: 899447 - }, - { - census_year: true, - year: 2014, - source: 'CoE', - population: 877926 - }, - { - year: 2013, - source: 'CoE 6', - population: 847712 - }, - { - census_year: true, - year: 2012, - source: 'CoE', - population: 817498 - }, - { - year: 2010, - source: 'CoE 6', - population: 797320 - }, - { - census_year: true, - year: 2009, - source: 'CoE', - population: 782439 - }, - { - census_year: true, - year: 2008, - source: 'CoE', - population: 752412 - }, - { - year: 2007, - source: 'CoE 6', - population: 741392 - }, - { - census_year: true, - year: 2005, - source: 'CoE', - population: 712391 - }, - { - year: 2004, - source: 'CoE 6', - population: 698631 - }, - { - year: 2003, - source: 'CoE 6', - population: 684871 - }, - { - year: 2002, - source: 'CoE 6', - population: 671110 - }, - { - year: 2000, - source: 'CoE 6', - population: 652817 - }, - { - census_year: true, - year: 1999, - source: 'CoE', - population: 648284 - }, - { - year: 1998, - source: 'CoE 6', - population: 637625 - }, - { - year: 1997, - source: 'CoE 6', - population: 626965 - }, - { - year: 1995, - source: 'CoE 6', - population: 619870 - }, - { - year: 1994, - source: 'CoE 6', - population: 623435 - }, - { - census_year: true, - year: 1993, - source: 'CoE', - population: 626999 - }, - { - census_year: true, - year: 1992, - source: 'CoE', - population: 618195 - }, - { - census_year: true, - year: 1990, - source: 'CoE', - population: 605538 - }, - { - census_year: true, - year: 1989, - source: 'CoE', - population: 583872 - }, - { - year: 1988, - source: 'CoE', - population: 580061 - }, - { - census_year: true, - year: 1987, - source: 'CoE', - population: 576249 - }, - { - year: 1985, - source: 'CoE 6', - population: 567699 - }, - { - year: 1984, - source: 'CoE 6', - population: 563892 - }, - { - census_year: true, - year: 1983, - source: 'CoE', - population: 560085 - }, - { - census_year: true, - year: 1982, - source: 'CoE 1', - population: 551314 - }, - { - census_year: true, - year: 1980, - source: 'CoE', - population: 505773 - }, - { - census_year: true, - year: 1979, - source: 'CoE', - population: 491359 - }, - { - census_year: true, - year: 1978, - source: 'CoE', - population: 478066 - }, - { - census_year: true, - year: 1977, - source: 'CoE', - population: 471474 - }, - { - census_year: true, - year: 1975, - source: 'CoE', - population: 451635 - }, - { - census_year: true, - year: 1974, - source: 'CoE', - population: 445691 - }, - { - census_year: true, - year: 1973, - source: 'CoE', - population: 442365 - }, - { - census_year: true, - year: 1972, - source: 'CoE', - population: 441530 - }, - { - census_year: true, - year: 1970, - source: 'CoE', - population: 429750 - }, - { - census_year: true, - year: 1969, - source: 'CoE', - population: 422418 - }, - { - census_year: true, - year: 1968, - source: 'CoE', - population: 410105 - }, - { - census_year: true, - year: 1967, - source: 'CoE', - population: 393593 - }, - { - census_year: true, - year: 1965, - source: 'CoE', - population: 371265 - }, - { - census_year: true, - year: 1964, - source: 'CoE 2', - population: 311804 - }, - { - census_year: true, - year: 1963, - source: 'CoE', - population: 303756 - }, - { - census_year: true, - year: 1962, - source: 'CoE', - population: 294967 - }, - { - census_year: true, - year: 1960, - source: 'CoE', - population: 269314 - }, - { - census_year: true, - year: 1959, - source: 'CoE', - population: 260733 - }, - { - census_year: true, - year: 1958, - source: 'CoE', - population: 252131 - }, - { - census_year: true, - year: 1957, - source: 'CoE', - population: 238353 - }, - { - census_year: true, - year: 1955, - source: 'CoE', - population: 209353 - }, - { - census_year: true, - year: 1954, - source: 'CoE', - population: 197836 - }, - { - census_year: true, - year: 1953, - source: 'CoE', - population: 183411 - }, - { - census_year: true, - year: 1952, - source: 'CoE', - population: 169196 - }, - { - census_year: true, - year: 1950, - source: 'CoE', - population: 148861 - }, - { - census_year: true, - year: 1949, - source: 'CoE', - population: 137469 - }, - { - census_year: true, - year: 1948, - source: 'CoE', - population: 126609 - }, - { - census_year: true, - year: 1947, - source: 'CoE', - population: 118541 - }, - { - census_year: true, - year: 1946, - source: 'CoE', - population: 114976 - }, - { - census_year: true, - year: 1945, - source: 'CoE', - population: 111745 - }, - { - census_year: true, - year: 1944, - source: 'CoE', - population: 108416 - }, - { - census_year: true, - year: 1943, - source: 'CoE', - population: 105536 - }, - { - census_year: true, - year: 1942, - source: 'CoE', - population: 96725 - }, - { - census_year: true, - year: 1940, - source: 'CoE', - population: 91723 - }, - { - census_year: true, - year: 1939, - source: 'CoE', - population: 90419 - }, - { - census_year: true, - year: 1938, - source: 'CoE', - population: 88887 - }, - { - census_year: true, - year: 1937, - source: 'CoE', - population: 87034 - }, - { - census_year: true, - year: 1936, - source: 'CoE', - population: 85470 - }, - { - census_year: true, - year: 1935, - source: 'CoE', - population: 82634 - }, - { - census_year: true, - year: 1934, - source: 'CoE', - population: 79773 - }, - { - census_year: true, - year: 1933, - source: 'CoE', - population: 79231 - }, - { - census_year: true, - year: 1932, - source: 'CoE', - population: 78387 - }, - { - census_year: true, - year: 1930, - source: 'CoE', - population: 77557 - }, - { - census_year: true, - year: 1929, - source: 'CoE', - population: 74298 - }, - { - census_year: true, - year: 1928, - source: 'CoE', - population: 69744 - }, - { - census_year: true, - year: 1927, - source: 'CoE', - population: 67083 - }, - { - census_year: true, - year: 1926, - source: 'CoE', - population: 65163 - }, - { - census_year: true, - year: 1925, - source: 'CoE', - population: 65378 - }, - { - census_year: true, - year: 1924, - source: 'CoE', - population: 63160 - }, - { - census_year: true, - year: 1923, - source: 'CoE*', - population: 60000 - }, - { - census_year: true, - year: 1922, - source: 'CoE*', - population: 60000 - }, - { - census_year: true, - year: 1920, - source: 'CoE', - population: 61045 - }, - { - census_year: true, - year: 1919, - source: 'CoE*', - population: 60000 - }, - { - census_year: true, - year: 1918, - source: 'CoE*', - population: 53000 - }, - { - census_year: true, - year: 1917, - source: 'CoE* 4', - population: 51000 - }, - { - census_year: true, - year: 1916, - source: 'CoE', - population: 53846 - }, - { - census_year: true, - year: 1915, - source: 'CoE', - population: 59339 - }, - { - census_year: true, - year: 1914, - source: 'CoE', - population: 72516 - }, - { - census_year: true, - year: 1913, - source: 'CoE', - population: 67243 - }, - { - census_year: true, - year: 1912, - source: 'CoE 5', - population: 53611 - }, - { - year: 1910, - source: 'CoE 6', - population: 23950 - }, - { - census_year: true, - year: 1909, - source: 'CoE*', - population: 23000 - }, - { - census_year: true, - year: 1908, - source: 'CoE', - population: 18500 - }, - { - year: 1907, - source: 'CoE 6', - population: 16294 - }, - { - census_year: true, - year: 1906, - source: 'CoE', - population: 14088 - }, - { - year: 1905, - source: 'CoE 6', - population: 11219 - }, - { - census_year: true, - year: 1904, - source: 'CoE', - population: 8350 - }, - { - census_year: true, - year: 1903, - source: 'CoE', - population: 6995 - }, - { - year: 1902, - source: 'CoE 6', - population: 4811 - }, - { - year: 1900, - source: 'CoE 6', - population: 2419 - }, - { - census_year: true, - year: 1899, - source: 'CoE', - population: 2212 - }, - { - year: 1898, - source: 'CoE 6', - population: 2212 - }, - { - census_year: true, - year: 1897, - source: 'CoE', - population: 2212 - }, - { - year: 1896, - source: 'CoE 6', - population: 1689 - }, - { - census_year: true, - year: 1895, - source: 'CoE', - population: 1165 - }, - { - year: 1894, - source: 'CoE 6', - population: 1010 - }, - { - year: 1893, - source: 'CoE 6', - population: 855 - }, - { - census_year: true, - year: 1892, - source: 'CoE', - population: 700 - }, - { - year: 1891, - source: 'CoE 6', - population: 630 - }, - { - year: 1890, - source: 'CoE 6', - population: 560 - }, - { - year: 1889, - source: 'CoE 6', - population: 490 - }, - { - year: 1888, - source: 'CoE 6', - population: 420 - }, - { - census_year: true, - year: 1887, - source: 'CoE*', - population: 350 - }, - { - year: 1886, - source: 'CoE', - population: 307 - }, - { - census_year: true, - year: 1885, - source: 'CoE', - population: 263 - }, - { - year: 1884, - source: 'CoE 6', - population: 247 - }, - { - year: 1883, - source: 'CoE 6', - population: 230 - }, - { - year: 1882, - source: 'CoE 6', - population: 214 - }, - { - year: 1881, - source: 'CoE 6', - population: 197 - }, - { - year: 1880, - source: 'CoE 6', - population: 181 - }, - { - year: 1879, - source: 'CoE 6', - population: 164 - }, - { - census_year: true, - year: 1878, - source: 'CoE', - population: 148 - } - ].reverse() } - }; + ], + point: { + style: { + visible: false + } + }, + line: { + style: { + lineWidth: 2 + } + }, + title: { + text: 'Population History - Line Chart', + textStyle: { + lineWidth: 3, + fill: '#333', + fontSize: 20, + fontFamily: 'Times New Roman' + } + }, + data: { + id: 'data2', + values: [ + { + census_year: true, + year: 2016, + source: 'CoE', + population: 899447 + }, + { + census_year: true, + year: 2014, + source: 'CoE', + population: 877926 + }, + { + year: 2013, + source: 'CoE 6', + population: 847712 + }, + { + census_year: true, + year: 2012, + source: 'CoE', + population: 817498 + }, + { + year: 2010, + source: 'CoE 6', + population: 797320 + }, + { + census_year: true, + year: 2009, + source: 'CoE', + population: 782439 + }, + { + census_year: true, + year: 2008, + source: 'CoE', + population: 752412 + }, + { + year: 2007, + source: 'CoE 6', + population: 741392 + }, + { + census_year: true, + year: 2005, + source: 'CoE', + population: 712391 + }, + { + year: 2004, + source: 'CoE 6', + population: 698631 + }, + { + year: 2003, + source: 'CoE 6', + population: 684871 + }, + { + year: 2002, + source: 'CoE 6', + population: 671110 + }, + { + year: 2000, + source: 'CoE 6', + population: 652817 + }, + { + census_year: true, + year: 1999, + source: 'CoE', + population: 648284 + }, + { + year: 1998, + source: 'CoE 6', + population: 637625 + }, + { + year: 1997, + source: 'CoE 6', + population: 626965 + }, + { + year: 1995, + source: 'CoE 6', + population: 619870 + }, + { + year: 1994, + source: 'CoE 6', + population: 623435 + }, + { + census_year: true, + year: 1993, + source: 'CoE', + population: 626999 + }, + { + census_year: true, + year: 1992, + source: 'CoE', + population: 618195 + }, + { + census_year: true, + year: 1990, + source: 'CoE', + population: 605538 + }, + { + census_year: true, + year: 1989, + source: 'CoE', + population: 583872 + }, + { + year: 1988, + source: 'CoE', + population: 580061 + }, + { + census_year: true, + year: 1987, + source: 'CoE', + population: 576249 + }, + { + year: 1985, + source: 'CoE 6', + population: 567699 + }, + { + year: 1984, + source: 'CoE 6', + population: 563892 + }, + { + census_year: true, + year: 1983, + source: 'CoE', + population: 560085 + }, + { + census_year: true, + year: 1982, + source: 'CoE 1', + population: 551314 + }, + { + census_year: true, + year: 1980, + source: 'CoE', + population: 505773 + }, + { + census_year: true, + year: 1979, + source: 'CoE', + population: 491359 + }, + { + census_year: true, + year: 1978, + source: 'CoE', + population: 478066 + }, + { + census_year: true, + year: 1977, + source: 'CoE', + population: 471474 + }, + { + census_year: true, + year: 1975, + source: 'CoE', + population: 451635 + }, + { + census_year: true, + year: 1974, + source: 'CoE', + population: 445691 + }, + { + census_year: true, + year: 1973, + source: 'CoE', + population: 442365 + }, + { + census_year: true, + year: 1972, + source: 'CoE', + population: 441530 + }, + { + census_year: true, + year: 1970, + source: 'CoE', + population: 429750 + }, + { + census_year: true, + year: 1969, + source: 'CoE', + population: 422418 + }, + { + census_year: true, + year: 1968, + source: 'CoE', + population: 410105 + }, + { + census_year: true, + year: 1967, + source: 'CoE', + population: 393593 + }, + { + census_year: true, + year: 1965, + source: 'CoE', + population: 371265 + }, + { + census_year: true, + year: 1964, + source: 'CoE 2', + population: 311804 + }, + { + census_year: true, + year: 1963, + source: 'CoE', + population: 303756 + }, + { + census_year: true, + year: 1962, + source: 'CoE', + population: 294967 + }, + { + census_year: true, + year: 1960, + source: 'CoE', + population: 269314 + }, + { + census_year: true, + year: 1959, + source: 'CoE', + population: 260733 + }, + { + census_year: true, + year: 1958, + source: 'CoE', + population: 252131 + }, + { + census_year: true, + year: 1957, + source: 'CoE', + population: 238353 + }, + { + census_year: true, + year: 1955, + source: 'CoE', + population: 209353 + }, + { + census_year: true, + year: 1954, + source: 'CoE', + population: 197836 + }, + { + census_year: true, + year: 1953, + source: 'CoE', + population: 183411 + }, + { + census_year: true, + year: 1952, + source: 'CoE', + population: 169196 + }, + { + census_year: true, + year: 1950, + source: 'CoE', + population: 148861 + }, + { + census_year: true, + year: 1949, + source: 'CoE', + population: 137469 + }, + { + census_year: true, + year: 1948, + source: 'CoE', + population: 126609 + }, + { + census_year: true, + year: 1947, + source: 'CoE', + population: 118541 + }, + { + census_year: true, + year: 1946, + source: 'CoE', + population: 114976 + }, + { + census_year: true, + year: 1945, + source: 'CoE', + population: 111745 + }, + { + census_year: true, + year: 1944, + source: 'CoE', + population: 108416 + }, + { + census_year: true, + year: 1943, + source: 'CoE', + population: 105536 + }, + { + census_year: true, + year: 1942, + source: 'CoE', + population: 96725 + }, + { + census_year: true, + year: 1940, + source: 'CoE', + population: 91723 + }, + { + census_year: true, + year: 1939, + source: 'CoE', + population: 90419 + }, + { + census_year: true, + year: 1938, + source: 'CoE', + population: 88887 + }, + { + census_year: true, + year: 1937, + source: 'CoE', + population: 87034 + }, + { + census_year: true, + year: 1936, + source: 'CoE', + population: 85470 + }, + { + census_year: true, + year: 1935, + source: 'CoE', + population: 82634 + }, + { + census_year: true, + year: 1934, + source: 'CoE', + population: 79773 + }, + { + census_year: true, + year: 1933, + source: 'CoE', + population: 79231 + }, + { + census_year: true, + year: 1932, + source: 'CoE', + population: 78387 + }, + { + census_year: true, + year: 1930, + source: 'CoE', + population: 77557 + }, + { + census_year: true, + year: 1929, + source: 'CoE', + population: 74298 + }, + { + census_year: true, + year: 1928, + source: 'CoE', + population: 69744 + }, + { + census_year: true, + year: 1927, + source: 'CoE', + population: 67083 + }, + { + census_year: true, + year: 1926, + source: 'CoE', + population: 65163 + }, + { + census_year: true, + year: 1925, + source: 'CoE', + population: 65378 + }, + { + census_year: true, + year: 1924, + source: 'CoE', + population: 63160 + }, + { + census_year: true, + year: 1923, + source: 'CoE*', + population: 60000 + }, + { + census_year: true, + year: 1922, + source: 'CoE*', + population: 60000 + }, + { + census_year: true, + year: 1920, + source: 'CoE', + population: 61045 + }, + { + census_year: true, + year: 1919, + source: 'CoE*', + population: 60000 + }, + { + census_year: true, + year: 1918, + source: 'CoE*', + population: 53000 + }, + { + census_year: true, + year: 1917, + source: 'CoE* 4', + population: 51000 + }, + { + census_year: true, + year: 1916, + source: 'CoE', + population: 53846 + }, + { + census_year: true, + year: 1915, + source: 'CoE', + population: 59339 + }, + { + census_year: true, + year: 1914, + source: 'CoE', + population: 72516 + }, + { + census_year: true, + year: 1913, + source: 'CoE', + population: 67243 + }, + { + census_year: true, + year: 1912, + source: 'CoE 5', + population: 53611 + }, + { + year: 1910, + source: 'CoE 6', + population: 23950 + }, + { + census_year: true, + year: 1909, + source: 'CoE*', + population: 23000 + }, + { + census_year: true, + year: 1908, + source: 'CoE', + population: 18500 + }, + { + year: 1907, + source: 'CoE 6', + population: 16294 + }, + { + census_year: true, + year: 1906, + source: 'CoE', + population: 14088 + }, + { + year: 1905, + source: 'CoE 6', + population: 11219 + }, + { + census_year: true, + year: 1904, + source: 'CoE', + population: 8350 + }, + { + census_year: true, + year: 1903, + source: 'CoE', + population: 6995 + }, + { + year: 1902, + source: 'CoE 6', + population: 4811 + }, + { + year: 1900, + source: 'CoE 6', + population: 2419 + }, + { + census_year: true, + year: 1899, + source: 'CoE', + population: 2212 + }, + { + year: 1898, + source: 'CoE 6', + population: 2212 + }, + { + census_year: true, + year: 1897, + source: 'CoE', + population: 2212 + }, + { + year: 1896, + source: 'CoE 6', + population: 1689 + }, + { + census_year: true, + year: 1895, + source: 'CoE', + population: 1165 + }, + { + year: 1894, + source: 'CoE 6', + population: 1010 + }, + { + year: 1893, + source: 'CoE 6', + population: 855 + }, + { + census_year: true, + year: 1892, + source: 'CoE', + population: 700 + }, + { + year: 1891, + source: 'CoE 6', + population: 630 + }, + { + year: 1890, + source: 'CoE 6', + population: 560 + }, + { + year: 1889, + source: 'CoE 6', + population: 490 + }, + { + year: 1888, + source: 'CoE 6', + population: 420 + }, + { + census_year: true, + year: 1887, + source: 'CoE*', + population: 350 + }, + { + year: 1886, + source: 'CoE', + population: 307 + }, + { + census_year: true, + year: 1885, + source: 'CoE', + population: 263 + }, + { + year: 1884, + source: 'CoE 6', + population: 247 + }, + { + year: 1883, + source: 'CoE 6', + population: 230 + }, + { + year: 1882, + source: 'CoE 6', + population: 214 + }, + { + year: 1881, + source: 'CoE 6', + population: 197 + }, + { + year: 1880, + source: 'CoE 6', + population: 181 + }, + { + year: 1879, + source: 'CoE 6', + population: 164 + }, + { + census_year: true, + year: 1878, + source: 'CoE', + population: 148 + } + ].reverse() + } +}; const vchart = new VChart(spec, { dom: CONTAINER_ID }); vchart.renderSync(); diff --git a/docs/assets/examples/zh/marker/mark-point-image.md b/docs/assets/examples/zh/marker/mark-point-image.md index 7671162d74..e86a19ed6b 100644 --- a/docs/assets/examples/zh/marker/mark-point-image.md +++ b/docs/assets/examples/zh/marker/mark-point-image.md @@ -57,12 +57,10 @@ const spec = { }, itemContent: { type: 'image', - image: { - style: { - dx: -50, - dy: 50, - image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/airplane.png' - } + style: { + dx: -50, + dy: 50, + image: 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/airplane.png' } } } diff --git a/docs/assets/examples/zh/marker/polar-mark-point.md b/docs/assets/examples/zh/marker/polar-mark-point.md index 69b07d2172..16b0de2e7f 100644 --- a/docs/assets/examples/zh/marker/polar-mark-point.md +++ b/docs/assets/examples/zh/marker/polar-mark-point.md @@ -18,289 +18,290 @@ option: roseChart#markPoint ## 代码演示 ```javascript livedemo - const spec = { - data: [ - { - id: 'id0', - values: [ - { type: 'MIDNIGHT', value: 1 }, - { type: '1 AM', value: 1 }, - { type: '2 AM', value: 1 }, - { type: '3 AM', value: 1 }, - { type: '4 AM', value: 1 }, - { type: '5 AM', value: 1 }, - { type: '6 AM', value: 1 }, - { type: '7 AM', value: 1 }, - { type: '8 AM', value: 1 }, - { type: '9 AM', value: 1 }, - { type: '10 AM', value: 1 }, - { type: '11 AM', value: 1 }, - { type: 'NOON', value: 1 }, - { type: '13 AM', value: 1 }, - { type: '14 AM', value: 1 }, - { type: '15 AM', value: 1 }, - { type: '16 AM', value: 1 }, - { type: '17 AM', value: 1 }, - { type: '18 AM', value: 1 }, - { type: '19 AM', value: 1 }, - { type: '20 AM', value: 1 }, - { type: '21 AM', value: 1 }, - { type: '22 AM', value: 1 }, - { type: '23 AM', value: 1 }, - ] - }, - { - id: 'id1', - values: [ - { type: 'a', value: 1 } - ] - } - ], - dataIndex: 0, - type: 'rose', - outerRadius: 0.7, - innerRadius: 0.5, - valueField: 'value', - categoryField: 'type', - seriesField: 'type', - startAngle: -97.5, - title: { - text: 'History of Earth in 24-hour clock', - textStyle: { - height: 50, - lineWidth: 2, - fill: '#333', - fontSize: 20, - fontFamily: 'Times New Roman' - }, - subtextStyle: { - character: [ - { - text: '', - fontFamily: 'Times New Roman', - fontSize: 14, - fill: '#333' - } - ] - } +const spec = { + data: [ + { + id: 'id0', + values: [ + { type: 'MIDNIGHT', value: 1 }, + { type: '1 AM', value: 1 }, + { type: '2 AM', value: 1 }, + { type: '3 AM', value: 1 }, + { type: '4 AM', value: 1 }, + { type: '5 AM', value: 1 }, + { type: '6 AM', value: 1 }, + { type: '7 AM', value: 1 }, + { type: '8 AM', value: 1 }, + { type: '9 AM', value: 1 }, + { type: '10 AM', value: 1 }, + { type: '11 AM', value: 1 }, + { type: 'NOON', value: 1 }, + { type: '13 AM', value: 1 }, + { type: '14 AM', value: 1 }, + { type: '15 AM', value: 1 }, + { type: '16 AM', value: 1 }, + { type: '17 AM', value: 1 }, + { type: '18 AM', value: 1 }, + { type: '19 AM', value: 1 }, + { type: '20 AM', value: 1 }, + { type: '21 AM', value: 1 }, + { type: '22 AM', value: 1 }, + { type: '23 AM', value: 1 } + ] + }, + { + id: 'id1', + values: [{ type: 'a', value: 1 }] + } + ], + dataIndex: 0, + type: 'rose', + outerRadius: 0.7, + innerRadius: 0.5, + valueField: 'value', + categoryField: 'type', + seriesField: 'type', + startAngle: -97.5, + title: { + text: 'History of Earth in 24-hour clock', + textStyle: { + height: 50, + lineWidth: 2, + fill: '#333', + fontSize: 20, + fontFamily: 'Times New Roman' + }, + subtextStyle: { + character: [ + { + text: '', + fontFamily: 'Times New Roman', + fontSize: 14, + fill: '#333' + } + ] + } + }, + axes: [ + { + orient: 'angle', + type: 'band', + zIndex: 999, + tick: { + visible: true, + tickSize: 10, + inside: true, + style: { + stroke: '#fff' + // lineWidth: 2, + } + }, + label: { + visible: true, + inside: true, + style: { + fill: '#fff' + } + }, + grid: { + visible: true, + style: { + lineDash: [0], + stroke: '#fff', + lineWidth: 1 }, - axes: [{ - orient: 'angle', - type: 'band', - zIndex: 999, - tick: { - visible: true, - tickSize: 10, - inside: true, - style: { - stroke: '#fff', - // lineWidth: 2, - } - }, - label: { - visible: true, - inside: true, - style: { - fill: '#fff' - } - }, - grid: { - visible: true, - style: { - lineDash: [0], - stroke: '#fff', - lineWidth: 1 - }, - alignWithLabel: false // grid does not align with label - }, - style: { - zIndex: 400, - } - }], - label: { - visible: false, - position: 'inside' + alignWithLabel: false // grid does not align with label + }, + style: { + zIndex: 400 + } + } + ], + label: { + visible: false, + position: 'inside' + }, + tooltip: { + visible: false + }, + rose: { + style: { + fill: 'rgb(129, 216, 208)' + } + }, + markLine: [ + { + radius: 1.1, + angle: 'MIDNIGHT', + angle1: '3 AM' + }, + { + radius: 1.1, + angle: '6 AM', + angle1: '13 AM' + } + ], + markPoint: [ + { + position: { + x: '50%', + y: '50%' + }, + regionRelative: true, + itemLine: { + visible: false + }, + itemContent: { + type: 'symbol', - }, - tooltip: { - visible: false - }, - rose: { - style: { - fill: 'rgb(129, 216, 208)' - } - }, - markLine: [{ - radius: 1.1, - angle: 'MIDNIGHT', - angle1: '3 AM' - }, { - radius: 1.1, - angle: '6 AM', - angle1: '13 AM' - }], - markPoint: [ - { - position: { - x: '50%', - y: '50%' - }, - regionRelative: true, - itemLine: { - visible: false - }, - itemContent: { - type: 'symbol', - symbol: { - style: { - dx: -80, - dy: -40, - size: 60, - symbolType: '', - fill: 'rgb(129, 216, 208)' - } - } - } - }, { - angle: '4 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: 5, - offsetY: -20, - text: { - text: '4: 00 Origin of life' - } - } - }, { - angle: '5 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: 5, - offsetY: -20, - text: { - text: '5: 00 Oldest Fossils' - } - } - }, { - angle: '14 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: 20, - text: { - text: 'Single-Celled Algae(Acritarchs)', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '18 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Sexual Reproduction', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '20 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Seaweeds', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '21 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Trilobites', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '22 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Coal Swamps', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '23 AM', - radius: 1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: -5, - offsetY: -20, - text: { - text: 'Humans', - style: { - textAlign: 'right' - } - } - } - }, { - angle: '2 AM', - radius: 1.1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: 10, - offsetY: -20, - text: { - text: 'Meteorite Bombardment 0:00 to 3 am' - } - } - }, { - angle: '10 AM', - radius: 1.1, - itemContent: { - type: 'text', - autoRotate: false, - offsetX: 10, - offsetY: 20, - text: { - text: '6:00 to 1: Abundant Banded Iron- Formations' - } - } - }], - }; + style: { + dx: -80, + dy: -40, + size: 60, + symbolType: + '', + fill: 'rgb(129, 216, 208)' + } + } + }, + { + angle: '4 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: 5, + offsetY: -20, + text: { + text: '4: 00 Origin of life' + } + } + }, + { + angle: '5 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: 5, + offsetY: -20, + style: { + text: '5: 00 Oldest Fossils' + } + } + }, + { + angle: '14 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: 20, + style: { + text: 'Single-Celled Algae(Acritarchs)', + textAlign: 'right' + } + } + }, + { + angle: '18 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Sexual Reproduction', + textAlign: 'right' + } + } + }, + { + angle: '20 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Seaweeds', + textAlign: 'right' + } + } + }, + { + angle: '21 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Trilobites', + textAlign: 'right' + } + } + }, + { + angle: '22 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Coal Swamps', + textAlign: 'right' + } + } + }, + { + angle: '23 AM', + radius: 1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: -5, + offsetY: -20, + style: { + text: 'Humans', + textAlign: 'right' + } + } + }, + { + angle: '2 AM', + radius: 1.1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: 10, + offsetY: -20, + style: { + text: 'Meteorite Bombardment 0:00 to 3 am' + } + } + }, + { + angle: '10 AM', + radius: 1.1, + itemContent: { + type: 'text', + autoRotate: false, + offsetX: 10, + offsetY: 20, + style: { + text: '6:00 to 1: Abundant Banded Iron- Formations' + } + } + } + ] +}; const vchart = new VChart(spec, { dom: CONTAINER_ID }); vchart.renderSync(); diff --git a/docs/assets/examples/zh/storytelling/disappear-animation-dissolve-config.md b/docs/assets/examples/zh/storytelling/disappear-animation-dissolve-config.md deleted file mode 100644 index 51b1156772..0000000000 --- a/docs/assets/examples/zh/storytelling/disappear-animation-dissolve-config.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -category: examples -group: storytelling -title: 溶解退场动画特效配置 -keywords: animation,disappear,particle,distortion,blur,glitch,pixelation,dissolve,stage -order: 42-20 -cover: -option: commonChart#animationDisappear ---- - -# 溶解退场动画特效配置 - -VRender 提供了丰富的阶段动画特效,包括粒子分解、扭曲变形、模糊效果、故障艺术、像素化、颜色效果和溶解效果等。这些动画可以通过 `animationDisappear.stage` 配置来应用(也可以尝试应用在`animationAppear.stage`等动画阶段)。 - -其中,溶解效果,根据方向不同,还可以细分为向内溶解、向外溶解、径向溶解、水平溶解、垂直溶解等。 - -## 关键配置 - -- `animationDisappear.stage` 用于配置舞台级别的退场动画特效 - - `type`: 动画类型,可选值为 - - `dissolve`: 溶解, - - `duration`: 动画时长(毫秒) - - `easing`: 缓动函数 - - `options`: 特效配置参数 - - `dissolveType`: 溶解效果类型,默认值为 `outward` - - 'outward': 向内溶解 - 从边缘开始向内溶解 - - 'inward': 向外溶解 - 从中心开始向外溶解 - - 'radial': 径向溶解 - 按角度顺序溶解 - - 'leftToRight': 从左侧开始向右溶解 - - 'rightToLeft': 从右侧开始向左溶解 - - 'topToBottom': 从顶部开始向下溶解 - - 'bottomToTop': 从底部开始向上溶解 - - `useWebGL`: 是否使用WebGL实现 (true: GPU加速, false: CPU计算),默认值为 `true` - - `noiseScale`: 溶解颗粒大小(0: 平滑溶解无颗粒, 1-20: 颗粒大小像素值,值越大颗粒越大),默认值为 `8` - - `fadeEdge`: 是否启用边缘渐变,让溶解效果更自然,默认值为 `true` - -### 代码演示 - -```javascript livedemo -const spec = { - type: 'funnel', - data: { - values: [ - { name: '展示', value: 100 }, - { name: '点击', value: 80 }, - { name: '访问', value: 60 }, - { name: '咨询', value: 40 }, - { name: '订单', value: 20 } - ] - }, - categoryField: 'name', - valueField: 'value', - animationAppear: { - stage: { - type: 'dissolve', - duration: 5000, - easing: 'linear', - options: { - dissolveType: 'topToBottom', - useWebGL: true, - noiseScale: 5, - fadeEdge: false - } - } - }, - animationUpdate: { - duration: 300 - }, - animationEnter: { - duration: 300 - } -}; - -const vchart = new VChart(spec, { dom: CONTAINER_ID }); -vchart.renderAsync(); -``` - -## 相关教程 - -[VChart动画教程](/vchart/guide/tutorial_docs/Animation/Animation_Types) diff --git a/docs/assets/examples/zh/storytelling/disappear-animation-gaussion-blur.md b/docs/assets/examples/zh/storytelling/disappear-animation-gaussion-blur.md new file mode 100644 index 0000000000..c85db66855 --- /dev/null +++ b/docs/assets/examples/zh/storytelling/disappear-animation-gaussion-blur.md @@ -0,0 +1,141 @@ +--- +category: examples +group: storytelling +title: Disappear Animation Gaussian Blur +keywords: animation,morphing,bar,pie,barChart,pieChart,comparison +order: 42-0 +cover: /vchart/preview/disappear-animation-gaussian-blur-2.0.11.gif +option: lineChart#animationAppear +--- + +# 退场动画高斯模糊效果 + +在自定义动画效果中可以通过 `afterStageRender` 方法实现高斯模糊效果。 + +## 关键配置 + +- callBack: 退场动画的自定义回调函数/动画实现类,用于执行用户自定义的退场效果。 + +### 代码演示 + +```javascript livedemo +// import { vglobal } from '@visactor/vchart'; +const vglobal = VCHART_MODULE.vglobal; + +function applyDownsampleBlur(imageData, radius) { + const { width, height } = imageData; + + // 降采样因子,减少计算量 + const downsample = Math.max(1, Math.floor(radius / 2)); + const smallWidth = Math.floor(width / downsample); + const smallHeight = Math.floor(height / downsample); + + // 创建小尺寸的临时canvas + const tempCanvas = vglobal.createCanvas({ + width: smallWidth, + height: smallHeight, + dpr: 1 + }); + const tempCtx = tempCanvas.getContext('2d'); + if (!tempCtx) { + return imageData; + } + + // 将图像绘制到小canvas上 + const originalCanvas = vglobal.createCanvas({ + width: width, + height: height, + dpr: 1 + }); + const originalCtx = originalCanvas.getContext('2d'); + if (!originalCtx) { + return imageData; + } + + originalCtx.putImageData(imageData, 0, 0); + + // 缩小绘制(自动插值) + tempCtx.drawImage(originalCanvas, 0, 0, smallWidth, smallHeight); + + // 应用模糊到小图像 + tempCtx.filter = `blur(${radius / downsample}px)`; + tempCtx.drawImage(tempCanvas, 0, 0); + tempCtx.filter = 'none'; + + // 放大回原尺寸 + originalCtx.clearRect(0, 0, width, height); + originalCtx.drawImage(tempCanvas, 0, 0, width, height); + + return originalCtx.getImageData(0, 0, width, height); +} + +function gaussianBlurAnimate(canvas, ratio) { + const blurRadius = ratio * 8; + + // 如果模糊强度为0,直接返回原图 + if (blurRadius <= 0) { + return canvas; + } + + // 使用传统的像素级模糊 + const c = vglobal.createCanvas({ + width: canvas.width, + height: canvas.height, + dpr: vglobal.devicePixelRatio + }); + const ctx = c.getContext('2d'); + if (!ctx) { + return false; + } + + // 清空画布 + ctx.clearRect(0, 0, canvas.width, canvas.height); + + // 绘制原始图像 + ctx.drawImage(canvas, 0, 0); + + // 获取图像数据 + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + + // 高质量模式下统一使用降采样模糊 + const blurredImageData = applyDownsampleBlur(imageData, blurRadius); + + // 将模糊后的图像数据绘制到画布上 + ctx.putImageData(blurredImageData, 0, 0); + + // 添加白色遮罩层 + ctx.fillStyle = `rgba(255, 255, 255, ${ratio.toFixed(2)})`; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + return c; +} + +const spec = { + type: 'bar', + data: [ + { + id: 'barData', + values: [ + { month: 'Monday', sales: 22 }, + { month: 'Tuesday', sales: 13 }, + { month: 'Wednesday', sales: 25 }, + { month: 'Thursday', sales: 29 }, + { month: 'Friday', sales: 38 } + ] + } + ], + xField: 'month', + yField: 'sales', + animationDisappear: { + callBack: (stage, canvas, ratio) => gaussianBlurAnimate(canvas, ratio), + duration: 2000 + } +}; + +const vchart = new VChart(spec, { dom: CONTAINER_ID }); +vchart.renderAsync(); + +setInterval(() => { + vchart.runDisappearAnimation(); +}, 4000); +``` diff --git a/docs/assets/examples/zh/storytelling/disappear-animation-glitch-config.md b/docs/assets/examples/zh/storytelling/disappear-animation-glitch-config.md deleted file mode 100644 index c7e97643c3..0000000000 --- a/docs/assets/examples/zh/storytelling/disappear-animation-glitch-config.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -category: examples -group: storytelling -title: 故障退场动画特效配置 -keywords: animation,disappear,particle,distortion,blur,glitch,pixelation,dissolve,stage -order: 42-20 -cover: -option: commonChart#animationDisappear ---- - -# 故障退场动画特效配置 - -VRender 提供了丰富的阶段动画特效,包括粒子分解、扭曲变形、模糊效果、故障艺术、像素化、颜色效果和溶解效果等。这些动画可以通过 `animationDisappear.stage` 配置来应用(也可以尝试应用在`animationAppear.stage`等动画阶段)。 - -其中,故障效果支持 'rgb-shift'、'digital-distortion'、'scan-lines'、'data-corruption' 四种类型 - -## 关键配置 - -- `animationDisappear.stage` 用于配置舞台级别的退场动画特效 - - `type`: 动画类型 - - `glitch`: 故障, - - `duration`: 动画时长(毫秒) - - `easing`: 缓动函数 - - `options`: 特效配置参数 - - `effectType`: 特效类型,默认值为 `rgb-shift` - - `rgb-shift`: RGB 偏移, - - `digital-distortion`: 数字失真, - - `scan-lines`: 扫描线, - - `data-corruption`: 数据损坏, - - `intensity`: 特效强度,范围为 0 到 1,默认值为 0.5 - - -### 代码演示 - -```javascript livedemo -const spec = { - type: 'bar', - data: { - values: [ - { type: 'Nail polish', country: 'Africa', value: 4229 }, - { type: 'Nail polish', country: 'EU', value: 4376 }, - { type: 'Nail polish', country: 'China', value: 3054 }, - { type: 'Nail polish', country: 'USA', value: 12814 }, - { type: 'Eyebrow pencil', country: 'Africa', value: 3932 }, - { type: 'Eyebrow pencil', country: 'EU', value: 3987 }, - { type: 'Eyebrow pencil', country: 'China', value: 5067 }, - { type: 'Eyebrow pencil', country: 'USA', value: 13012 }, - { type: 'Rouge', country: 'Africa', value: 5221 }, - { type: 'Rouge', country: 'EU', value: 3574 }, - { type: 'Rouge', country: 'China', value: 7004 }, - { type: 'Rouge', country: 'USA', value: 11624 }, - { type: 'Lipstick', country: 'Africa', value: 9256 }, - { type: 'Lipstick', country: 'EU', value: 4376 }, - { type: 'Lipstick', country: 'China', value: 9054 }, - { type: 'Lipstick', country: 'USA', value: 8814 } - ] - }, - xField: 'type', - yField: 'value', - seriesField: 'country', - animationAppear: { - stage: { - type: 'glitch', - duration: 3000, - easing: 'linear', - options: { - effectType: 'digital-distortion', - intensity: 1 - } - }, - type: 'fadeOut', - duration: 3000, - easing: 'linear' - }, - animationUpdate: { - duration: 300 - }, - animationEnter: { - duration: 300 - }, -}; - -const vchart = new VChart(spec, { dom: CONTAINER_ID }); -vchart.renderSync(); -``` - -## 相关教程 - -[VChart动画教程](/vchart/guide/tutorial_docs/Animation/Animation_Types) - diff --git a/docs/assets/examples/zh/storytelling/disappear-animation-wipe.md b/docs/assets/examples/zh/storytelling/disappear-animation-wipe.md new file mode 100644 index 0000000000..28e18e5c1d --- /dev/null +++ b/docs/assets/examples/zh/storytelling/disappear-animation-wipe.md @@ -0,0 +1,117 @@ +--- +category: examples +group: storytelling +title: Disappear Animation Wipe +keywords: animation,morphing,bar,pie,barChart,pieChart,comparison +order: 42-0 +cover: /vchart/preview/disappear-animation-wipe-2.0.11.gif +option: lineChart#animationAppear +--- + +# 退场动画擦除效果 + +在自定义动画效果中可以通过 `afterStageRender` 方法实现擦除动画效果。 + +## 关键配置 + +- callBack: 退场动画的自定义回调函数/动画实现类,用于执行用户自定义的退场效果。 + +### 代码演示 + +```javascript livedemo +// import { vglobal } from '@visactor/vchart'; +const vglobal = VCHART_MODULE.vglobal; + +function wipeAnimate(canvas, ratio) { + // 创建临时画布 + const c = vglobal.createCanvas({ + width: canvas.width, + height: canvas.height, + dpr: vglobal.devicePixelRatio + }); + const ctx = c.getContext('2d'); + if (!ctx) { + return false; + } + + // 将原画布内容绘制到临时画布 + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(canvas, 0, 0); + + // 获取临时画布的图像数据 + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const data = imageData.data; + + // 根据ratio计算擦除位置(从左到右) + const wipePosition = Math.floor(canvas.width * ratio); + + // 设置渐变区域宽度,可根据需要调整 + const gradientWidth = Math.min(canvas.width * 0.3, 50); + + // 遍历每个像素点 + for (let y = 0; y < canvas.height; y++) { + for (let x = 0; x < canvas.width; x++) { + // 计算当前像素在数据数组中的索引 + const index = (y * canvas.width + x) * 4; + + // 计算当前像素的原始透明度 + const originalAlpha = data[index + 3]; + + // 计算当前像素与擦除位置的距离 + const distance = x - wipePosition; + + // 根据距离计算透明度 + let newAlpha; + if (distance <= 0) { + // 擦除位置左侧:完全透明 + newAlpha = 0; + } else if (distance <= gradientWidth) { + // 渐变区域内:透明度从0到原始透明度渐变 + const gradientRatio = distance / gradientWidth; + newAlpha = Math.floor(originalAlpha * gradientRatio); + } else { + // 擦除位置右侧:保持原始透明度 + newAlpha = originalAlpha; + } + + // 设置新的透明度 + data[index + 3] = newAlpha; + } + } + + // 将处理后的图像数据绘制回临时画布 + ctx.putImageData(imageData, 0, 0); + + return c; +} + +const spec = { + type: 'bar', + data: [ + { + id: 'barData', + values: [ + { month: 'Monday', sales: 22 }, + { month: 'Tuesday', sales: 13 }, + { month: 'Wednesday', sales: 25 }, + { month: 'Thursday', sales: 29 }, + { month: 'Friday', sales: 38 } + ] + } + ], + xField: 'month', + yField: 'sales', + animationDisappear: { + callBack: (stage, canvas, ratio) => wipeAnimate(canvas, ratio), + easing: 'linear', + duration: 2000 + } +}; + +const vchart = new VChart(spec, { dom: CONTAINER_ID }); +vchart.renderAsync(); + +setInterval(() => { + vchart.runDisappearAnimation(); +}, 3000); +``` diff --git a/docs/assets/examples/zh/storytelling/disappear-animation.md b/docs/assets/examples/zh/storytelling/disappear-animation.md new file mode 100644 index 0000000000..f649c3c987 --- /dev/null +++ b/docs/assets/examples/zh/storytelling/disappear-animation.md @@ -0,0 +1,101 @@ +--- +category: examples +group: storytelling +title: Disappear Animation +keywords: animation,morphing,bar,pie,barChart,pieChart,comparison +order: 42-0 +cover: /vchart/preview/disappear-animation-2.0.11.gif +option: lineChart#animationAppear +--- + +# 退场动画 + +用户可以手动调用 `vchart.runDisappearAnimation()` 方法执行退场动画。 +退场动画与入场、更新等其他动画配置的差异之处在于退场动画额外提供了 `callBack` 参数用于执行用户的自定义退场效果。 +用户可以在 `callBack` 参数中配置动画的自定义插值回调函数,或者提供一个继承自 `AStageAnimation` 的动画实现类。 + +## 关键配置 + +- callBack: 退场动画的自定义回调函数/动画实现类,用于执行用户自定义的退场效果。 + +### 代码演示 + +```javascript livedemo +// import { vglobal } from '@visactor/vchart'; +// import { AStageAnimate } from '@visactor/vrender-animate'; +const vglobal = VCHART_MODULE.vglobal; +const AStageAnimate = VRender.AStageAnimate; + +// 自定义退场动画实现类 +class TestStageAnimate extends AStageAnimate { + onUpdate(end, ratio, out) { + super.onUpdate(end, ratio, out); + this.ratio = ratio; + } + + // 更新画布渲染内容 + afterStageRender(stage, canvas) { + const c = vglobal.createCanvas({ + width: canvas.width, + height: canvas.height, + dpr: vglobal.devicePixelRatio + }); + const ctx = c.getContext('2d'); + if (!ctx) { + return false; + } + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(canvas, 0, 0); + ctx.fillStyle = `rgba(255, 255, 255, ${this.ratio.toFixed(2)})`; + ctx.fillRect(0, 0, canvas.width, canvas.height); + return c; + } +} + +const spec = { + type: 'bar', + data: [ + { + id: 'barData', + values: [ + { month: 'Monday', sales: 22 }, + { month: 'Tuesday', sales: 13 }, + { month: 'Wednesday', sales: 25 }, + { month: 'Thursday', sales: 29 }, + { month: 'Friday', sales: 38 } + ] + } + ], + xField: 'month', + yField: 'sales', + animationDisappear: { + // 自定义动画执行回调函数 + callBack: (stage, canvas, ratio) => { + const c = vglobal.createCanvas({ + width: canvas.width, + height: canvas.height, + dpr: vglobal.devicePixelRatio + }); + const ctx = c.getContext('2d'); + if (!ctx) { + return false; + } + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(canvas, 0, 0); + ctx.fillStyle = `rgba(255, 255, 255, ${ratio.toFixed(2)})`; + ctx.fillRect(0, 0, canvas.width, canvas.height); + return c; + }, + // 自定义动画执行类使用方式 + // callBack: TestStageAnimate, + duration: 1000 + } +}; + +const vchart = new VChart(spec, { dom: CONTAINER_ID }); +vchart.renderAsync(); + +setInterval(() => { + vchart.runDisappearAnimation(); +}, 2000); +``` diff --git a/docs/assets/examples/zh/vscreen/gauge.md b/docs/assets/examples/zh/vscreen/gauge.md index 047d3d8733..5b55e3247f 100644 --- a/docs/assets/examples/zh/vscreen/gauge.md +++ b/docs/assets/examples/zh/vscreen/gauge.md @@ -134,50 +134,49 @@ const spec = { itemContent: { type: 'richText', autoRotate: false, - richText: { - style: { - width: 40000, - height: 40000, - textAlign: 'left', - textBaseline: 'top', - type: 'rich', - textConfig: [ - { - visible: false, - text: '\n', - fontSize: 12, - fill: '#FFF', - fontWeight: 'normal', - fontFamily: 'D-DIN', - textAlign: 'center', - textBaseline: 'middle' - }, - { - visible: true, - text: 'Profit', - fontSize: 16, - fill: '#FFF', - fontWeight: 'normal', - fontFamily: 'D-DIN', - textAlign: 'center', - textBaseline: 'middle' - }, - { - text: ' ', - fontSize: 8 - }, - { - visible: true, - text: '341.80', - fontSize: 32, - fill: '#FFF', - fontWeight: 'bold', - fontFamily: 'D-DIN', - textAlign: 'center', - textBaseline: 'middle' - } - ] - } + + style: { + width: 40000, + height: 40000, + textAlign: 'left', + textBaseline: 'top', + type: 'rich', + textConfig: [ + { + visible: false, + text: '\n', + fontSize: 12, + fill: '#FFF', + fontWeight: 'normal', + fontFamily: 'D-DIN', + textAlign: 'center', + textBaseline: 'middle' + }, + { + visible: true, + text: 'Profit', + fontSize: 16, + fill: '#FFF', + fontWeight: 'normal', + fontFamily: 'D-DIN', + textAlign: 'center', + textBaseline: 'middle' + }, + { + text: ' ', + fontSize: 8 + }, + { + visible: true, + text: '341.80', + fontSize: 32, + fill: '#FFF', + fontWeight: 'bold', + fontFamily: 'D-DIN', + textAlign: 'center', + textBaseline: 'middle' + } + ] } } } diff --git a/docs/assets/option/en/animate/animation.md b/docs/assets/option/en/animate/animation.md index 2357a65195..5d108dab6c 100644 --- a/docs/assets/option/en/animate/animation.md +++ b/docs/assets/option/en/animate/animation.md @@ -135,36 +135,6 @@ ${markName} mark animation config. {{ /for }} -##${prefix} type='IStageAnimateSpec'(object) -Stage effect animation configuration. Provides various cool exit animation effects, including particle disintegration, distortion, blur effects, glitch art, pixelation, color effects, and dissolve effects. - -###${prefix} stage(object) -Stage animation configuration. - -####${prefix} type(string) -Animation effect type. Available values: - -- `'particle'`: Particle disintegration effect -- `'distortion'`: Distortion effect -- `'gaussianBlur'`: Gaussian blur effect -- `'glitch'`: Glitch art effect -- `'pixelation'`: Pixelation effect -- `'grayscale'`: Color effect -- `'dissolve'`: Dissolve effect - -####${prefix} duration(number) = 2000 -Animation duration in milliseconds. - -####${prefix} easing(string) = 'linear' -Animation easing effect. Supported values: 'linear', 'quadIn', 'quadOut', 'quadInOut', 'cubicIn', 'cubicOut', 'cubicInOut', 'quartIn', 'quartOut', 'quartInOut', 'quintIn', 'quintOut', 'quintInOut', 'backIn', 'backOut', 'backInOut', 'circIn', 'circOut', 'circInOut', 'bounceOut', 'bounceIn', 'bounceInOut', 'elasticIn', 'elasticOut', 'elasticInOut'. - -####${prefix} options(object) -Specific effect configuration parameters, which vary based on different `type` values. - -{{ use: animate-stage-options( prefix = '####' + ${prefix} ) }} - -{{ /for }} - #${prefix} animationState(boolean|object) Animation effect when the graphic state changes. Supported after version `1.12.0`. diff --git a/docs/assets/option/en/animate/stage-options.md b/docs/assets/option/en/animate/stage-options.md deleted file mode 100644 index 54d7b3a5d8..0000000000 --- a/docs/assets/option/en/animate/stage-options.md +++ /dev/null @@ -1,250 +0,0 @@ -{{ target: animate-stage-options }} - - - -#${prefix} type = 'particle' - -Particle Disintegration Effect -Configuration parameters when `type` is `'particle'`: - -##${prefix} effectType(string) = 'gravity' -Particle motion mode. Available values: - -- `'explode'`: Explosion effect - particles scatter outward from center -- `'vortex'`: Vortex effect - particles expand outward in a spiral pattern -- `'gravity'`: Gravity effect - particles disintegrate and fall - -##${prefix} count(number) = 4000 -Number of particles. Value range: 1000-8000. - -##${prefix} size(number) = 20 -Particle size. Value range: 2-15. - -##${prefix} strength(number) = 1.0 -Force field strength. Value range: 0.1-3.0. - -##${prefix} useWebGL(boolean) = true -Whether to use WebGL implementation. - -**Usage Example:** - -```typescript -animationDisappear: { - stage: { - type: 'particle', - duration: 3000, - easing: 'linear', - options: { - effectType: 'vortex', - count: 6000, - size: 8, - strength: 2.0, - useWebGL: true - } - } -} -``` - -#${prefix} type = 'distortion' - -Distortion Effect -Configuration parameters when `type` is `'distortion'`: - -##${prefix} distortionType(string) = 'wave' -Distortion effect type. Available values: - -- `'wave'`: Wave distortion - sinusoidal wave distortion producing wave effects -- `'ripple'`: Ripple distortion - circular ripples expanding from center point -- `'swirl'`: Swirl distortion - rotational distortion around center point - -##${prefix} strength(number) = 0.3 -Distortion strength. Value range: 0.0-2.0. - -##${prefix} useWebGL(boolean) = true -Whether to use WebGL implementation. - -**Usage Example:** - -```typescript -animationDisappear: { - stage: { - type: 'distortion', - duration: 3000, - easing: 'linear', - options: { - distortionType: 'wave', - strength: 0.8, - useWebGL: true - } - } -} -``` - -#${prefix} type = 'gaussianBlur' - -Gaussian Blur Effect -Configuration parameters when `type` is `'gaussianBlur'`: - -##${prefix} blurRadius(number) = 8 -Blur intensity. Value range: 1-20. - -##${prefix} useOptimizedBlur(boolean) = true -Whether to use optimized version. - -- `true`: High-performance mode - uses CSS filters with GPU acceleration -- `false`: High-quality mode - uses pixel-level downsampling algorithm - -**Usage Example:** - -```typescript -animationDisappear: { - stage: { - type: 'gaussianBlur', - duration: 1000, - easing: 'linear', - options: { - blurRadius: 10, - useOptimizedBlur: true - } - } -} -``` - -#${prefix} type = 'glitch' - -Glitch Art Effect -Configuration parameters when `type` is `'glitch'`: - -##${prefix} effectType(string) = 'rgb-shift' -Glitch effect type. Available values: - -- `'rgb-shift'`: RGB channel shift - red, green, blue color channel separation and offset -- `'digital-distortion'`: Digital distortion - horizontal slice offset + random pixel noise -- `'scan-lines'`: Scan line glitch - horizontal scan lines and bright line effects -- `'data-corruption'`: Data corruption - vertical stripes + block corruption - -##${prefix} intensity(number) = 0.5 -Glitch intensity. Value range: 0.0-1.0. - -**Usage Example:** - -```typescript -animationDisappear: { - stage: { - type: 'glitch', - duration: 1000, - easing: 'linear', - options: { - effectType: 'rgb-shift', - intensity: 0.5 - } - } -} -``` - -#${prefix} type = 'pixelation' - -Pixelation Effect -Configuration parameters when `type` is `'pixelation'`: - -##${prefix} maxPixelSize(number) = 20 -Maximum pixelation intensity. Value range: 1-50. - -##${prefix} method(string) = 'out' -Pixelation direction. Available values: - -- `'out'`: Exit effect - pixelation intensity gradually increases from 1 to maximum -- `'in'`: Enter effect - pixelation intensity gradually decreases from maximum to 1 - -**Usage Example:** - -```typescript -animationDisappear: { - stage: { - type: 'pixelation', - duration: 2000, - easing: 'linear', - options: { - maxPixelSize: 25, - method: 'out' - } - } -} -``` - -#${prefix} type = 'grayscale' - -Color Effect -Configuration parameters when `type` is `'grayscale'`: - -##${prefix} effectType(string) = 'grayscale' -Color effect type. Available values: - -- `'grayscale'`: Grayscale effect - converts to black and white using standard luminance formula -- `'sepia'`: Sepia effect - nostalgic style sepia filter - -##${prefix} strength(number) = 1.0 -Effect strength. Value range: 0.0-1.0. - -##${prefix} useWebGL(boolean) = true -Whether to use WebGL implementation. - -**Usage Example:** - -```typescript -animationDisappear: { - stage: { - type: 'grayscale', - duration: 2000, - easing: 'linear', - options: { - effectType: 'grayscale', - strength: 1.0, - useWebGL: true - } - } -} -``` - -#${prefix} type = 'dissolve' - -Dissolve Effect -Configuration parameters when `type` is `'dissolve'`: - -##${prefix} dissolveType(string) = 'outward' -Dissolve direction. Available values: - -- `'outward'`: Dissolve from center outward -- `'inward'`: Dissolve from outside to center -- `'radial'`: Radial dissolve -- `'leftToRight'`: Dissolve from left to right -- `'rightToLeft'`: Dissolve from right to left -- `'topToBottom'`: Dissolve from top to bottom -- `'bottomToTop'`: Dissolve from bottom to top - -##${prefix} noiseScale(number) = 8 -Noise scale. Value range: 1-20. - -##${prefix} fadeEdge(boolean) = true -Whether to use edge fading. - -##${prefix} strength(number) = 1.0 -Dissolve strength. Value range: 0.0-2.0. - -**Usage Example:** - -```typescript -animationDisappear: { - stage: { - type: 'dissolve', - duration: 2000, - easing: 'linear', - options: { - dissolveType: 'radial', - noiseScale: 10, - fadeEdge: true, - strength: 1.2 - } - } -} -``` diff --git a/docs/assets/option/en/component/mark-point.md b/docs/assets/option/en/component/mark-point.md index 32ff1f71b7..5d867e6103 100644 --- a/docs/assets/option/en/component/mark-point.md +++ b/docs/assets/option/en/component/mark-point.md @@ -216,76 +216,42 @@ In addition to directly configuring offset values, since the `1.11.0` version: Since version 1.8.7, whether to automatically adjust item content so that it is displayed within the visible area of ​​​​the marker. -#### symbol(Object) - -When the content type is symbol, the state and style are configured. - -{{ use: component-marker-state( - prefix = '####', - graphicType = 'symbol' -) }} - -##### style(Object) - -For mark content type 'symbol', the symbol style. - -{{ use: component-marker-style-callback( - description = 'symbol style' -) }} - -{{ use: graphic-symbol( - prefix = '#####' -) }} - -#### image(Object) +#### text(Object) -When the content type is image, the state and style are configured. +For mark content type 'text', the text style. -{{ use: component-marker-state( +{{ use: component-marker-label( prefix = '####', - graphicType = 'image' + noConfine = true, + noMarkerRef = true, + noAutoRotate = true ) }} -##### style(Object) - -For mark content type 'image', the image style. +#### style(Object) {{ use: component-marker-style-callback( - description = 'image style' + description = 'image | text | richText | symbol style' ) }} {{ use: graphic-image( - prefix = '#####' + prefix = '####' ) }} -#### text(Object) - -For mark content type 'text', the text style. - -{{ use: component-marker-label( - prefix = '####', - noConfine = true +{{ use: graphic-text( + prefix = '####' ) }} -#### richText(Object) - -When the content type is richText, the state and style are configured. - -{{ use: component-marker-state( - prefix = '####', - graphicType = 'richText' +{{ use: graphic-rich-text( + prefix = '####' ) }} -##### style(Object) - -For mark content type 'richText', the richText style. - -{{ use: component-marker-style-callback( - description = 'richText style' +{{ use: graphic-symbol( + prefix = '####' ) }} -{{ use: graphic-rich-text( - prefix = '#####' +{{ use: component-marker-state( + prefix = '###', + graphicType = 'all' ) }} {{ use: component-marker-animation( diff --git a/docs/assets/option/en/component/marker-common/marker-label.md b/docs/assets/option/en/component/marker-common/marker-label.md index 06dc5b152b..9ad0b171e2 100644 --- a/docs/assets/option/en/component/marker-common/marker-label.md +++ b/docs/assets/option/en/component/marker-common/marker-label.md @@ -4,10 +4,13 @@ Label visibility. +{{ if: !${noAutoRotate} }} #${prefix} autoRotate(boolean) Label as a whole - whether to auto-rotate. +{{ /if }} + {{ if: !${noMarkerRef} }} {{ use: component-marker-ref( prefix = ${prefix} diff --git a/docs/assets/option/en/component/marker-common/marker-state.md b/docs/assets/option/en/component/marker-common/marker-state.md index 716d30ed58..b950f1b408 100644 --- a/docs/assets/option/en/component/marker-common/marker-state.md +++ b/docs/assets/option/en/component/marker-common/marker-state.md @@ -3,6 +3,7 @@ #${prefix} state(Object) Supported since `1.11.0` version, annotate the interaction state configuration of components. The label line currently has the following four states. You can configure the line style after these interactive states are triggered. + - `'hover'`: hover state - `'hover_reverse'`: non-hover state - `'selected'`: selected state @@ -11,209 +12,249 @@ The label line currently has the following four states. You can configure the li ##${prefix} hover(Object) hover state。 -###${prefix} style(Object|Array) - -{{ use: component-marker-style-callback( - description = 'hover state of annotation style supports callback' -) }} - {{ if: ${graphicType} === 'line' }} {{ use: graphic-line( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'polygon' }} {{ use: graphic-polygon( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'symbol' }} {{ use: graphic-symbol( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'image' }} {{ use: graphic-image( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'richText' }} {{ use: graphic-rich-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'rect' }} {{ use: graphic-rect( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'text' }} {{ use: graphic-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} +{{ if: ${graphicType} === 'all' }} +{{ use: graphic-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-rich-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-image( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-symbol( + prefix = '##' + ${prefix} +) }} +{{ /if }} ##${prefix} hover_reverse(Object) 非 hover state。 -###${prefix} style(Object|Array) - {{ use: component-marker-style-callback( description = 'unHover state of annotation style supports callback' ) }} {{ if: ${graphicType} === 'line' }} {{ use: graphic-line( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'polygon' }} {{ use: graphic-polygon( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'symbol' }} {{ use: graphic-symbol( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'image' }} {{ use: graphic-image( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'richText' }} {{ use: graphic-rich-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'rect' }} {{ use: graphic-rect( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'text' }} {{ use: graphic-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} +) }} +{{ /if }} +{{ if: ${graphicType} === 'all' }} +{{ use: graphic-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-rich-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-image( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-symbol( + prefix = '##' + ${prefix} ) }} {{ /if }} - - ##${prefix} selected(Object) selected state -###${prefix} style(Object|Array) - {{ use: component-marker-style-callback( description = 'selected state of annotation style supports callback' ) }} {{ if: ${graphicType} === 'line' }} {{ use: graphic-line( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'polygon' }} {{ use: graphic-polygon( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'symbol' }} {{ use: graphic-symbol( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'image' }} {{ use: graphic-image( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'richText' }} {{ use: graphic-rich-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'rect' }} {{ use: graphic-rect( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'text' }} {{ use: graphic-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} +{{ if: ${graphicType} === 'all' }} +{{ use: graphic-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-rich-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-image( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-symbol( + prefix = '##' + ${prefix} +) }} +{{ /if }} ##${prefix} selected_reverse(Object) unSelected state -###${prefix} style(Object|Array) - {{ use: component-marker-style-callback( description = 'unSelected state of annotation style supports callback' ) }} {{ if: ${graphicType} === 'line' }} {{ use: graphic-line( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'polygon' }} {{ use: graphic-polygon( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'symbol' }} {{ use: graphic-symbol( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'image' }} {{ use: graphic-image( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'richText' }} {{ use: graphic-rich-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'rect' }} {{ use: graphic-rect( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'text' }} {{ use: graphic-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} +) }} +{{ /if }} +{{ if: ${graphicType} === 'all' }} +{{ use: graphic-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-rich-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-image( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-symbol( + prefix = '##' + ${prefix} ) }} {{ /if }} - - diff --git a/docs/assets/option/zh/animate/animation.md b/docs/assets/option/zh/animate/animation.md index 7c4cf496d5..95e537ec7b 100644 --- a/docs/assets/option/zh/animate/animation.md +++ b/docs/assets/option/zh/animate/animation.md @@ -135,36 +135,6 @@ ${markName} 图元的动画配置。 {{ /for }} -##${prefix} type='IStageAnimateSpec'(object) -舞台特效动画配置。提供多种炫酷的退场动画效果,包括粒子分解、扭曲变形、模糊效果、故障艺术、像素化、颜色效果和溶解效果等。 - -###${prefix} stage(object) -舞台动画配置。 - -####${prefix} type(string) -动画效果类型。可选值: - -- `'particle'`: 粒子分解效果 -- `'distortion'`: 扭曲变形效果 -- `'gaussianBlur'`: 高斯模糊效果 -- `'glitch'`: 故障艺术效果 -- `'pixelation'`: 像素化效果 -- `'grayscale'`: 颜色效果 -- `'dissolve'`: 溶解效果 - -####${prefix} duration(number) = 2000 -动画持续时间,单位毫秒。 - -####${prefix} easing(string) = 'linear' -动画缓动效果。支持的值有:'linear', 'quadIn', 'quadOut', 'quadInOut', 'cubicIn', 'cubicOut', 'cubicInOut', 'quartIn', 'quartOut', 'quartInOut', 'quintIn', 'quintOut', 'quintInOut', 'backIn', 'backOut', 'backInOut', 'circIn', 'circOut', 'circInOut', 'bounceOut', 'bounceIn', 'bounceInOut', 'elasticIn', 'elasticOut', 'elasticInOut'。 - -####${prefix} options(object) -具体效果配置参数,根据不同的 `type` 有不同的配置项。 - -{{ use: animate-stage-options( prefix = '####' + ${prefix} ) }} - -{{ /for }} - #${prefix} animationState(boolean|object) 图元状态切换时的动画效果。自 `1.12.0` 版本后支持。 diff --git a/docs/assets/option/zh/animate/stage-options.md b/docs/assets/option/zh/animate/stage-options.md deleted file mode 100644 index 2f7fbf4de6..0000000000 --- a/docs/assets/option/zh/animate/stage-options.md +++ /dev/null @@ -1,246 +0,0 @@ -{{ target: animate-stage-options }} - - - -#${prefix} type = 'particle' - -粒子分解效果 -当 `type` 为 `'particle'` 时的配置参数: - -##${prefix} effectType(string) = 'gravity' -粒子运动模式。可选值: - -- `'explode'`: 爆炸效果 - 粒子从中心向外飞散 -- `'vortex'`: 漩涡效果 - 粒子以螺旋方式向外扩散 -- `'gravity'`: 重力效果 - 粒子瓦解下落 - -##${prefix} count(number) = 4000 -粒子数量。取值范围:1000-8000。 - -##${prefix} size(number) = 20 -粒子大小。取值范围:2-15。 - -##${prefix} strength(number) = 1.0 -力场强度。取值范围:0.1-3.0。 - -##${prefix} useWebGL(boolean) = true -是否使用 WebGL 实现。 - -**使用示例:** - -```typescript -animationDisappear: { - stage: { - type: 'particle', - duration: 3000, - easing: 'linear', - options: { - effectType: 'vortex', - count: 6000, - size: 8, - strength: 2.0, - useWebGL: true - } - } -} -``` - -#${prefix} type = 'distortion' - -扭曲变形效果 -当 `type` 为 `'distortion'` 时的配置参数: - -##${prefix} distortionType(string) = 'wave' -扭曲效果类型。可选值: - -- `'wave'`: 波浪扭曲 - 正弦波形扭曲,产生波浪效果 -- `'ripple'`: 涟漪扭曲 - 从中心点扩散的圆形波纹 -- `'swirl'`: 漩涡扭曲 - 围绕中心点的旋转扭曲 - -##${prefix} strength(number) = 0.3 -扭曲强度。取值范围:0.0-2.0。 - -##${prefix} useWebGL(boolean) = true -是否使用 WebGL 实现。 - -**使用示例:** - -```typescript -animationDisappear: { - stage: { - type: 'distortion', - duration: 3000, - easing: 'linear', - options: { - distortionType: 'wave', - strength: 0.8, - useWebGL: true - } - } -} -``` - -#${prefix} type = 'gaussianBlur' - -高斯模糊效果 -当 `type` 为 `'gaussianBlur'` 时的配置参数: - -##${prefix} blurRadius(number) = 8 -模糊强度。取值范围:1-20。 - -##${prefix} useOptimizedBlur(boolean) = true -是否使用优化版本。 - -- `true`: 高性能模式 - 使用 CSS 滤镜,GPU 加速 -- `false`: 高质量模式 - 使用像素级降采样算法 - -**使用示例:** - -```typescript -animationDisappear: { - stage: { - type: 'gaussianBlur', - duration: 1000, - easing: 'linear', - options: { - blurRadius: 10, - useOptimizedBlur: true - } - } -} -``` - -#${prefix} type = 'glitch' - -故障艺术效果 -当 `type` 为 `'glitch'` 时的配置参数: - -##${prefix} effectType(string) = 'rgb-shift' -故障效果类型。可选值: - -- `'rgb-shift'`: RGB 通道偏移 - 红绿蓝颜色通道分离偏移 -- `'digital-distortion'`: 数字扭曲 - 水平切片偏移 + 随机像素噪声 -- `'scan-lines'`: 扫描线故障 - 水平扫描线和亮线效果 -- `'data-corruption'`: 数据损坏 - 垂直条纹 + 块状损坏 - -##${prefix} intensity(number) = 0.5 -故障强度。取值范围:0.0-1.0。 - -**使用示例:** - -```typescript -animationDisappear: { - stage: { - type: 'glitch', - duration: 1000, - easing: 'linear', - options: { - effectType: 'rgb-shift', - intensity: 0.5 - } - } -} -``` - -#${prefix} type = 'pixelation' - -像素化效果 -当 `type` 为 `'pixelation'` 时的配置参数: - -##${prefix} maxPixelSize(number) = 20 -最大像素化强度。取值范围:1-50。 - -##${prefix} method(string) = 'out' -像素化方向。可选值: - -- `'out'`: 退场效果 - 像素化强度从 1 逐渐增加到最大值 -- `'in'`: 入场效果 - 像素化强度从最大值逐渐减小到 1 - -**使用示例:** - -```typescript -animationDisappear: { - stage: { - type: 'pixelation', - duration: 2000, - easing: 'linear', - options: { - maxPixelSize: 25, - method: 'out' - } - } -} -``` - -#${prefix} type = 'grayscale' - -颜色效果 -当 `type` 为 `'grayscale'` 时的配置参数: - -##${prefix} effectType(string) = 'grayscale' -颜色效果类型。可选值: - -- `'grayscale'`: 灰度效果 - 使用标准亮度公式转为黑白 -- `'sepia'`: 褐色调效果 - 怀旧风格的褐色滤镜 - -##${prefix} strength(number) = 1.0 -效果强度。取值范围:0.0-1.0。 - -##${prefix} useWebGL(boolean) = true -是否使用 WebGL 实现。 - -**使用示例:** - -```typescript -animationDisappear: { - stage: { - type: 'grayscale', - duration: 2000, - easing: 'linear', - options: { - effectType: 'grayscale', - strength: 1.0, - useWebGL: true - } - } -} -``` - -#${prefix} type = 'dissolve' - -溶解效果 -当 `type` 为 `'dissolve'` 时的配置参数: - -##${prefix} dissolveType(string) = 'outward' -溶解方向。可选值: - -- `'outward'`: 从中心向外溶解 -- `'inward'`: 从外向中心溶解 -- `'radial'`: 径向溶解 -- `'leftToRight'`: 从左到右溶解 -- `'rightToLeft'`: 从右到左溶解 -- `'topToBottom'`: 从上到下溶解 -- `'bottomToTop'`: 从下到上溶解 - -##${prefix} noiseScale(number) = 8 -噪声比例。取值范围:1-20。 - -##${prefix} fadeEdge(boolean) = true -是否边缘渐变。 - -**使用示例:** - -```typescript -animationDisappear: { - stage: { - type: 'dissolve', - duration: 2000, - easing: 'linear', - options: { - dissolveType: 'radial', - noiseScale: 10, - fadeEdge: true, - } - } -} -``` diff --git a/docs/assets/option/zh/component/mark-point.md b/docs/assets/option/zh/component/mark-point.md index 4a6cebd002..463fff8b23 100644 --- a/docs/assets/option/zh/component/mark-point.md +++ b/docs/assets/option/zh/component/mark-point.md @@ -220,72 +220,40 @@ 自 1.8.7 版本开始, 是否自动调整 item content 使其展示在 marker 可见区域内。 -#### symbol(Object) - -标注内容类型为 symbol 时, 状态和样式配置。 - -{{ use: component-marker-state( - prefix = '####', - graphicType = 'symbol' -) }} - -##### style(Object) - -标注内容类型为 symbol 时,symbol 的样式。 -{{ use: component-marker-style-callback( - description = 'symbol样式' -) }} - -{{ use: graphic-symbol( - prefix = '#####' -) }} - -#### image(Object) - -标注内容类型为 image 时, 状态和样式配置。 +#### text(Object) -{{ use: component-marker-state( +{{ use: component-marker-label( prefix = '####', - graphicType = 'image' + noConfine = true, + noMarkerRef = true, + noAutoRotate = true ) }} -##### style(Object) +#### style(Object) -标注内容类型为 image 时,image 的样式。 {{ use: component-marker-style-callback( - description = 'image样式' + description = 'image | text | richText | symbol style' ) }} {{ use: graphic-image( - prefix = '#####' + prefix = '####' ) }} -#### text(Object) - -{{ use: component-marker-label( - prefix = '####', - noConfine = true +{{ use: graphic-text( + prefix = '####' ) }} -#### richText(Object) - -标注内容类型为 richText 时, 状态和样式配置。 - -{{ use: component-marker-style-callback( - description = 'richText样式' +{{ use: graphic-rich-text( + prefix = '####' ) }} -{{ use: component-marker-state( - prefix = '####', - graphicType = 'richText' +{{ use: graphic-symbol( + prefix = '####' ) }} -##### style(Object) - -标注内容类型为 richText 时,richText 的样式。 - -{{ use: graphic-rich-text( - prefix = '#####' +{{ use: component-marker-state( + prefix = '###', + graphicType = 'all' ) }} {{ use: component-marker-animation( diff --git a/docs/assets/option/zh/component/marker-common/marker-label.md b/docs/assets/option/zh/component/marker-common/marker-label.md index 1a0534f38a..24cc77a424 100644 --- a/docs/assets/option/zh/component/marker-common/marker-label.md +++ b/docs/assets/option/zh/component/marker-common/marker-label.md @@ -3,10 +3,11 @@ #${prefix} visible(boolean) 标签是否可见。 - +{{ if: !${noAutoRotate} }} #${prefix} autoRotate(boolean) 标签整体 - 是否自动旋转。 +{{ /if }} {{ if: !${noMarkerRef} }} {{ use: component-marker-ref( diff --git a/docs/assets/option/zh/component/marker-common/marker-state.md b/docs/assets/option/zh/component/marker-common/marker-state.md index cb03b14539..465cb31e1d 100644 --- a/docs/assets/option/zh/component/marker-common/marker-state.md +++ b/docs/assets/option/zh/component/marker-common/marker-state.md @@ -3,6 +3,7 @@ #${prefix} state(Object) 自`1.11.0`版本支持,标注组件的交互状态配置。 标注线目前有如下4种状态,您可以配置这几种交互状态触发后,线的样式。 + - `'hover'`:hover态 - `'hover_reverse'`:非hover状态 - `'selected'`:选中状态 @@ -11,209 +12,251 @@ ##${prefix} hover(Object) hover态。 -###${prefix} style(Object|Array) - -{{ use: component-marker-style-callback( - description = '标注样式hover状态支持回调' -) }} - {{ if: ${graphicType} === 'line' }} {{ use: graphic-line( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'polygon' }} {{ use: graphic-polygon( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'symbol' }} {{ use: graphic-symbol( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'image' }} {{ use: graphic-image( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'richText' }} {{ use: graphic-rich-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'rect' }} {{ use: graphic-rect( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'text' }} {{ use: graphic-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} +{{ if: ${graphicType} === 'all' }} +{{ use: graphic-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-rich-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-image( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-symbol( + prefix = '##' + ${prefix} +) }} +{{ /if }} ##${prefix} hover_reverse(Object) 非 hover态。 -###${prefix} style(Object|Array) - {{ use: component-marker-style-callback( description = '标注样式非hover状态支持回调' ) }} {{ if: ${graphicType} === 'line' }} {{ use: graphic-line( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'polygon' }} {{ use: graphic-polygon( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'symbol' }} {{ use: graphic-symbol( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'image' }} {{ use: graphic-image( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'richText' }} {{ use: graphic-rich-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'rect' }} {{ use: graphic-rect( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'text' }} {{ use: graphic-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} - +{{ if: ${graphicType} === 'all' }} +{{ use: graphic-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-rich-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-image( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-symbol( + prefix = '##' + ${prefix} +) }} +{{ /if }} ##${prefix} selected(Object) 选中态。 -###${prefix} style(Object|Array) - {{ use: component-marker-style-callback( description = '标注样式选中状态支持回调' ) }} {{ if: ${graphicType} === 'line' }} {{ use: graphic-line( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'polygon' }} {{ use: graphic-polygon( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'symbol' }} {{ use: graphic-symbol( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'image' }} {{ use: graphic-image( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'richText' }} {{ use: graphic-rich-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'rect' }} {{ use: graphic-rect( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'text' }} {{ use: graphic-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} +{{ if: ${graphicType} === 'all' }} +{{ use: graphic-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-rich-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-image( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-symbol( + prefix = '##' + ${prefix} +) }} +{{ /if }} ##${prefix} selected_reverse(Object) 非选中态。 -###${prefix} style(Object|Array) - {{ use: component-marker-style-callback( description = '标注样式非选中状态支持回调' ) }} {{ if: ${graphicType} === 'line' }} {{ use: graphic-line( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'polygon' }} {{ use: graphic-polygon( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'symbol' }} {{ use: graphic-symbol( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'image' }} {{ use: graphic-image( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'richText' }} {{ use: graphic-rich-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'rect' }} {{ use: graphic-rect( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} {{ if: ${graphicType} === 'text' }} {{ use: graphic-text( - prefix = '###' + ${prefix} + prefix = '##' + ${prefix} ) }} {{ /if }} - +{{ if: ${graphicType} === 'all' }} +{{ use: graphic-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-rich-text( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-image( + prefix = '##' + ${prefix} +) }} +{{ use: graphic-symbol( + prefix = '##' + ${prefix} +) }} +{{ /if }} diff --git a/docs/public/vchart/preview/disappear-animation-2.0.11.gif b/docs/public/vchart/preview/disappear-animation-2.0.11.gif new file mode 100644 index 0000000000..2515a9ee59 Binary files /dev/null and b/docs/public/vchart/preview/disappear-animation-2.0.11.gif differ diff --git a/docs/public/vchart/preview/disappear-animation-gaussian-blur-2.0.11.gif b/docs/public/vchart/preview/disappear-animation-gaussian-blur-2.0.11.gif new file mode 100644 index 0000000000..4240c92c18 Binary files /dev/null and b/docs/public/vchart/preview/disappear-animation-gaussian-blur-2.0.11.gif differ diff --git a/docs/public/vchart/preview/disappear-animation-wipe-2.0.11.gif b/docs/public/vchart/preview/disappear-animation-wipe-2.0.11.gif new file mode 100644 index 0000000000..328307eaf2 Binary files /dev/null and b/docs/public/vchart/preview/disappear-animation-wipe-2.0.11.gif differ diff --git a/packages/harmony_vchart/library/CHANGELOG.md b/packages/harmony_vchart/library/CHANGELOG.md index c34f76d140..8ac86c2719 100644 --- a/packages/harmony_vchart/library/CHANGELOG.md +++ b/packages/harmony_vchart/library/CHANGELOG.md @@ -1,7 +1,27 @@ -# v2.0.11 - -2025-12-11 - +# v2.0.12 + +2025-12-25 + +**🆕 新增功能** + +- **@visactor/vchart**: 极坐标轴(CircleAxis)支持 `autoLabelMaxWidth` 配置 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4357 +- **@visactor/vchart**: 新增图表消失(Disappear)状态支持 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4341 +- **@visactor/vchart**: 优化热力图(Heatmap)形状渲染逻辑 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4377 +- **@visactor/vchart**: 优化地图(Map)zoom交互,增加 `zoomRate` 配置 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4373 + +**🐛 问题修复** + +- **@visactor/vchart**: 修复坐标轴标题(Axes Title)的布局问题 by @xuefei1313 in https://github.com/VisActor/VChart/pull/4371 + +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.11...v2.0.12 + +[more detail about v2.0.12](https://github.com/VisActor/VChart/releases/tag/v2.0.12) + + +# v2.0.11 + +2025-12-11 + # v2.0.11 2025-12-11 @@ -21,22 +41,22 @@ **Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.10...v2.0.11 -[more detail about v2.0.11](https://github.com/VisActor/VChart/releases/tag/v2.0.11) - -[more detail about v2.0.11](https://github.com/VisActor/VChart/releases/tag/v2.0.11) - -# v2.0.10 - -2025-11-28 - - -**🆕 New Features** +[more detail about v2.0.11](https://github.com/VisActor/VChart/releases/tag/v2.0.11) + +[more detail about v2.0.11](https://github.com/VisActor/VChart/releases/tag/v2.0.11) + +# v2.0.10 + +2025-11-28 + + +**🆕 New Features** * @visactor/vchart: Enhance boxplot features by @xile611 in https://github.com/VisActor/VChart/pull/4323 - -**🐛 Bug Fixes** + +**🐛 Bug Fixes** * @visactor/vchart: Upgrade vrender dependency to fix rose chart issues by @xuefei1313 in https://github.com/VisActor/VChart/pull/4315 @@ -45,8 +65,8 @@ * @visactor/vchart: Fix font family setting issue by @xuefei1313 in https://github.com/VisActor/VChart/pull/4324 * @visactor/vchart: Fix issue with setDimensionIndex by @xuefei1313 in https://github.com/VisActor/VChart/pull/4291 - -**📖 Documentation** + +**📖 Documentation** * @visactor/vchart: Add candlestick chart guide by @xuefei1313 in https://github.com/VisActor/VChart/pull/4310 @@ -55,44 +75,44 @@ * @visactor/vchart: Add 3D registration content to guide by @xuefei1313 in https://github.com/VisActor/VChart/pull/4312 * @visactor/vchart: Fix documentation for common chart option labelLayout by @xuefei1313 in https://github.com/VisActor/VChart/pull/4316 -**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.9...v2.0.10 - -[more detail about v2.0.10](https://github.com/VisActor/VChart/releases/tag/v2.0.10) - -# v2.0.9 - -2025-11-18 - - -**🆕 New Features** +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.9...v2.0.10 + +[more detail about v2.0.10](https://github.com/VisActor/VChart/releases/tag/v2.0.10) + +# v2.0.9 + +2025-11-18 + + +**🆕 New Features** * @visactor/react-vchart: Add export for registerChartResizeZoomPlugin by @xuefei1313 in https://github.com/VisActor/VChart/pull/4286 * @visactor/vchart: Support effect animation by @purpose233 in https://github.com/VisActor/VChart/pull/4299 * @visactor/vchart: Enhance datazoom and fix bugs by @skie1997 in https://github.com/VisActor/VChart/pull/4065 - -**🐛 Bug Fixes** + +**🐛 Bug Fixes** * @visactor/vchart-extension: Fix the vchart-extension packaged artifacts contained an extra version by @xuefei1313 in https://github.com/VisActor/VChart/pull/4277 * @visactor/vchart: Fix markline auto range by @xuefei1313 in https://github.com/VisActor/VChart/pull/4290 - -**📖 Documentation** + +**📖 Documentation** * @visactor/vchart: Fix registerMorph error in example by @xuefei1313 in https://github.com/VisActor/VChart/pull/4285 * @visactor/vchart: Add candlestick demo by @xuefei1313 in https://github.com/VisActor/VChart/pull/4297 -**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.7...v2.0.9 - -[more detail about v2.0.9](https://github.com/VisActor/VChart/releases/tag/v2.0.9) - -# v2.0.7 - -2025-11-03 - +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.7...v2.0.9 + +[more detail about v2.0.9](https://github.com/VisActor/VChart/releases/tag/v2.0.9) + +# v2.0.7 + +2025-11-03 + 🆕 New Features @visactor/vchart: Support resize zoom chart plugin by @xuefei1313 in https://github.com/VisActor/VChart/pull/4241 @@ -112,16 +132,16 @@ - - -[more detail about v2.0.7](https://github.com/VisActor/VChart/releases/tag/v2.0.7) - -# v2.0.6 - -2025-10-14 - - -**What's Changed** + + +[more detail about v2.0.7](https://github.com/VisActor/VChart/releases/tag/v2.0.7) + +# v2.0.6 + +2025-10-14 + + +**What's Changed** * fix: fix the issue of legend pager by @xuefei1313 in https://github.com/VisActor/VChart/pull/4212 * Feat/support calc in formatter by @xuefei1313 in https://github.com/VisActor/VChart/pull/4211 @@ -132,43 +152,43 @@ * feat: change vrender dependencies by @xuefei1313 in https://github.com/VisActor/VChart/pull/4224 -**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.5...v2.0.6 - -[more detail about v2.0.6](https://github.com/VisActor/VChart/releases/tag/v2.0.6) - -# v2.0.5 - -2025-09-19 - - - -[more detail about v2.0.5](https://github.com/VisActor/VChart/releases/tag/v2.0.5) - -# v2.0.2 - -2025-07-28 - - -**🆕 New feature** +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.5...v2.0.6 + +[more detail about v2.0.6](https://github.com/VisActor/VChart/releases/tag/v2.0.6) + +# v2.0.5 + +2025-09-19 + + + +[more detail about v2.0.5](https://github.com/VisActor/VChart/releases/tag/v2.0.5) + +# v2.0.2 + +2025-07-28 + + +**🆕 New feature** - **@visactor/vchart**: add the afterClearRect hook of render -**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.1...v2.0.2 - -[more detail about v2.0.2](https://github.com/VisActor/VChart/releases/tag/v2.0.2) - -# v2.0.1 - -2025-07-24 - - -**🆕 New feature** +**Full Changelog**: https://github.com/VisActor/VChart/compare/v2.0.1...v2.0.2 + +[more detail about v2.0.2](https://github.com/VisActor/VChart/releases/tag/v2.0.2) + +# v2.0.1 + +2025-07-24 + + +**🆕 New feature** - **@visactor/vchart**: add config to avoid brush state update. close [#4035](https://github.com/VisActor/VChart/issues/4035) - **@visactor/vchart**: optimize datazoom animation effect - **@visactor/vchart**: add the afterClearScreen hook of render - -**🐛 Bug fix** + +**🐛 Bug fix** - **@visactor/vchart**: fix issue with 3d chart grid - **@visactor/vchart**: tickData of axis should update when `sampling` is changed, fix [#4059](https://github.com/VisActor/VChart/issues/4059) @@ -179,10 +199,10 @@ - **@visactor/vchart**: fix tooltip throw error when some tooltip processor is undefined, fix [#4044](https://github.com/VisActor/VChart/issues/4044) - **@visactor/vchart**: fix `textAlign` not works in tooltip.style.titleLabel, fix [#4043](https://github.com/VisActor/VChart/issues/4043) - - -[more detail about v2.0.1](https://github.com/VisActor/VChart/releases/tag/v2.0.1) - + + +[more detail about v2.0.1](https://github.com/VisActor/VChart/releases/tag/v2.0.1) + # v1.13.11 2025-05-29 @@ -1099,3 +1119,4 @@ # 1.11.0-alpha.1 - VChart支持HarmonyOS的StageTS架构 + diff --git a/packages/vchart/__tests__/runtime/browser/test-page/area.ts b/packages/vchart/__tests__/runtime/browser/test-page/area.ts index 28a14ab2ab..bf70c30dba 100644 --- a/packages/vchart/__tests__/runtime/browser/test-page/area.ts +++ b/packages/vchart/__tests__/runtime/browser/test-page/area.ts @@ -1,5 +1,4 @@ import { isMobile } from 'react-device-detect'; -import type { IAreaChartSpec } from '../../../../src/index'; // eslint-disable-next-line no-duplicate-imports import { default as VChart, @@ -9,162 +8,104 @@ import { registerStateTransition, vglobal } from '../../../../src/index'; -import { AnimateExecutor, AStageAnimate } from '@visactor/vrender-animate'; registerAnimate(); registerCustomAnimate(); registerStateTransition(); -class TestStageAnimate extends AStageAnimate { - // 原版代码 - protected afterStageRender(stage: any, canvas: HTMLCanvasElement): HTMLCanvasElement | void | null | false { - const c = vglobal.createCanvas({ - width: canvas.width, - height: canvas.height, - dpr: vglobal.devicePixelRatio - }); - const ctx = c.getContext('2d'); - if (!ctx) { - return false; - } - ctx.clearRect(0, 0, canvas.width, canvas.height); - ctx.drawImage(canvas, 0, 0); - ctx.fillStyle = `rgba(${Math.floor(Math.random() * 255)}, ${Math.floor(Math.random() * 255)}, ${Math.floor( - Math.random() * 255 - )}, 0.2)`; - ctx.fillRect(0, 0, canvas.width, canvas.height); - return c; +function wipeAnimate(canvas, ratio) { + // 创建临时画布 + const c = vglobal.createCanvas({ + width: canvas.width, + height: canvas.height, + dpr: vglobal.devicePixelRatio + }); + const ctx = c.getContext('2d'); + if (!ctx) { + return false; } -} -AnimateExecutor.registerBuiltInAnimate('stageTest', TestStageAnimate); + // 将原画布内容绘制到临时画布 + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(canvas, 0, 0); + + // 获取临时画布的图像数据 + const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + const data = imageData.data; + + // 根据ratio计算擦除位置(从左到右) + const wipePosition = Math.floor(canvas.width * ratio); + + // 设置渐变区域宽度,可根据需要调整 + const gradientWidth = Math.min(canvas.width * 0.3, 50); + + // 遍历每个像素点 + for (let y = 0; y < canvas.height; y++) { + for (let x = 0; x < canvas.width; x++) { + // 计算当前像素在数据数组中的索引 + const index = (y * canvas.width + x) * 4; + + // 计算当前像素的原始透明度 + const originalAlpha = data[index + 3]; + + // 计算当前像素与擦除位置的距离 + const distance = x - wipePosition; + + // 根据距离计算透明度 + let newAlpha; + if (distance <= 0) { + // 擦除位置左侧:完全透明 + newAlpha = 0; + } else if (distance <= gradientWidth) { + // 渐变区域内:透明度从0到原始透明度渐变 + const gradientRatio = distance / gradientWidth; + newAlpha = Math.floor(originalAlpha * gradientRatio); + } else { + // 擦除位置右侧:保持原始透明度 + newAlpha = originalAlpha; + } -let dataArray = [ - { type: 'Nail polish', country: 'Africa', value: 4229 }, - { type: 'Nail polish', country: 'EU', value: 4376 }, - { type: 'Nail polish', country: 'China', value: 3054 }, - { type: 'Nail polish', country: 'USA', value: 12814 }, - { type: 'Eyebrow pencil', country: 'Africa', value: 3932 }, - { type: 'Eyebrow pencil', country: 'EU', value: 3987 }, - { type: 'Eyebrow pencil', country: 'China', value: 5067 }, - { type: 'Eyebrow pencil', country: 'USA', value: 13012 }, - { type: 'Rouge', country: 'Africa', value: 5221 }, - { type: 'Rouge', country: 'EU', value: 3574 }, - { type: 'Rouge', country: 'China', value: 7004 }, - { type: 'Rouge', country: 'USA', value: 11624 }, - { type: 'Lipstick', country: 'Africa', value: 9256 }, - { type: 'Lipstick', country: 'EU', value: 4376 }, - { type: 'Lipstick', country: 'China', value: 9054 }, - { type: 'Lipstick', country: 'USA', value: 8814 }, - { type: 'Eyeshadows', country: 'Africa', value: 3308 }, - { type: 'Eyeshadows', country: 'EU', value: 4572 }, - { type: 'Eyeshadows', country: 'China', value: 12043 }, - { type: 'Eyeshadows', country: 'USA', value: 12998 }, - { type: 'Eyeliner', country: 'Africa', value: 5432 }, - { type: 'Eyeliner', country: 'EU', value: 3417 }, - { type: 'Eyeliner', country: 'China', value: 15067 }, - { type: 'Eyeliner', country: 'USA', value: 12321 }, - { type: 'Foundation', country: 'Africa', value: 13701 }, - { type: 'Foundation', country: 'EU', value: 5231 }, - { type: 'Foundation', country: 'China', value: 10119 }, - { type: 'Foundation', country: 'USA', value: 10342 }, - { type: 'Lip gloss', country: 'Africa', value: 4008 }, - { type: 'Lip gloss', country: 'EU', value: 4572 }, - { type: 'Lip gloss', country: 'China', value: 12043 }, - { type: 'Lip gloss', country: 'USA', value: 22998 }, - { type: 'Mascara', country: 'Africa', value: 18712 }, - { type: 'Mascara', country: 'EU', value: 6134 }, - { type: 'Mascara', country: 'China', value: 10419 }, - { type: 'Mascara', country: 'USA', value: 11261 } -]; + // 设置新的透明度 + data[index + 3] = newAlpha; + } + } -const direction: string = 'vertical'; + // 将处理后的图像数据绘制回临时画布 + ctx.putImageData(imageData, 0, 0); -let spec = { + return c; +} + +const spec = { type: 'bar', - data: { - id: 'data0', - values: dataArray - }, - title: { - visible: true, - text: 'Stacked area chart of cosmetic products sales' - }, - direction, - useSequentialAnimation: true, - // stack: true, - xField: direction === 'horizontal' ? 'value' : 'type', - yField: direction === 'horizontal' ? 'type' : 'value', - seriesField: 'country', - legends: [{ visible: true, position: 'middle' as const, orient: 'bottom' as const }], - crosshair: { - followTooltip: true, - xField: { visible: true, label: { visible: true } }, - yField: { visible: true, label: { visible: true } } - }, - // animationAppear: { - // duration: 300 - // }, - animationAppear: { - stage: { - type: 'stageTest', - duration: 1000, - easing: 'linear' - } - }, - animationUpdate: { - duration: 300 - }, - animationEnter: { - duration: 300 - }, - animationExit: { - duration: 2000, - type: 'fadeOut' - }, - animationNormal: { - point: [ - { - loop: true, - startTime: 100, - oneByOne: 100, - priority: 1, - timeSlices: [ - { - delay: 1000, - effects: { - channel: { - fillOpacity: { to: 0.5 } - }, - easing: 'linear' - }, - duration: 500 - }, - { - effects: { - channel: { - fillOpacity: { to: 1 } - }, - easing: 'linear' - }, - duration: 500 - } - ] - } - ] - }, - point: { - state: { - hover: { - fill: 'red' - } - }, - style: { - size: 80 + data: [ + { + id: 'barData', + values: [ + { month: 'Monday', sales: 22 }, + { month: 'Tuesday', sales: 13 }, + { month: 'Wednesday', sales: 25 }, + { month: 'Thursday', sales: 29 }, + { month: 'Friday', sales: 38 } + ] } + ], + xField: 'month', + yField: 'sales', + animationDisappear: { + callBack: (stage, canvas, ratio) => wipeAnimate(canvas, ratio), + easing: 'linear', + duration: 2000 } }; const run = () => { + const container = document.getElementById('chart'); + if (container) { + container.style.width = '640px'; + container.style.height = '480px'; + container.style.border = '1px solid #eee'; + } + registerMediaQuery(); // VChart.ThemeManager.setCurrentTheme('dark'); const cs = new VChart(spec, { @@ -182,194 +123,17 @@ const run = () => { }); const button = document.createElement('button'); - button.innerHTML = 'click'; + button.innerHTML = '退场动画'; button.addEventListener('click', () => { - dataArray = dataArray.map(d => ({ ...d, value: 100000 * Math.random() })); - cs.updateData('data0', dataArray); + cs.runDisappearAnimation(); }); - document.body.appendChild(button); + // document.body.appendChild(button); - const button2 = document.createElement('button'); - button2.innerHTML = 'add&remove'; - button2.addEventListener('click', () => { - const name = Math.random().toString(); - dataArray = dataArray.map(d => ({ - ...d, - value: 100000 * Math.random(), - country: ['EU', 'China', 'USA'].includes(d.country) ? d.country : name - })); - cs.updateData('data0', dataArray); - }); - document.body.appendChild(button2); - - function addData() { - const name = Math.random().toString(); - const newData = dataArray - .filter(d => d.country === 'EU') - .map(d => ({ - ...d, - value: 100000 * Math.random(), - country: name - })); - - dataArray = [...dataArray, ...newData]; - } - - function removeData() { - dataArray = dataArray.filter(d => ['EU', 'China', 'USA'].includes(d.country)); - } - - const button3 = document.createElement('button'); - button3.innerHTML = 'stack<->group'; - button3.addEventListener('click', () => { - const nextSpec: any = { ...spec }; - const fieldKey = direction === 'horizontal' ? 'yField' : 'xField'; - if (typeof nextSpec[fieldKey] === 'string') { - (nextSpec as any)[fieldKey] = ['type', 'country']; - } else { - (nextSpec as any)[fieldKey] = 'type'; - } - spec = nextSpec; - cs.updateSpec(spec as any); - }); - document.body.appendChild(button3); - - const button4 = document.createElement('button'); - button4.innerHTML = 'stack<->group add'; - button4.addEventListener('click', () => { - const nextSpec: any = { ...spec }; - const fieldKey = direction === 'horizontal' ? 'yField' : 'xField'; - if (typeof nextSpec[fieldKey] === 'string') { - (nextSpec as any)[fieldKey] = ['type', 'country']; - } else { - (nextSpec as any)[fieldKey] = 'type'; - } - addData(); - nextSpec.data = { - id: 'data0', - values: dataArray - }; - spec = nextSpec; - cs.updateSpec(spec as any); - }); - document.body.appendChild(button4); - - const button5 = document.createElement('button'); - button5.innerHTML = 'stack<->group remove'; - button5.addEventListener('click', () => { - const nextSpec: any = { ...spec }; - const fieldKey = direction === 'horizontal' ? 'yField' : 'xField'; - if (typeof nextSpec[fieldKey] === 'string') { - (nextSpec as any)[fieldKey] = ['type', 'country']; - } else { - (nextSpec as any)[fieldKey] = 'type'; - } - removeData(); - nextSpec.data = { - id: 'data0', - values: dataArray - }; - spec = nextSpec; - cs.updateSpec(spec as any); - }); - document.body.appendChild(button5); - - const button6 = document.createElement('button'); - button6.innerHTML = 'direction'; - button6.addEventListener('click', () => { - const nextSpec: any = { ...spec }; - nextSpec.direction = nextSpec.direction === 'horizontal' ? 'vertical' : 'horizontal'; - [nextSpec.xField, nextSpec.yField] = [nextSpec.yField, nextSpec.xField]; - spec = nextSpec; - cs.updateSpec(spec as any); - }); - document.body.appendChild(button6); - - // 添加退场动画按钮 - const button7 = document.createElement('button'); - button7.innerHTML = '触发退场动画'; - button7.addEventListener('click', () => { - console.log('触发退场动画...'); - - // 方法1: 通过移除数据来触发退场动画 - // 先保存原始数据 - const originalData = [...dataArray]; - - // 清空数据,这会触发所有元素的退场动画 - cs.updateData('data0', []); - - // 3秒后恢复数据,重新显示图表 - setTimeout(() => { - console.log('恢复数据,重新显示图表...'); - cs.updateData('data0', originalData); - }, 3000); - }); - document.body.appendChild(button7); - - // 添加第三种退场动画按钮 - 通过更新spec来触发 - const button9 = document.createElement('button'); - button9.innerHTML = 'Spec退场动画'; - button9.addEventListener('click', () => { - console.log('通过更新spec触发退场动画...'); - - // 保存原始spec - const originalSpec = { ...spec }; - - // 创建一个空的spec来触发退场动画 - const emptySpec = { - ...spec, - data: { - id: 'data0', - values: [] // 空数据 - } - }; - - // 更新spec,这会触发退场动画 - cs.updateSpec(emptySpec as any); - - // 3秒后恢复原始spec - setTimeout(() => { - console.log('恢复原始spec...'); - cs.updateSpec(originalSpec as any); - }, 3000); - }); - document.body.appendChild(button9); - - // 添加自定义退场动画按钮 - const button10 = document.createElement('button'); - button10.innerHTML = '自定义退场动画'; - button10.addEventListener('click', () => { - console.log('触发自定义退场动画...'); - - // 保存原始spec - const originalSpec = { ...spec }; - - // 创建带有自定义退场动画的spec - const customExitSpec = { - ...spec, - animationExit: { - duration: 1000, // 1秒退场动画 - type: 'fadeOut', // 淡出效果 - easing: 'easeInOut' // 缓动函数 - }, - data: { - id: 'data0', - values: [] // 空数据触发退场 - } - }; - - // 更新spec,触发自定义退场动画 - cs.updateSpec(customExitSpec as any); - - // 2秒后恢复原始spec - setTimeout(() => { - console.log('恢复原始spec...'); - cs.updateSpec(originalSpec as any); - }, 2000); - }); - document.body.appendChild(button10); + // setInterval(() => { + // cs.runDisappearAnimation(); + // }, 2000); - window['vchart'] = cs; + (window as any)['vchart'] = cs; console.log(cs); }; run(); diff --git a/packages/vchart/src/animation/callback-disappear.ts b/packages/vchart/src/animation/callback-disappear.ts index 94b61eb26d..22205537c7 100644 --- a/packages/vchart/src/animation/callback-disappear.ts +++ b/packages/vchart/src/animation/callback-disappear.ts @@ -29,6 +29,6 @@ export class CallbackDisappearAnimate extends AStageAnimate { } protected afterStageRender(stage: any, canvas: HTMLCanvasElement): void { - this.params?.callBack?.(stage, canvas, this.currentAnimationRatio, this.animationTime); + return this.params?.callBack?.(stage, canvas, this.currentAnimationRatio, this.animationTime); } } diff --git a/packages/vchart/src/animation/interface.ts b/packages/vchart/src/animation/interface.ts index cf900fdb59..ef6eeb08f1 100644 --- a/packages/vchart/src/animation/interface.ts +++ b/packages/vchart/src/animation/interface.ts @@ -162,7 +162,7 @@ export type IAnimationConfig = IAnimationTimeline | IAnimationTypeConfig; export type IStageAnimationCallback = (stage: IStage, canvas: HTMLCanvasElement, ratio: number, time: number) => void; export interface MarkAnimationSpec { - disappear?: IStateAnimationConfig & { + disappear?: IAnimationConfig & { callBack?: IStageAnimationCallback | AStageAnimate; }; appear?: IAnimationConfig | IAnimationConfig[]; diff --git a/packages/vchart/src/component/marker/mark-point/base-mark-point.ts b/packages/vchart/src/component/marker/mark-point/base-mark-point.ts index b7853758a2..6414f768cc 100644 --- a/packages/vchart/src/component/marker/mark-point/base-mark-point.ts +++ b/packages/vchart/src/component/marker/mark-point/base-mark-point.ts @@ -16,7 +16,7 @@ import { transformToGraphic } from '../../../util/style'; import { BaseMarker } from '../base-marker'; import { LayoutZIndex } from '../../../constant/layout'; import type { IGroup } from '@visactor/vrender-core'; -import type { IMarkerLabelSpec } from '../interface'; +import type { IMarkerLabelSpec, IMarkerLabelWithoutRefSpec } from '../interface'; export abstract class BaseMarkPoint extends BaseMarker implements IMarkPoint { static specKey = 'markPoint'; @@ -72,7 +72,10 @@ export abstract class BaseMarkPoint extends BaseMarker implement dy: 0 }; itemContentStyle = transformLabelAttributes( - merge(defaultStyle, label ?? textStyle ?? (style as IMarkerLabelSpec)), + { + ...label, + style: merge(defaultStyle, label?.textStyle ?? textStyle ?? (style as Pick)) + }, this._markerData, this._markAttributeContext ); diff --git a/packages/vchart/src/series/heatmap/heatmap.ts b/packages/vchart/src/series/heatmap/heatmap.ts index 3ad2f3d783..7467526fb9 100644 --- a/packages/vchart/src/series/heatmap/heatmap.ts +++ b/packages/vchart/src/series/heatmap/heatmap.ts @@ -73,7 +73,7 @@ export class HeatmapSeries ex return; } this.setMarkStyle(textMark, { - fill: this.getColorAttribute(), + fill: this._spec.cell?.style?.fill ?? this.getColorAttribute(), text: (datum: Datum) => { return datum[this.getMeasureField()[0]]; } diff --git a/packages/vchart/src/theme/builtin/common/series/heatmap.ts b/packages/vchart/src/theme/builtin/common/series/heatmap.ts index 6697536abf..460e324640 100644 --- a/packages/vchart/src/theme/builtin/common/series/heatmap.ts +++ b/packages/vchart/src/theme/builtin/common/series/heatmap.ts @@ -9,5 +9,10 @@ export const heatmap: IHeatmapSeriesTheme = { }, cellBackground: { visible: false + }, + label: { + style: { + lineWidth: 2 + } } };