From ef40f8ffb54086fe9576abbdeb4f5ee0d5681933 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 20 Nov 2024 21:08:06 +0800 Subject: [PATCH 01/51] feat: add switch component --- ...eat-switch-component_2024-11-20-13-07.json | 10 + .../__tests__/browser/examples/switch.ts | 75 +++++++ .../__tests__/browser/main.ts | 4 + packages/vrender-components/src/index.ts | 1 + .../vrender-components/src/switch/index.ts | 2 + .../vrender-components/src/switch/register.ts | 8 + .../vrender-components/src/switch/switch.ts | 187 ++++++++++++++++++ .../vrender-components/src/switch/type.ts | 35 ++++ 8 files changed, 322 insertions(+) create mode 100644 common/changes/@visactor/vrender-components/feat-switch-component_2024-11-20-13-07.json create mode 100644 packages/vrender-components/__tests__/browser/examples/switch.ts create mode 100644 packages/vrender-components/src/switch/index.ts create mode 100644 packages/vrender-components/src/switch/register.ts create mode 100644 packages/vrender-components/src/switch/switch.ts create mode 100644 packages/vrender-components/src/switch/type.ts diff --git a/common/changes/@visactor/vrender-components/feat-switch-component_2024-11-20-13-07.json b/common/changes/@visactor/vrender-components/feat-switch-component_2024-11-20-13-07.json new file mode 100644 index 000000000..cb6498c4b --- /dev/null +++ b/common/changes/@visactor/vrender-components/feat-switch-component_2024-11-20-13-07.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-components", + "comment": "feat: add switch component", + "type": "none" + } + ], + "packageName": "@visactor/vrender-components" +} \ No newline at end of file diff --git a/packages/vrender-components/__tests__/browser/examples/switch.ts b/packages/vrender-components/__tests__/browser/examples/switch.ts new file mode 100644 index 000000000..58340b485 --- /dev/null +++ b/packages/vrender-components/__tests__/browser/examples/switch.ts @@ -0,0 +1,75 @@ +import '@visactor/vrender'; +import { IPointLike } from '@visactor/vutils'; +import render from '../../util/render'; +import { Switch, SwitchAttributes } from '../../../src'; + +export function run() { + const switchs: Switch[] = []; + switchs.push( + new Switch({ + x: 100, + y: 100 + }) + ); + + switchs.push( + new Switch({ + x: 200, + y: 100, + checked: true + }) + ); + + switchs.push( + new Switch({ + x: 300, + y: 100, + checked: true, + box: { + checkedFill: 'red', + uncheckedFill: 'blue' + } + } as SwitchAttributes) + ); + + switchs.push( + new Switch({ + x: 100, + y: 200, + text: { + checkedText: '开', + uncheckedText: '关', + fill: '#FFF', + fontSize: 12 + } + } as SwitchAttributes) + ); + + switchs.push( + new Switch({ + x: 200, + y: 200, + text: { + checkedText: 'enable', + uncheckedText: 'disableaaaaa', + fill: '#FFF', + fontSize: 12 + } + } as SwitchAttributes) + ); + + switchs.push( + new Switch({ + x: 350, + y: 200, + text: { + checkedText: 'enableaaaaa', + uncheckedText: 'disable', + fill: '#FFF', + fontSize: 12 + } + } as SwitchAttributes) + ); + + const stage = render(switchs, 'main'); +} diff --git a/packages/vrender-components/__tests__/browser/main.ts b/packages/vrender-components/__tests__/browser/main.ts index 595d01510..c5e0f1efb 100644 --- a/packages/vrender-components/__tests__/browser/main.ts +++ b/packages/vrender-components/__tests__/browser/main.ts @@ -285,6 +285,10 @@ const specs = [ { path: 'timeline', name: 'timeline' + }, + { + path: 'switch', + name: 'switch' } ]; diff --git a/packages/vrender-components/src/index.ts b/packages/vrender-components/src/index.ts index 7e3f5da76..0452c268c 100644 --- a/packages/vrender-components/src/index.ts +++ b/packages/vrender-components/src/index.ts @@ -29,3 +29,4 @@ export * from './checkbox'; export * from './radio'; export * from './empty-tip'; export * from './util'; +export * from './switch'; diff --git a/packages/vrender-components/src/switch/index.ts b/packages/vrender-components/src/switch/index.ts new file mode 100644 index 000000000..f8d5ccad0 --- /dev/null +++ b/packages/vrender-components/src/switch/index.ts @@ -0,0 +1,2 @@ +export * from './switch'; +export * from './type'; diff --git a/packages/vrender-components/src/switch/register.ts b/packages/vrender-components/src/switch/register.ts new file mode 100644 index 000000000..66d617601 --- /dev/null +++ b/packages/vrender-components/src/switch/register.ts @@ -0,0 +1,8 @@ +import { registerGroup, registerCircle, registerRect, registerText } from '@visactor/vrender-kits'; + +export function loadSwitchComponent() { + registerGroup(); + registerRect(); + registerText(); + registerCircle(); +} diff --git a/packages/vrender-components/src/switch/switch.ts b/packages/vrender-components/src/switch/switch.ts new file mode 100644 index 000000000..bb17a76d6 --- /dev/null +++ b/packages/vrender-components/src/switch/switch.ts @@ -0,0 +1,187 @@ +import { merge } from '@visactor/vutils'; +import { AbstractComponent } from '../core/base'; +import type { SwitchAttributes } from './type'; +import type { ICircle } from '@visactor/vrender-core'; +import { Circle, Rect, Text } from '@visactor/vrender-core'; +import type { ComponentOptions } from '../interface'; +import { loadSwitchComponent } from './register'; +import { measureTextSize } from '../util'; + +loadSwitchComponent(); +export class Switch extends AbstractComponent> { + static defaultAttributes: Partial = { + interactive: true, + disabled: false, + checked: false, + cursor: 'pointer', + disableCursor: 'not-allowed', + circle: { + radius: 8, + fill: '#FFF', + pickable: false + }, + box: { + width: 40, + height: 24, + cornerRadius: 12, + uncheckedFill: 'rgb(201,205,212)', + checkedFill: '#165DFF', + disableUncheckedFill: 'rgb(242,243,245)', + disableCheckedFill: 'rgb(148,191,255)', + pickable: false + }, + text: { + textAlign: 'left', + textBaseline: 'top', + pickable: false + }, + spaceBetweenTextAndCircle: 6 + }; + _box: Rect; + _circle: ICircle; + _text: Text; + + name: 'switch'; + + constructor(attributes: SwitchAttributes, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, Switch.defaultAttributes, attributes)); + this.renderGroup(); + + this.onBeforeAttributeUpdate = (val: any, attributes: any, key: null | string | string[]) => { + if ('interactive' in val) { + this.setAttribute('pickable', val.interactive); + } + if ('disabled' in val) { + this.setAttribute('cursor', val.disable ? this.attribute.disableCursor : this.attribute.cursor); + } + return undefined; + }; + + this.addEventListener('pointerup', this._handlePointerUp); + } + + render() { + this.removeAllChild(true); + + this.renderBox(); + this.renderCircle(); + this.renderText(); + this.layout(); + } + + renderBox() { + this._box = new Rect(merge({}, this.attribute.box)); + if (this.attribute.disabled && this.attribute.checked) { + this._box.setAttributes({ + fill: this.attribute.box.disableCheckedFill + }); + } else if (this.attribute.disabled && !this.attribute.checked) { + this._box.setAttributes({ + fill: this.attribute.box.disableUncheckedFill + }); + } else if (this.attribute.checked) { + this._box.setAttributes({ + fill: this.attribute.box.checkedFill + }); + } else { + this._box.setAttributes({ + fill: this.attribute.box.uncheckedFill + }); + } + this.appendChild(this._box); + } + + renderCircle() { + this._circle = new Circle(merge({}, this.attribute.circle)); + this.appendChild(this._circle); + } + + renderText() { + this._text = new Text(merge({}, this.attribute.text ?? {})); + if (this.attribute.checked && this.attribute.text?.checkedText) { + this._text.setAttributes({ + text: this.attribute.text.checkedText + }); + } else if (this.attribute.text?.uncheckedText) { + this._text.setAttributes({ + text: this.attribute.text.uncheckedText + }); + } + this.appendChild(this._text); + } + + renderGroup() { + if (!this.attribute.interactive) { + this.setAttribute('pickable', false); + } + if (this.attribute.disabled) { + this.setAttribute('cursor', this.attribute.disableCursor); + } + } + + layout() { + const space = this.attribute.spaceBetweenTextAndCircle; + const radius = this.attribute.circle.radius; + + const boxHeight = this.attribute.box.height; + const circleHeight = radius * 2; + const textHeight = this._text.AABBBounds.height(); + const maxHeight = Math.max(boxHeight, circleHeight, textHeight); + const circleY = maxHeight / 2 - circleHeight / 2 + radius; + const textY = maxHeight / 2 - textHeight / 2; + + const boxWidth = this.attribute.box.width; + const circleWidth = radius * 2; + // const textWidth = this._text.AABBBounds.width(); + const textWidth = measureTextSize( + (this.attribute.text?.checkedText?.length ?? 0) > (this.attribute.text?.uncheckedText?.length ?? 0) + ? this.attribute.text?.checkedText ?? '' + : this.attribute.text?.uncheckedText ?? '', + this._text.attribute + ).width; + const maxWidth = Math.max(boxWidth, circleWidth + textWidth + space * 3); // [circle[space]text[space][space]] + const circleX = boxHeight / 2 - circleWidth / 2 + radius; + const textX = circleX + radius + space; + + this._box.setAttributes({ + width: maxWidth, + height: maxHeight + }); + + // set circle position + this._circle.setAttributes({ + y: circleY, + x: this.attribute.checked ? circleX : maxWidth - circleX + }); + + // set text position + this._text.setAttributes({ + x: this.attribute.checked ? textX : maxWidth - textX - textWidth, + y: textY + }); + } + + private _handlePointerUp = () => { + if (this.attribute.disabled) { + return; + } else if (this.attribute.checked) { + this.setAttribute('checked', false); + } else { + this.setAttribute('checked', true); + } + + this._dispatchEvent('switch_state_change', { + eventType: 'switch_state_change', + checked: this.attribute.checked + }); + + this.stage.renderNextFrame(); + }; + + initAttributes(params: SwitchAttributes, options?: ComponentOptions) { + params = options?.skipDefault ? params : merge({}, Switch.defaultAttributes, params); + super.initAttributes(params); + this.renderGroup(); + this.render(); + } +} diff --git a/packages/vrender-components/src/switch/type.ts b/packages/vrender-components/src/switch/type.ts new file mode 100644 index 000000000..93186b07e --- /dev/null +++ b/packages/vrender-components/src/switch/type.ts @@ -0,0 +1,35 @@ +import type { + Cursor, + ICircleGraphicAttribute, + IColor, + IGroupGraphicAttribute, + IRectGraphicAttribute, + ITextGraphicAttribute +} from '@visactor/vrender-core'; + +export type SwitchRect = { + checkedFill?: IColor; + uncheckedFill?: IColor; + disableCheckedFill?: IColor; + disableUncheckedFill?: IColor; +} & IRectGraphicAttribute; + +export type SwitchCircle = ICircleGraphicAttribute; + +export type SwitchText = { + checkedText?: string; + uncheckedText?: string; +} & ITextGraphicAttribute; + +export type SwitchAttributes = IGroupGraphicAttribute & { + interactive?: boolean; + disabled?: boolean; + checked?: boolean; + + text?: SwitchText; + circle?: SwitchCircle; + box?: SwitchRect; + disableCursor?: Cursor; + + spaceBetweenTextAndCircle?: number; +}; From e1c82c5c8ec525c5625111e141035a2b6639fcd3 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Wed, 18 Dec 2024 19:28:36 +0800 Subject: [PATCH 02/51] fix: add onBeforeAttributeUpdate in base-component --- ...eforeAttributeUpdate_2024-12-18-11-28.json | 10 ++++++++++ packages/vrender-components/src/core/base.ts | 20 ++++++++++++++++--- 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 common/changes/@visactor/vrender-components/fix-base-onBeforeAttributeUpdate_2024-12-18-11-28.json diff --git a/common/changes/@visactor/vrender-components/fix-base-onBeforeAttributeUpdate_2024-12-18-11-28.json b/common/changes/@visactor/vrender-components/fix-base-onBeforeAttributeUpdate_2024-12-18-11-28.json new file mode 100644 index 000000000..aecfde658 --- /dev/null +++ b/common/changes/@visactor/vrender-components/fix-base-onBeforeAttributeUpdate_2024-12-18-11-28.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-components", + "comment": "fix: add onBeforeAttributeUpdate in base-component", + "type": "none" + } + ], + "packageName": "@visactor/vrender-components" +} \ No newline at end of file diff --git a/packages/vrender-components/src/core/base.ts b/packages/vrender-components/src/core/base.ts index 3c2f5a6f6..81cb72a10 100644 --- a/packages/vrender-components/src/core/base.ts +++ b/packages/vrender-components/src/core/base.ts @@ -1,7 +1,7 @@ /** * @description 组件基类 */ -import type { IGroupGraphicAttribute } from '@visactor/vrender-core'; +import type { IGroupGraphicAttribute, ISetAttributeContext } from '@visactor/vrender-core'; import { Group, CustomEvent } from '@visactor/vrender-core'; import type { Dict } from '@visactor/vutils'; import { merge, isFunction, isPlainObject, isNil } from '@visactor/vutils'; @@ -65,7 +65,13 @@ export abstract class AbstractComponent, forceUpdateTag); + } + // overwrite when previous or next attribute is function if ( isPlainObject(this.attribute[key]) && @@ -93,8 +99,16 @@ export abstract class AbstractComponent, forceUpdateTag?: boolean | undefined, context?: ISetAttributeContext): void { + params = + (this.onBeforeAttributeUpdate && + (this.onBeforeAttributeUpdate(params, this.attribute, null, context) as Partial)) || + params; + return this._setAttributes(params, forceUpdateTag); + } + // @ts-ignore - setAttributes(params: Partial, forceUpdateTag?: boolean | undefined): void { + _setAttributes(params: Partial, forceUpdateTag?: boolean | undefined): void { const keys = Object.keys(params) as (keyof T)[]; this._mergeAttributes(params, keys); From b1ad3acd36da1959dbe9d7005918108c21a4f893 Mon Sep 17 00:00:00 2001 From: xiaoluoHe Date: Mon, 23 Dec 2024 17:53:56 +0800 Subject: [PATCH 03/51] feat: store axis label related data --- packages/vrender-components/src/axis/base.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vrender-components/src/axis/base.ts b/packages/vrender-components/src/axis/base.ts index 9fc851f29..963a541ff 100644 --- a/packages/vrender-components/src/axis/base.ts +++ b/packages/vrender-components/src/axis/base.ts @@ -340,7 +340,7 @@ export abstract class AxisBase extends AbstractCom }); text.states = labelState; } - + text.data = { ...item, index, layer }; labelGroup.add(text); }); From 85807b315c73441826b4c8d4b45c578f95a747e2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 23 Dec 2024 10:21:22 +0000 Subject: [PATCH 04/51] build: prelease version 0.21.4 --- ...x-gesture-compatible_2024-12-23-09-54.json | 10 ------- common/config/rush/pnpm-lock.yaml | 26 +++++++++---------- common/config/rush/version-policies.json | 2 +- docs/package.json | 2 +- packages/react-vrender-utils/CHANGELOG.json | 6 +++++ packages/react-vrender-utils/CHANGELOG.md | 7 ++++- packages/react-vrender-utils/package.json | 6 ++--- packages/react-vrender/CHANGELOG.json | 6 +++++ packages/react-vrender/CHANGELOG.md | 7 ++++- packages/react-vrender/package.json | 4 +-- packages/vrender-components/CHANGELOG.json | 6 +++++ packages/vrender-components/CHANGELOG.md | 7 ++++- packages/vrender-components/package.json | 6 ++--- packages/vrender-core/CHANGELOG.json | 6 +++++ packages/vrender-core/CHANGELOG.md | 7 ++++- packages/vrender-core/package.json | 2 +- packages/vrender-kits/CHANGELOG.json | 12 +++++++++ packages/vrender-kits/CHANGELOG.md | 9 ++++++- packages/vrender-kits/package.json | 4 +-- packages/vrender/CHANGELOG.json | 6 +++++ packages/vrender/CHANGELOG.md | 7 ++++- packages/vrender/package.json | 6 ++--- tools/bugserver-trigger/package.json | 8 +++--- 23 files changed, 113 insertions(+), 49 deletions(-) delete mode 100644 common/changes/@visactor/vrender-kits/fix-gesture-compatible_2024-12-23-09-54.json diff --git a/common/changes/@visactor/vrender-kits/fix-gesture-compatible_2024-12-23-09-54.json b/common/changes/@visactor/vrender-kits/fix-gesture-compatible_2024-12-23-09-54.json deleted file mode 100644 index 66f46320a..000000000 --- a/common/changes/@visactor/vrender-kits/fix-gesture-compatible_2024-12-23-09-54.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vrender-kits", - "comment": "fix: fix issue with gesture emitEvent when gesture is released", - "type": "none" - } - ], - "packageName": "@visactor/vrender-kits" -} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index b28188194..7b410c21a 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -14,7 +14,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vchart': 1.3.0 '@visactor/vgrammar': ~0.5.7 - '@visactor/vrender': workspace:0.21.3 + '@visactor/vrender': workspace:0.21.4 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 axios: ^1.4.0 @@ -71,7 +71,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@types/react-reconciler': ^0.28.2 - '@visactor/vrender': workspace:0.21.3 + '@visactor/vrender': workspace:0.21.4 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 @@ -111,8 +111,8 @@ importers: '@rushstack/eslint-patch': ~1.1.4 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/react-vrender': workspace:0.21.3 - '@visactor/vrender': workspace:0.21.3 + '@visactor/react-vrender': workspace:0.21.4 + '@visactor/vrender': workspace:0.21.4 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 @@ -153,8 +153,8 @@ importers: '@types/jest': ^26.0.0 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vrender-core': workspace:0.21.3 - '@visactor/vrender-kits': workspace:0.21.3 + '@visactor/vrender-core': workspace:0.21.4 + '@visactor/vrender-kits': workspace:0.21.4 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 @@ -200,8 +200,8 @@ importers: '@internal/ts-config': workspace:* '@rushstack/eslint-patch': ~1.1.4 '@types/jest': ^26.0.0 - '@visactor/vrender-core': workspace:0.21.3 - '@visactor/vrender-kits': workspace:0.21.3 + '@visactor/vrender-core': workspace:0.21.4 + '@visactor/vrender-kits': workspace:0.21.4 '@visactor/vscale': ~0.19.2 '@visactor/vutils': ~0.19.2 cross-env: ^7.0.3 @@ -287,7 +287,7 @@ importers: '@types/node-fetch': 2.6.4 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vrender-core': workspace:0.21.3 + '@visactor/vrender-core': workspace:0.21.4 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 @@ -369,10 +369,10 @@ importers: '@rushstack/eslint-patch': ~1.1.4 '@types/node': '*' '@types/node-fetch': 2.6.4 - '@visactor/vrender': workspace:0.21.3 - '@visactor/vrender-components': workspace:0.21.3 - '@visactor/vrender-core': workspace:0.21.3 - '@visactor/vrender-kits': workspace:0.21.3 + '@visactor/vrender': workspace:0.21.4 + '@visactor/vrender-components': workspace:0.21.4 + '@visactor/vrender-core': workspace:0.21.4 + '@visactor/vrender-kits': workspace:0.21.4 cross-env: ^7.0.3 eslint: ~8.18.0 form-data: ~4.0.0 diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json index ae6d22b59..7f88b0965 100644 --- a/common/config/rush/version-policies.json +++ b/common/config/rush/version-policies.json @@ -1 +1 @@ -[{"definitionName":"lockStepVersion","policyName":"vrenderMain","version":"0.21.3","nextBump":"patch"}] +[{"definitionName":"lockStepVersion","policyName":"vrenderMain","version":"0.21.4","nextBump":"patch"}] diff --git a/docs/package.json b/docs/package.json index 8fa171eb2..572beefc9 100644 --- a/docs/package.json +++ b/docs/package.json @@ -13,7 +13,7 @@ "@visactor/vchart": "1.3.0", "@visactor/vutils": "~0.19.2", "@visactor/vgrammar": "~0.5.7", - "@visactor/vrender": "workspace:0.21.3", + "@visactor/vrender": "workspace:0.21.4", "markdown-it": "^13.0.0", "highlight.js": "^11.8.0", "axios": "^1.4.0", diff --git a/packages/react-vrender-utils/CHANGELOG.json b/packages/react-vrender-utils/CHANGELOG.json index 53e53d5b2..076146ca6 100644 --- a/packages/react-vrender-utils/CHANGELOG.json +++ b/packages/react-vrender-utils/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/react-vrender-utils", "entries": [ + { + "version": "0.21.4", + "tag": "@visactor/react-vrender-utils_v0.21.4", + "date": "Mon, 23 Dec 2024 10:16:00 GMT", + "comments": {} + }, { "version": "0.21.3", "tag": "@visactor/react-vrender-utils_v0.21.3", diff --git a/packages/react-vrender-utils/CHANGELOG.md b/packages/react-vrender-utils/CHANGELOG.md index ebff27066..7578c992b 100644 --- a/packages/react-vrender-utils/CHANGELOG.md +++ b/packages/react-vrender-utils/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/react-vrender-utils -This log was last generated on Mon, 23 Dec 2024 08:28:14 GMT and should not be manually modified. +This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. + +## 0.21.4 +Mon, 23 Dec 2024 10:16:00 GMT + +_Version update only_ ## 0.21.3 Mon, 23 Dec 2024 08:28:14 GMT diff --git a/packages/react-vrender-utils/package.json b/packages/react-vrender-utils/package.json index dcc8ba649..f100bebaa 100644 --- a/packages/react-vrender-utils/package.json +++ b/packages/react-vrender-utils/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vrender-utils", - "version": "0.21.3", + "version": "0.21.4", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -24,8 +24,8 @@ "react-dom": "^18.2.0" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.3", - "@visactor/react-vrender": "workspace:0.21.3", + "@visactor/vrender": "workspace:0.21.4", + "@visactor/react-vrender": "workspace:0.21.4", "@visactor/vutils": "~0.19.2", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" diff --git a/packages/react-vrender/CHANGELOG.json b/packages/react-vrender/CHANGELOG.json index 46f8e5aad..433e8a9c7 100644 --- a/packages/react-vrender/CHANGELOG.json +++ b/packages/react-vrender/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/react-vrender", "entries": [ + { + "version": "0.21.4", + "tag": "@visactor/react-vrender_v0.21.4", + "date": "Mon, 23 Dec 2024 10:16:00 GMT", + "comments": {} + }, { "version": "0.21.3", "tag": "@visactor/react-vrender_v0.21.3", diff --git a/packages/react-vrender/CHANGELOG.md b/packages/react-vrender/CHANGELOG.md index d0ce86e11..593557f50 100644 --- a/packages/react-vrender/CHANGELOG.md +++ b/packages/react-vrender/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/react-vrender -This log was last generated on Mon, 23 Dec 2024 08:28:14 GMT and should not be manually modified. +This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. + +## 0.21.4 +Mon, 23 Dec 2024 10:16:00 GMT + +_Version update only_ ## 0.21.3 Mon, 23 Dec 2024 08:28:14 GMT diff --git a/packages/react-vrender/package.json b/packages/react-vrender/package.json index 59e8d9c97..cb9a23a50 100644 --- a/packages/react-vrender/package.json +++ b/packages/react-vrender/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vrender", - "version": "0.21.3", + "version": "0.21.4", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -23,7 +23,7 @@ "react": "^18.2.0" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.3", + "@visactor/vrender": "workspace:0.21.4", "@visactor/vutils": "~0.19.2", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" diff --git a/packages/vrender-components/CHANGELOG.json b/packages/vrender-components/CHANGELOG.json index 8b32d7ece..7047f6127 100644 --- a/packages/vrender-components/CHANGELOG.json +++ b/packages/vrender-components/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/vrender-components", "entries": [ + { + "version": "0.21.4", + "tag": "@visactor/vrender-components_v0.21.4", + "date": "Mon, 23 Dec 2024 10:16:00 GMT", + "comments": {} + }, { "version": "0.21.3", "tag": "@visactor/vrender-components_v0.21.3", diff --git a/packages/vrender-components/CHANGELOG.md b/packages/vrender-components/CHANGELOG.md index efad89fcc..ba9de1304 100644 --- a/packages/vrender-components/CHANGELOG.md +++ b/packages/vrender-components/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/vrender-components -This log was last generated on Mon, 23 Dec 2024 08:28:14 GMT and should not be manually modified. +This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. + +## 0.21.4 +Mon, 23 Dec 2024 10:16:00 GMT + +_Version update only_ ## 0.21.3 Mon, 23 Dec 2024 08:28:14 GMT diff --git a/packages/vrender-components/package.json b/packages/vrender-components/package.json index da2c6a4f6..1934f1e18 100644 --- a/packages/vrender-components/package.json +++ b/packages/vrender-components/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-components", - "version": "0.21.3", + "version": "0.21.4", "description": "components library for dp visualization", "sideEffects": false, "main": "cjs/index.js", @@ -27,8 +27,8 @@ "dependencies": { "@visactor/vutils": "~0.19.2", "@visactor/vscale": "~0.19.2", - "@visactor/vrender-core": "workspace:0.21.3", - "@visactor/vrender-kits": "workspace:0.21.3" + "@visactor/vrender-core": "workspace:0.21.4", + "@visactor/vrender-kits": "workspace:0.21.4" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/packages/vrender-core/CHANGELOG.json b/packages/vrender-core/CHANGELOG.json index 5916fd7e3..e02bc7f58 100644 --- a/packages/vrender-core/CHANGELOG.json +++ b/packages/vrender-core/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/vrender-core", "entries": [ + { + "version": "0.21.4", + "tag": "@visactor/vrender-core_v0.21.4", + "date": "Mon, 23 Dec 2024 10:16:00 GMT", + "comments": {} + }, { "version": "0.21.3", "tag": "@visactor/vrender-core_v0.21.3", diff --git a/packages/vrender-core/CHANGELOG.md b/packages/vrender-core/CHANGELOG.md index 9e4b243c8..7304a989f 100644 --- a/packages/vrender-core/CHANGELOG.md +++ b/packages/vrender-core/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/vrender-core -This log was last generated on Mon, 23 Dec 2024 08:28:14 GMT and should not be manually modified. +This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. + +## 0.21.4 +Mon, 23 Dec 2024 10:16:00 GMT + +_Version update only_ ## 0.21.3 Mon, 23 Dec 2024 08:28:14 GMT diff --git a/packages/vrender-core/package.json b/packages/vrender-core/package.json index 098003215..087eb08b0 100644 --- a/packages/vrender-core/package.json +++ b/packages/vrender-core/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-core", - "version": "0.21.3", + "version": "0.21.4", "description": "", "sideEffects": [ "./src/modules.ts", diff --git a/packages/vrender-kits/CHANGELOG.json b/packages/vrender-kits/CHANGELOG.json index 9f8a890a2..8ce7ec4a9 100644 --- a/packages/vrender-kits/CHANGELOG.json +++ b/packages/vrender-kits/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/vrender-kits", "entries": [ + { + "version": "0.21.4", + "tag": "@visactor/vrender-kits_v0.21.4", + "date": "Mon, 23 Dec 2024 10:16:00 GMT", + "comments": { + "none": [ + { + "comment": "fix: fix issue with gesture emitEvent when gesture is released" + } + ] + } + }, { "version": "0.21.3", "tag": "@visactor/vrender-kits_v0.21.3", diff --git a/packages/vrender-kits/CHANGELOG.md b/packages/vrender-kits/CHANGELOG.md index 2e1918671..ea5e8af78 100644 --- a/packages/vrender-kits/CHANGELOG.md +++ b/packages/vrender-kits/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log - @visactor/vrender-kits -This log was last generated on Mon, 23 Dec 2024 08:28:14 GMT and should not be manually modified. +This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. + +## 0.21.4 +Mon, 23 Dec 2024 10:16:00 GMT + +### Updates + +- fix: fix issue with gesture emitEvent when gesture is released ## 0.21.3 Mon, 23 Dec 2024 08:28:14 GMT diff --git a/packages/vrender-kits/package.json b/packages/vrender-kits/package.json index ca42a90ff..eba43ba6d 100644 --- a/packages/vrender-kits/package.json +++ b/packages/vrender-kits/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-kits", - "version": "0.21.3", + "version": "0.21.4", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -21,7 +21,7 @@ }, "dependencies": { "@visactor/vutils": "~0.19.2", - "@visactor/vrender-core": "workspace:0.21.3", + "@visactor/vrender-core": "workspace:0.21.4", "@resvg/resvg-js": "2.4.1", "roughjs": "4.5.2" }, diff --git a/packages/vrender/CHANGELOG.json b/packages/vrender/CHANGELOG.json index fed22b258..3355ae114 100644 --- a/packages/vrender/CHANGELOG.json +++ b/packages/vrender/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/vrender", "entries": [ + { + "version": "0.21.4", + "tag": "@visactor/vrender_v0.21.4", + "date": "Mon, 23 Dec 2024 10:16:00 GMT", + "comments": {} + }, { "version": "0.21.3", "tag": "@visactor/vrender_v0.21.3", diff --git a/packages/vrender/CHANGELOG.md b/packages/vrender/CHANGELOG.md index c5fbdc02d..23b46f83f 100644 --- a/packages/vrender/CHANGELOG.md +++ b/packages/vrender/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/vrender -This log was last generated on Mon, 23 Dec 2024 08:28:14 GMT and should not be manually modified. +This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. + +## 0.21.4 +Mon, 23 Dec 2024 10:16:00 GMT + +_Version update only_ ## 0.21.3 Mon, 23 Dec 2024 08:28:14 GMT diff --git a/packages/vrender/package.json b/packages/vrender/package.json index 9b8a391c3..c6796ff01 100644 --- a/packages/vrender/package.json +++ b/packages/vrender/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender", - "version": "0.21.3", + "version": "0.21.4", "description": "", "sideEffects": true, "main": "cjs/index.js", @@ -24,8 +24,8 @@ "test-watch": "cross-env DEBUG_MODE=1 jest --watch" }, "dependencies": { - "@visactor/vrender-core": "workspace:0.21.3", - "@visactor/vrender-kits": "workspace:0.21.3" + "@visactor/vrender-core": "workspace:0.21.4", + "@visactor/vrender-kits": "workspace:0.21.4" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/tools/bugserver-trigger/package.json b/tools/bugserver-trigger/package.json index 78f399fde..5e8a3de38 100644 --- a/tools/bugserver-trigger/package.json +++ b/tools/bugserver-trigger/package.json @@ -8,10 +8,10 @@ "ci": "ts-node --transpileOnly --skipProject ./scripts/trigger-test.ts" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.3", - "@visactor/vrender-core": "workspace:0.21.3", - "@visactor/vrender-kits": "workspace:0.21.3", - "@visactor/vrender-components": "workspace:0.21.3" + "@visactor/vrender": "workspace:0.21.4", + "@visactor/vrender-core": "workspace:0.21.4", + "@visactor/vrender-kits": "workspace:0.21.4", + "@visactor/vrender-components": "workspace:0.21.4" }, "devDependencies": { "@rushstack/eslint-patch": "~1.1.4", From 69086d5a2004997973dda9a4cbb6574c9ffcbd3d Mon Sep 17 00:00:00 2001 From: neuqzxy Date: Mon, 23 Dec 2024 10:33:19 +0000 Subject: [PATCH 05/51] docs: generate changelog of release v0.21.4 --- docs/assets/changelog/en/changelog.md | 13 +++++++++++++ docs/assets/changelog/zh/changelog.md | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/docs/assets/changelog/en/changelog.md b/docs/assets/changelog/en/changelog.md index 09fb203e4..553a897db 100644 --- a/docs/assets/changelog/en/changelog.md +++ b/docs/assets/changelog/en/changelog.md @@ -1,3 +1,16 @@ +# v0.21.4 + +2024-12-23 + + +**🐛 Bug fix** + +- **@visactor/vrender-kits**: fix issue with gesture emitEvent when gesture is released + + + +[more detail about v0.21.4](https://github.com/VisActor/VRender/releases/tag/v0.21.4) + # v0.21.3 2024-12-23 diff --git a/docs/assets/changelog/zh/changelog.md b/docs/assets/changelog/zh/changelog.md index c1cac48e1..737084441 100644 --- a/docs/assets/changelog/zh/changelog.md +++ b/docs/assets/changelog/zh/changelog.md @@ -1,3 +1,16 @@ +# v0.21.4 + +2024-12-23 + + +**🐛 功能修复** + +- **@visactor/vrender-kits**: fix issue with gesture emitEvent when gesture is released + + + +[更多详情请查看 v0.21.4](https://github.com/VisActor/VRender/releases/tag/v0.21.4) + # v0.21.3 2024-12-23 From 2e6f24b7716c1dd87c452ebe16f623bc5b20a15f Mon Sep 17 00:00:00 2001 From: xiaoluoHe Date: Mon, 23 Dec 2024 20:32:52 +0800 Subject: [PATCH 06/51] feat: support polygon sector crosshair for non-smooth angle axis --- .../examples/crosshair-polygon-sector.ts | 27 ++++++++ .../__tests__/browser/main.ts | 4 ++ .../vrender-components/src/crosshair/index.ts | 4 +- .../src/crosshair/polygon-sector.ts | 66 +++++++++++++++++++ .../src/crosshair/register.ts | 5 ++ .../vrender-components/src/crosshair/type.ts | 21 +++++- 6 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 packages/vrender-components/__tests__/browser/examples/crosshair-polygon-sector.ts create mode 100644 packages/vrender-components/src/crosshair/polygon-sector.ts diff --git a/packages/vrender-components/__tests__/browser/examples/crosshair-polygon-sector.ts b/packages/vrender-components/__tests__/browser/examples/crosshair-polygon-sector.ts new file mode 100644 index 000000000..ceac08290 --- /dev/null +++ b/packages/vrender-components/__tests__/browser/examples/crosshair-polygon-sector.ts @@ -0,0 +1,27 @@ +import '@visactor/vrender'; +import render from '../../util/render'; +import { PolygonSectorCrosshair, SectorCrosshair } from '../../../src'; + +export function run() { + const startAngle = 1.3 * Math.PI; + const endAngle = 1.7 * Math.PI; + const crosshair = new PolygonSectorCrosshair({ + center: { + x: 250, + y: 250 + }, + radius: 100, + innerRadius: 30, + startAngle, + endAngle + }); + + const stage = render([crosshair], 'main'); + + stage.addEventListener('pointermove', e => { + crosshair.setLocation({ + x: e.viewX, + y: e.viewY + }); + }); +} diff --git a/packages/vrender-components/__tests__/browser/main.ts b/packages/vrender-components/__tests__/browser/main.ts index 595d01510..a22968776 100644 --- a/packages/vrender-components/__tests__/browser/main.ts +++ b/packages/vrender-components/__tests__/browser/main.ts @@ -154,6 +154,10 @@ const specs = [ path: 'crosshair-sector', name: '扇形 crosshair' }, + { + path: 'crosshair-polygon-sector', + name: '矩形扇形 crosshair' + }, { path: 'crosshair-polygon', name: '多边形 crosshair' diff --git a/packages/vrender-components/src/crosshair/index.ts b/packages/vrender-components/src/crosshair/index.ts index e957e76f9..7360b7764 100644 --- a/packages/vrender-components/src/crosshair/index.ts +++ b/packages/vrender-components/src/crosshair/index.ts @@ -2,13 +2,15 @@ * @description crosshair 组件 * 1. line 直线 * 2. rect 矩形 - * 3. sector rect 在极坐标系下的 + * 3. sector rect 在极坐标系下的角度轴,smooth === true 时 * 4. circle 用于极坐标系下弧度轴,smooth === true 时 * 5. polygon 用于极坐标系下弧度轴,smooth === false 时 + * 6. polygon-sector 用于极坐标系下的角度轴,smooth === false 时 */ export * from './line'; export * from './rect'; export * from './circle'; export * from './sector'; export * from './polygon'; +export * from './polygon-sector'; export * from './type'; diff --git a/packages/vrender-components/src/crosshair/polygon-sector.ts b/packages/vrender-components/src/crosshair/polygon-sector.ts new file mode 100644 index 000000000..fbefdacc5 --- /dev/null +++ b/packages/vrender-components/src/crosshair/polygon-sector.ts @@ -0,0 +1,66 @@ +/** + * @description sector 类型 crosshair,用于极坐标系下 + */ +import type { IGroup } from '@visactor/vrender-core'; +import { merge, getAngleByPoint, radianToDegree, polarToCartesian } from '@visactor/vutils'; +import type { PointLocationCfg } from '../core/type'; +import { POLAR_END_ANGLE, POLAR_START_ANGLE } from '../constant'; +import { CrosshairBase } from './base'; +import type { PolygonSectorCrosshairAttrs } from './type'; +import type { ComponentOptions } from '../interface'; +import { loadPolygonSectorCrosshairComponent } from './register'; + +loadPolygonSectorCrosshairComponent(); +export class PolygonSectorCrosshair extends CrosshairBase { + static defaultAttributes = { + polygonSectorStyle: { + fill: '#b2bacf', + opacity: 0.2 + } + }; + + constructor(attributes: PolygonSectorCrosshairAttrs, options?: ComponentOptions) { + super(options?.skipDefault ? attributes : merge({}, PolygonSectorCrosshair.defaultAttributes, attributes)); + } + + protected renderCrosshair(container: IGroup) { + const { center, radius, innerRadius = 0, polygonSectorStyle } = this.attribute as PolygonSectorCrosshairAttrs; + const { startAngle, endAngle } = this.attribute; + const points = []; + points.push(polarToCartesian(center, innerRadius, startAngle)); + points.push(polarToCartesian(center, radius * Math.cos((endAngle - startAngle) / 2), startAngle)); + points.push(polarToCartesian(center, radius, (startAngle + endAngle) / 2)); + points.push(polarToCartesian(center, radius * Math.cos((endAngle - startAngle) / 2), endAngle)); + points.push(polarToCartesian(center, innerRadius, endAngle)); + const path = points.reduce((acc, cur, index) => { + if (index === 0) { + return `M${cur.x},${cur.y}`; + } + return acc + `L${cur.x},${cur.y}`; + }, ''); + + const polygon = container.createOrUpdateChild( + 'crosshair-polygon-sector', + { + path, + ...polygonSectorStyle + }, + 'path' + ); + return polygon; + } + + setLocation(point: PointLocationCfg) { + const { + center, + startAngle = POLAR_START_ANGLE, + endAngle = POLAR_END_ANGLE + } = this.attribute as PolygonSectorCrosshairAttrs; + const sectorAngle = endAngle - startAngle; + const pointAngle = radianToDegree(getAngleByPoint(center, point)); + this.setAttributes({ + startAngle: pointAngle - sectorAngle / 2, + endAngle: pointAngle + sectorAngle / 2 + }); + } +} diff --git a/packages/vrender-components/src/crosshair/register.ts b/packages/vrender-components/src/crosshair/register.ts index dbc834fbf..cd928e7d9 100644 --- a/packages/vrender-components/src/crosshair/register.ts +++ b/packages/vrender-components/src/crosshair/register.ts @@ -25,3 +25,8 @@ export function loadSectorCrosshairComponent() { registerGroup(); registerArc(); } + +export function loadPolygonSectorCrosshairComponent() { + registerGroup(); + registerPath(); +} diff --git a/packages/vrender-components/src/crosshair/type.ts b/packages/vrender-components/src/crosshair/type.ts index f5ee93fc1..8156661b0 100644 --- a/packages/vrender-components/src/crosshair/type.ts +++ b/packages/vrender-components/src/crosshair/type.ts @@ -1,8 +1,13 @@ -import type { IGroupGraphicAttribute, ILineGraphicAttribute, IRectGraphicAttribute } from '@visactor/vrender-core'; +import type { + IGroupGraphicAttribute, + ILineGraphicAttribute, + IPolygonGraphicAttribute, + IRectGraphicAttribute +} from '@visactor/vrender-core'; import type { Point } from '../core/type'; export interface BaseCrosshairAttrs extends IGroupGraphicAttribute { - type?: 'line' | 'rect' | 'circle' | 'polygon' | 'sector'; + type?: 'line' | 'rect' | 'circle' | 'polygon' | 'sector' | 'polygon-sector'; } export interface PolarCrosshairAttrs extends BaseCrosshairAttrs { @@ -83,3 +88,15 @@ export interface PolygonCrosshairAttrs extends PolarCrosshairAttrs { /** 多边形样式 */ lineStyle?: Partial; } + +export interface PolygonSectorCrosshairAttrs extends PolarCrosshairAttrs { + type?: 'polygon-sector'; + /** + * 内半径 + */ + innerRadius?: number; + /** + * 样式配置 + */ + polygonSectorStyle?: Partial; +} From d7b845dba711b8787b1475ddd5d66d94f7abce56 Mon Sep 17 00:00:00 2001 From: xiaoluoHe Date: Mon, 23 Dec 2024 20:33:53 +0800 Subject: [PATCH 07/51] docs: add changelog --- ...feat-polygon-sector-crosshair_2024-12-23-12-33.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json diff --git a/common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json b/common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json new file mode 100644 index 000000000..11ea174bb --- /dev/null +++ b/common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-components", + "comment": "feat: support polygon sector crosshair for non-smooth angle axis", + "type": "none" + } + ], + "packageName": "@visactor/vrender-components" +} \ No newline at end of file From 644c1746b627c651111a26aef698b244ad2b08fa Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 24 Dec 2024 11:39:16 +0800 Subject: [PATCH 08/51] fix: fix issue with image background stroke --- ...fix-image-background_2024-12-24-03-40.json | 10 + .../image-contribution-render.ts | 237 +++++++++--------- .../contributions/render/image-render.ts | 53 ++-- 3 files changed, 156 insertions(+), 144 deletions(-) create mode 100644 common/changes/@visactor/vrender-core/fix-image-background_2024-12-24-03-40.json diff --git a/common/changes/@visactor/vrender-core/fix-image-background_2024-12-24-03-40.json b/common/changes/@visactor/vrender-core/fix-image-background_2024-12-24-03-40.json new file mode 100644 index 000000000..e8b1f67de --- /dev/null +++ b/common/changes/@visactor/vrender-core/fix-image-background_2024-12-24-03-40.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "fix: fix issue with image background stroke, closed #1640", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file diff --git a/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts b/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts index bb0e833de..37a95be2d 100644 --- a/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts +++ b/packages/vrender-core/src/render/contributions/render/contributions/image-contribution-render.ts @@ -10,137 +10,140 @@ import type { IMarkAttribute } from '../../../../interface'; import { getTheme } from '../../../../graphic/theme'; -import { DefaultBaseBackgroundRenderContribution } from './base-contribution-render'; +import { + defaultBaseBackgroundRenderContribution, + DefaultBaseBackgroundRenderContribution +} from './base-contribution-render'; import { BaseRenderContributionTime } from '../../../../common/enums'; import { isNumber, isObject } from '@visactor/vutils'; import { parsePadding } from '../../../../common/utils'; import { createRectPath } from '../../../../common/shape/rect'; import { DefaultRectRenderContribution } from './rect-contribution-render'; -export class DefaultImageBackgroundRenderContribution - extends DefaultBaseBackgroundRenderContribution - implements IImageRenderContribution -{ - time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; +// export class DefaultImageBackgroundRenderContribution +// extends DefaultBaseBackgroundRenderContribution +// implements IImageRenderContribution +// { +// time: BaseRenderContributionTime = BaseRenderContributionTime.beforeFillStroke; - drawShape( - graphic: IImage, - context: IContext2d, - x: number, - y: number, - doFill: boolean, - doStroke: boolean, - fVisible: boolean, - sVisible: boolean, - graphicAttribute: Required, - drawContext: IDrawContext, - fillCb?: (ctx: IContext2d, markAttribute: Partial, themeAttribute: IThemeAttribute) => boolean, - strokeCb?: (ctx: IContext2d, markAttribute: Partial, themeAttribute: IThemeAttribute) => boolean - ) { - const { - background, - backgroundMode = graphicAttribute.backgroundMode, - backgroundFit = graphicAttribute.backgroundFit, - width, - height - } = graphic.attribute; - if (!background) { - return; - } +// drawShape( +// graphic: IImage, +// context: IContext2d, +// x: number, +// y: number, +// doFill: boolean, +// doStroke: boolean, +// fVisible: boolean, +// sVisible: boolean, +// graphicAttribute: Required, +// drawContext: IDrawContext, +// fillCb?: (ctx: IContext2d, markAttribute: Partial, themeAttribute: IThemeAttribute) => boolean, +// strokeCb?: (ctx: IContext2d, markAttribute: Partial, themeAttribute: IThemeAttribute) => boolean +// ) { +// const { +// background, +// backgroundMode = graphicAttribute.backgroundMode, +// backgroundFit = graphicAttribute.backgroundFit, +// width, +// height +// } = graphic.attribute; +// if (!background) { +// return; +// } - if (!graphic.backgroundImg) { - if (isObject(background)) { - const { - stroke, - fill, - lineWidth = 1, - cornerRadius = 0, - expandX = 0, - expandY = 0 - } = background as IBackgroundConfig; +// if (!graphic.backgroundImg) { +// if (isObject(background)) { +// const { +// stroke, +// fill, +// lineWidth = 1, +// cornerRadius = 0, +// expandX = 0, +// expandY = 0 +// } = background as IBackgroundConfig; - if (!stroke && !fill) { - return; - } +// if (!stroke && !fill) { +// return; +// } - context.beginPath(); - const { x, y, width, height } = getActualPosition(graphic); - if (cornerRadius) { - createRectPath(context, x - expandX, y - expandY, width + expandX * 2, height + expandY * 2, cornerRadius); - } else { - context.rect(x - expandX, y - expandY, width + expandX * 2, height + expandY * 2); - } +// context.beginPath(); +// const { x, y, width, height } = getActualPosition(graphic); +// if (cornerRadius) { +// createRectPath(context, x - expandX, y - expandY, width + expandX * 2, height + expandY * 2, cornerRadius); +// } else { +// context.rect(x - expandX, y - expandY, width + expandX * 2, height + expandY * 2); +// } - context.globalAlpha = 1; - if (fill) { - context.fillStyle = fill as string; - context.fill(); - } +// context.globalAlpha = 1; +// if (fill) { +// context.fillStyle = fill as string; +// context.fill(); +// } - if (stroke && lineWidth > 0) { - context.lineWidth = lineWidth; - context.strokeStyle = stroke as string; - context.stroke(); - } - } else { - context.beginPath(); - // const b = graphic.AABBBounds; - // image的背景不包括Bounds了 - context.rect(x, y, width || 0, height || 0); - context.fillStyle = background as string; - context.globalAlpha = 1; - context.fill(); - } - } else { - const res = graphic.resources.get(background as any); - if (res.state !== 'success' || !res.data) { - return; - } - context.save(); - if (graphic.parent && !graphic.transMatrix.onlyTranslate()) { - const groupAttribute = getTheme(graphic.parent).group; - const { scrollX = groupAttribute.scrollX, scrollY = groupAttribute.scrollY } = graphic.parent.attribute; - context.setTransformFromMatrix(graphic.parent.globalTransMatrix, true); - context.translate(scrollX, scrollY); - } - // context.clip(); - const b = graphic.AABBBounds; - this.doDrawImage(context, res.data, b, backgroundMode, backgroundFit); - context.restore(); - if (!graphic.transMatrix.onlyTranslate()) { - context.setTransformForCurrent(); - } - } - } -} +// if (stroke && lineWidth > 0) { +// context.lineWidth = lineWidth; +// context.strokeStyle = stroke as string; +// context.stroke(); +// } +// } else { +// context.beginPath(); +// // const b = graphic.AABBBounds; +// // image的背景不包括Bounds了 +// context.rect(x, y, width || 0, height || 0); +// context.fillStyle = background as string; +// context.globalAlpha = 1; +// context.fill(); +// } +// } else { +// const res = graphic.resources.get(background as any); +// if (res.state !== 'success' || !res.data) { +// return; +// } +// context.save(); +// if (graphic.parent && !graphic.transMatrix.onlyTranslate()) { +// const groupAttribute = getTheme(graphic.parent).group; +// const { scrollX = groupAttribute.scrollX, scrollY = groupAttribute.scrollY } = graphic.parent.attribute; +// context.setTransformFromMatrix(graphic.parent.globalTransMatrix, true); +// context.translate(scrollX, scrollY); +// } +// // context.clip(); +// const b = graphic.AABBBounds; +// this.doDrawImage(context, res.data, b, backgroundMode, backgroundFit); +// context.restore(); +// if (!graphic.transMatrix.onlyTranslate()) { +// context.setTransformForCurrent(); +// } +// } +// } +// } -function getActualPosition(graphic: IGraphic) { - const boundsPadding = parsePadding(graphic.attribute.boundsPadding); - const bounds = graphic.AABBBounds; - let x = bounds.x1; - let y = bounds.y1; - let width = bounds.width(); - let height = bounds.height(); +// function getActualPosition(graphic: IGraphic) { +// const boundsPadding = parsePadding(graphic.attribute.boundsPadding); +// const bounds = graphic.AABBBounds; +// let x = bounds.x1; +// let y = bounds.y1; +// let width = bounds.width(); +// let height = bounds.height(); - if (isNumber(boundsPadding)) { - x += boundsPadding; - y += boundsPadding; - width -= boundsPadding * 2; - height -= boundsPadding * 2; - } else { - x += boundsPadding[3]; - y += boundsPadding[0]; - width -= boundsPadding[1] + boundsPadding[3]; - height -= boundsPadding[0] + boundsPadding[2]; - } +// if (isNumber(boundsPadding)) { +// x += boundsPadding; +// y += boundsPadding; +// width -= boundsPadding * 2; +// height -= boundsPadding * 2; +// } else { +// x += boundsPadding[3]; +// y += boundsPadding[0]; +// width -= boundsPadding[1] + boundsPadding[3]; +// height -= boundsPadding[0] + boundsPadding[2]; +// } - return { - x, - y, - width, - height - }; -} +// return { +// x, +// y, +// width, +// height +// }; +// } export class DefaultImageRenderContribution extends DefaultRectRenderContribution implements IImageRenderContribution { time: BaseRenderContributionTime = BaseRenderContributionTime.afterFillStroke; @@ -186,4 +189,4 @@ export class DefaultImageRenderContribution extends DefaultRectRenderContributio } export const defaultImageRenderContribution = new DefaultImageRenderContribution(); -export const defaultImageBackgroundRenderContribution = new DefaultImageBackgroundRenderContribution(); +export const defaultImageBackgroundRenderContribution = defaultBaseBackgroundRenderContribution; diff --git a/packages/vrender-core/src/render/contributions/render/image-render.ts b/packages/vrender-core/src/render/contributions/render/image-render.ts index 540b09a07..7155d0cbf 100644 --- a/packages/vrender-core/src/render/contributions/render/image-render.ts +++ b/packages/vrender-core/src/render/contributions/render/image-render.ts @@ -80,11 +80,30 @@ export class DefaultCanvasImageRender extends BaseRender implements IGra } const { fVisible, sVisible, doFill, doStroke } = data; - // shadow - context.setShadowBlendStyle && context.setShadowBlendStyle(image, image.attribute, imageAttribute); + if (!url || !image.resources) { + return; + } + const res = image.resources.get(url); + if (res.state !== 'success') { + return; + } + + // deal with cornerRadius + let needRestore = false; + if (cornerRadius === 0 || (isArray(cornerRadius) && (cornerRadius).every(num => num === 0))) { + // 不需要处理圆角 + } else { + context.beginPath(); + createRectPath(context, x, y, width, height, cornerRadius); + context.save(); + context.clip(); + needRestore = true; + } this.beforeRenderStep(image, context, x, y, doFill, false, fVisible, false, imageAttribute, drawContext, fillCb); + // shadow + context.setShadowBlendStyle && context.setShadowBlendStyle(image, image.attribute, imageAttribute); // context.beginPath(); // context.image(x, y, width, height); @@ -93,26 +112,6 @@ export class DefaultCanvasImageRender extends BaseRender implements IGra if (fillCb) { fillCb(context, image.attribute, imageAttribute); } else if (fVisible) { - if (!url || !image.resources) { - return; - } - const res = image.resources.get(url); - if (res.state !== 'success') { - return; - } - - // deal with cornerRadius - let needRestore = false; - if (cornerRadius === 0 || (isArray(cornerRadius) && (cornerRadius).every(num => num === 0))) { - // 不需要处理圆角 - } else { - context.beginPath(); - createRectPath(context, x, y, width, height, cornerRadius); - context.save(); - context.clip(); - needRestore = true; - } - context.setCommonStyle(image, image.attribute, x, y, imageAttribute); let repeat = 0; if (repeatX === 'repeat') { @@ -130,10 +129,6 @@ export class DefaultCanvasImageRender extends BaseRender implements IGra } else { context.drawImage(res.data, x, y, width, height); } - - if (needRestore) { - context.restore(); - } } } }; @@ -144,7 +139,7 @@ export class DefaultCanvasImageRender extends BaseRender implements IGra strokeCb(context, image.attribute, imageAttribute); } else if (sVisible) { context.setStrokeStyle(image, image.attribute, originX - x, originY - y, imageAttribute); - context.strokeRect(x, y, width, height); + context.stroke(); } } }; @@ -158,6 +153,10 @@ export class DefaultCanvasImageRender extends BaseRender implements IGra } this.afterRenderStep(image, context, x, y, doFill, false, fVisible, false, imageAttribute, drawContext, fillCb); + + if (needRestore) { + context.restore(); + } } draw(image: IImage, renderService: IRenderService, drawContext: IDrawContext) { From 7d3e85136823e83c41bb3661b857933d4eafbe10 Mon Sep 17 00:00:00 2001 From: Rui-Sun Date: Tue, 24 Dec 2024 15:06:56 +0800 Subject: [PATCH 09/51] fix: height option in HtmlAttributePlugin --- .../src/plugins/builtin-plugin/html-attribute-plugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/html-attribute-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/html-attribute-plugin.ts index 3e371baa4..0873420d7 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/html-attribute-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/html-attribute-plugin.ts @@ -196,7 +196,7 @@ export class HtmlAttributePlugin implements IPlugin { // 更新样式 application.global.updateDom(wrapContainer, { width: options.width, - height: options.width, + height: options.height, style: calculateStyle }); } From a6402a1e4abdbdfe639320504f75e081b7cbac26 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 24 Dec 2024 07:57:35 +0000 Subject: [PATCH 10/51] build: prelease version 0.21.5 --- ...fix-image-background_2024-12-24-03-40.json | 10 ------- common/config/rush/pnpm-lock.yaml | 26 +++++++++---------- common/config/rush/version-policies.json | 2 +- docs/package.json | 2 +- packages/react-vrender-utils/CHANGELOG.json | 6 +++++ packages/react-vrender-utils/CHANGELOG.md | 7 ++++- packages/react-vrender-utils/package.json | 6 ++--- packages/react-vrender/CHANGELOG.json | 6 +++++ packages/react-vrender/CHANGELOG.md | 7 ++++- packages/react-vrender/package.json | 4 +-- packages/vrender-components/CHANGELOG.json | 6 +++++ packages/vrender-components/CHANGELOG.md | 7 ++++- packages/vrender-components/package.json | 6 ++--- packages/vrender-core/CHANGELOG.json | 12 +++++++++ packages/vrender-core/CHANGELOG.md | 9 ++++++- packages/vrender-core/package.json | 2 +- packages/vrender-kits/CHANGELOG.json | 6 +++++ packages/vrender-kits/CHANGELOG.md | 7 ++++- packages/vrender-kits/package.json | 4 +-- packages/vrender/CHANGELOG.json | 6 +++++ packages/vrender/CHANGELOG.md | 7 ++++- packages/vrender/package.json | 6 ++--- tools/bugserver-trigger/package.json | 8 +++--- 23 files changed, 113 insertions(+), 49 deletions(-) delete mode 100644 common/changes/@visactor/vrender-core/fix-image-background_2024-12-24-03-40.json diff --git a/common/changes/@visactor/vrender-core/fix-image-background_2024-12-24-03-40.json b/common/changes/@visactor/vrender-core/fix-image-background_2024-12-24-03-40.json deleted file mode 100644 index e8b1f67de..000000000 --- a/common/changes/@visactor/vrender-core/fix-image-background_2024-12-24-03-40.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vrender-core", - "comment": "fix: fix issue with image background stroke, closed #1640", - "type": "none" - } - ], - "packageName": "@visactor/vrender-core" -} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 7b410c21a..b69038d6a 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -14,7 +14,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vchart': 1.3.0 '@visactor/vgrammar': ~0.5.7 - '@visactor/vrender': workspace:0.21.4 + '@visactor/vrender': workspace:0.21.5 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 axios: ^1.4.0 @@ -71,7 +71,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@types/react-reconciler': ^0.28.2 - '@visactor/vrender': workspace:0.21.4 + '@visactor/vrender': workspace:0.21.5 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 @@ -111,8 +111,8 @@ importers: '@rushstack/eslint-patch': ~1.1.4 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/react-vrender': workspace:0.21.4 - '@visactor/vrender': workspace:0.21.4 + '@visactor/react-vrender': workspace:0.21.5 + '@visactor/vrender': workspace:0.21.5 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 @@ -153,8 +153,8 @@ importers: '@types/jest': ^26.0.0 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vrender-core': workspace:0.21.4 - '@visactor/vrender-kits': workspace:0.21.4 + '@visactor/vrender-core': workspace:0.21.5 + '@visactor/vrender-kits': workspace:0.21.5 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 @@ -200,8 +200,8 @@ importers: '@internal/ts-config': workspace:* '@rushstack/eslint-patch': ~1.1.4 '@types/jest': ^26.0.0 - '@visactor/vrender-core': workspace:0.21.4 - '@visactor/vrender-kits': workspace:0.21.4 + '@visactor/vrender-core': workspace:0.21.5 + '@visactor/vrender-kits': workspace:0.21.5 '@visactor/vscale': ~0.19.2 '@visactor/vutils': ~0.19.2 cross-env: ^7.0.3 @@ -287,7 +287,7 @@ importers: '@types/node-fetch': 2.6.4 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vrender-core': workspace:0.21.4 + '@visactor/vrender-core': workspace:0.21.5 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 @@ -369,10 +369,10 @@ importers: '@rushstack/eslint-patch': ~1.1.4 '@types/node': '*' '@types/node-fetch': 2.6.4 - '@visactor/vrender': workspace:0.21.4 - '@visactor/vrender-components': workspace:0.21.4 - '@visactor/vrender-core': workspace:0.21.4 - '@visactor/vrender-kits': workspace:0.21.4 + '@visactor/vrender': workspace:0.21.5 + '@visactor/vrender-components': workspace:0.21.5 + '@visactor/vrender-core': workspace:0.21.5 + '@visactor/vrender-kits': workspace:0.21.5 cross-env: ^7.0.3 eslint: ~8.18.0 form-data: ~4.0.0 diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json index 7f88b0965..88114a5db 100644 --- a/common/config/rush/version-policies.json +++ b/common/config/rush/version-policies.json @@ -1 +1 @@ -[{"definitionName":"lockStepVersion","policyName":"vrenderMain","version":"0.21.4","nextBump":"patch"}] +[{"definitionName":"lockStepVersion","policyName":"vrenderMain","version":"0.21.5","nextBump":"patch"}] diff --git a/docs/package.json b/docs/package.json index 572beefc9..4f83bec33 100644 --- a/docs/package.json +++ b/docs/package.json @@ -13,7 +13,7 @@ "@visactor/vchart": "1.3.0", "@visactor/vutils": "~0.19.2", "@visactor/vgrammar": "~0.5.7", - "@visactor/vrender": "workspace:0.21.4", + "@visactor/vrender": "workspace:0.21.5", "markdown-it": "^13.0.0", "highlight.js": "^11.8.0", "axios": "^1.4.0", diff --git a/packages/react-vrender-utils/CHANGELOG.json b/packages/react-vrender-utils/CHANGELOG.json index 076146ca6..93133638b 100644 --- a/packages/react-vrender-utils/CHANGELOG.json +++ b/packages/react-vrender-utils/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/react-vrender-utils", "entries": [ + { + "version": "0.21.5", + "tag": "@visactor/react-vrender-utils_v0.21.5", + "date": "Tue, 24 Dec 2024 07:53:11 GMT", + "comments": {} + }, { "version": "0.21.4", "tag": "@visactor/react-vrender-utils_v0.21.4", diff --git a/packages/react-vrender-utils/CHANGELOG.md b/packages/react-vrender-utils/CHANGELOG.md index 7578c992b..4d04e29eb 100644 --- a/packages/react-vrender-utils/CHANGELOG.md +++ b/packages/react-vrender-utils/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/react-vrender-utils -This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.5 +Tue, 24 Dec 2024 07:53:11 GMT + +_Version update only_ ## 0.21.4 Mon, 23 Dec 2024 10:16:00 GMT diff --git a/packages/react-vrender-utils/package.json b/packages/react-vrender-utils/package.json index f100bebaa..0b9e18757 100644 --- a/packages/react-vrender-utils/package.json +++ b/packages/react-vrender-utils/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vrender-utils", - "version": "0.21.4", + "version": "0.21.5", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -24,8 +24,8 @@ "react-dom": "^18.2.0" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.4", - "@visactor/react-vrender": "workspace:0.21.4", + "@visactor/vrender": "workspace:0.21.5", + "@visactor/react-vrender": "workspace:0.21.5", "@visactor/vutils": "~0.19.2", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" diff --git a/packages/react-vrender/CHANGELOG.json b/packages/react-vrender/CHANGELOG.json index 433e8a9c7..ee59616da 100644 --- a/packages/react-vrender/CHANGELOG.json +++ b/packages/react-vrender/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/react-vrender", "entries": [ + { + "version": "0.21.5", + "tag": "@visactor/react-vrender_v0.21.5", + "date": "Tue, 24 Dec 2024 07:53:11 GMT", + "comments": {} + }, { "version": "0.21.4", "tag": "@visactor/react-vrender_v0.21.4", diff --git a/packages/react-vrender/CHANGELOG.md b/packages/react-vrender/CHANGELOG.md index 593557f50..dd3eff19f 100644 --- a/packages/react-vrender/CHANGELOG.md +++ b/packages/react-vrender/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/react-vrender -This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.5 +Tue, 24 Dec 2024 07:53:11 GMT + +_Version update only_ ## 0.21.4 Mon, 23 Dec 2024 10:16:00 GMT diff --git a/packages/react-vrender/package.json b/packages/react-vrender/package.json index cb9a23a50..6a6b46280 100644 --- a/packages/react-vrender/package.json +++ b/packages/react-vrender/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vrender", - "version": "0.21.4", + "version": "0.21.5", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -23,7 +23,7 @@ "react": "^18.2.0" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.4", + "@visactor/vrender": "workspace:0.21.5", "@visactor/vutils": "~0.19.2", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" diff --git a/packages/vrender-components/CHANGELOG.json b/packages/vrender-components/CHANGELOG.json index 7047f6127..5cb287cd7 100644 --- a/packages/vrender-components/CHANGELOG.json +++ b/packages/vrender-components/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/vrender-components", "entries": [ + { + "version": "0.21.5", + "tag": "@visactor/vrender-components_v0.21.5", + "date": "Tue, 24 Dec 2024 07:53:11 GMT", + "comments": {} + }, { "version": "0.21.4", "tag": "@visactor/vrender-components_v0.21.4", diff --git a/packages/vrender-components/CHANGELOG.md b/packages/vrender-components/CHANGELOG.md index ba9de1304..d80d802d4 100644 --- a/packages/vrender-components/CHANGELOG.md +++ b/packages/vrender-components/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/vrender-components -This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.5 +Tue, 24 Dec 2024 07:53:11 GMT + +_Version update only_ ## 0.21.4 Mon, 23 Dec 2024 10:16:00 GMT diff --git a/packages/vrender-components/package.json b/packages/vrender-components/package.json index 1934f1e18..af0c95fa6 100644 --- a/packages/vrender-components/package.json +++ b/packages/vrender-components/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-components", - "version": "0.21.4", + "version": "0.21.5", "description": "components library for dp visualization", "sideEffects": false, "main": "cjs/index.js", @@ -27,8 +27,8 @@ "dependencies": { "@visactor/vutils": "~0.19.2", "@visactor/vscale": "~0.19.2", - "@visactor/vrender-core": "workspace:0.21.4", - "@visactor/vrender-kits": "workspace:0.21.4" + "@visactor/vrender-core": "workspace:0.21.5", + "@visactor/vrender-kits": "workspace:0.21.5" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/packages/vrender-core/CHANGELOG.json b/packages/vrender-core/CHANGELOG.json index e02bc7f58..5dec233a8 100644 --- a/packages/vrender-core/CHANGELOG.json +++ b/packages/vrender-core/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/vrender-core", "entries": [ + { + "version": "0.21.5", + "tag": "@visactor/vrender-core_v0.21.5", + "date": "Tue, 24 Dec 2024 07:53:11 GMT", + "comments": { + "none": [ + { + "comment": "fix: fix issue with image background stroke, closed #1640" + } + ] + } + }, { "version": "0.21.4", "tag": "@visactor/vrender-core_v0.21.4", diff --git a/packages/vrender-core/CHANGELOG.md b/packages/vrender-core/CHANGELOG.md index 7304a989f..1e98bfc1e 100644 --- a/packages/vrender-core/CHANGELOG.md +++ b/packages/vrender-core/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log - @visactor/vrender-core -This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.5 +Tue, 24 Dec 2024 07:53:11 GMT + +### Updates + +- fix: fix issue with image background stroke, closed #1640 ## 0.21.4 Mon, 23 Dec 2024 10:16:00 GMT diff --git a/packages/vrender-core/package.json b/packages/vrender-core/package.json index 087eb08b0..cc081151d 100644 --- a/packages/vrender-core/package.json +++ b/packages/vrender-core/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-core", - "version": "0.21.4", + "version": "0.21.5", "description": "", "sideEffects": [ "./src/modules.ts", diff --git a/packages/vrender-kits/CHANGELOG.json b/packages/vrender-kits/CHANGELOG.json index 8ce7ec4a9..82b69454e 100644 --- a/packages/vrender-kits/CHANGELOG.json +++ b/packages/vrender-kits/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/vrender-kits", "entries": [ + { + "version": "0.21.5", + "tag": "@visactor/vrender-kits_v0.21.5", + "date": "Tue, 24 Dec 2024 07:53:11 GMT", + "comments": {} + }, { "version": "0.21.4", "tag": "@visactor/vrender-kits_v0.21.4", diff --git a/packages/vrender-kits/CHANGELOG.md b/packages/vrender-kits/CHANGELOG.md index ea5e8af78..162c3e485 100644 --- a/packages/vrender-kits/CHANGELOG.md +++ b/packages/vrender-kits/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/vrender-kits -This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.5 +Tue, 24 Dec 2024 07:53:11 GMT + +_Version update only_ ## 0.21.4 Mon, 23 Dec 2024 10:16:00 GMT diff --git a/packages/vrender-kits/package.json b/packages/vrender-kits/package.json index eba43ba6d..5a05f137c 100644 --- a/packages/vrender-kits/package.json +++ b/packages/vrender-kits/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-kits", - "version": "0.21.4", + "version": "0.21.5", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -21,7 +21,7 @@ }, "dependencies": { "@visactor/vutils": "~0.19.2", - "@visactor/vrender-core": "workspace:0.21.4", + "@visactor/vrender-core": "workspace:0.21.5", "@resvg/resvg-js": "2.4.1", "roughjs": "4.5.2" }, diff --git a/packages/vrender/CHANGELOG.json b/packages/vrender/CHANGELOG.json index 3355ae114..6a166b8fe 100644 --- a/packages/vrender/CHANGELOG.json +++ b/packages/vrender/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/vrender", "entries": [ + { + "version": "0.21.5", + "tag": "@visactor/vrender_v0.21.5", + "date": "Tue, 24 Dec 2024 07:53:11 GMT", + "comments": {} + }, { "version": "0.21.4", "tag": "@visactor/vrender_v0.21.4", diff --git a/packages/vrender/CHANGELOG.md b/packages/vrender/CHANGELOG.md index 23b46f83f..7049f5a53 100644 --- a/packages/vrender/CHANGELOG.md +++ b/packages/vrender/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/vrender -This log was last generated on Mon, 23 Dec 2024 10:16:00 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 07:53:12 GMT and should not be manually modified. + +## 0.21.5 +Tue, 24 Dec 2024 07:53:11 GMT + +_Version update only_ ## 0.21.4 Mon, 23 Dec 2024 10:16:00 GMT diff --git a/packages/vrender/package.json b/packages/vrender/package.json index c6796ff01..3e70dc72c 100644 --- a/packages/vrender/package.json +++ b/packages/vrender/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender", - "version": "0.21.4", + "version": "0.21.5", "description": "", "sideEffects": true, "main": "cjs/index.js", @@ -24,8 +24,8 @@ "test-watch": "cross-env DEBUG_MODE=1 jest --watch" }, "dependencies": { - "@visactor/vrender-core": "workspace:0.21.4", - "@visactor/vrender-kits": "workspace:0.21.4" + "@visactor/vrender-core": "workspace:0.21.5", + "@visactor/vrender-kits": "workspace:0.21.5" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/tools/bugserver-trigger/package.json b/tools/bugserver-trigger/package.json index 5e8a3de38..81b2d53de 100644 --- a/tools/bugserver-trigger/package.json +++ b/tools/bugserver-trigger/package.json @@ -8,10 +8,10 @@ "ci": "ts-node --transpileOnly --skipProject ./scripts/trigger-test.ts" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.4", - "@visactor/vrender-core": "workspace:0.21.4", - "@visactor/vrender-kits": "workspace:0.21.4", - "@visactor/vrender-components": "workspace:0.21.4" + "@visactor/vrender": "workspace:0.21.5", + "@visactor/vrender-core": "workspace:0.21.5", + "@visactor/vrender-kits": "workspace:0.21.5", + "@visactor/vrender-components": "workspace:0.21.5" }, "devDependencies": { "@rushstack/eslint-patch": "~1.1.4", From c671a2aabb6447318654bb408fe3f1bd8681cfa2 Mon Sep 17 00:00:00 2001 From: xiaoluoHe Date: Tue, 24 Dec 2024 16:11:17 +0800 Subject: [PATCH 11/51] refactor: reuse util function --- .../vrender-components/src/crosshair/polygon-sector.ts | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/vrender-components/src/crosshair/polygon-sector.ts b/packages/vrender-components/src/crosshair/polygon-sector.ts index fbefdacc5..5aad7e924 100644 --- a/packages/vrender-components/src/crosshair/polygon-sector.ts +++ b/packages/vrender-components/src/crosshair/polygon-sector.ts @@ -9,6 +9,7 @@ import { CrosshairBase } from './base'; import type { PolygonSectorCrosshairAttrs } from './type'; import type { ComponentOptions } from '../interface'; import { loadPolygonSectorCrosshairComponent } from './register'; +import { getPolygonPath } from '../axis'; loadPolygonSectorCrosshairComponent(); export class PolygonSectorCrosshair extends CrosshairBase { @@ -32,17 +33,11 @@ export class PolygonSectorCrosshair extends CrosshairBase { - if (index === 0) { - return `M${cur.x},${cur.y}`; - } - return acc + `L${cur.x},${cur.y}`; - }, ''); const polygon = container.createOrUpdateChild( 'crosshair-polygon-sector', { - path, + path: getPolygonPath(points, true), ...polygonSectorStyle }, 'path' From 045778e74e8ac57f8e8db1de72be12d6b10509e6 Mon Sep 17 00:00:00 2001 From: neuqzxy Date: Tue, 24 Dec 2024 09:08:49 +0000 Subject: [PATCH 12/51] docs: generate changelog of release v0.21.5 --- docs/assets/changelog/en/changelog.md | 13 +++++++++++++ docs/assets/changelog/zh/changelog.md | 13 +++++++++++++ 2 files changed, 26 insertions(+) diff --git a/docs/assets/changelog/en/changelog.md b/docs/assets/changelog/en/changelog.md index 553a897db..5466e3a06 100644 --- a/docs/assets/changelog/en/changelog.md +++ b/docs/assets/changelog/en/changelog.md @@ -1,3 +1,16 @@ +# v0.21.5 + +2024-12-24 + + +**🐛 Bug fix** + +- **@visactor/vrender-core**: fix issue with image background stroke, closed [#1640](https://github.com/VisActor/VRender/issues/1640) + + + +[more detail about v0.21.5](https://github.com/VisActor/VRender/releases/tag/v0.21.5) + # v0.21.4 2024-12-23 diff --git a/docs/assets/changelog/zh/changelog.md b/docs/assets/changelog/zh/changelog.md index 737084441..54beae205 100644 --- a/docs/assets/changelog/zh/changelog.md +++ b/docs/assets/changelog/zh/changelog.md @@ -1,3 +1,16 @@ +# v0.21.5 + +2024-12-24 + + +**🐛 功能修复** + +- **@visactor/vrender-core**: fix issue with image background stroke, closed [#1640](https://github.com/VisActor/VRender/issues/1640) + + + +[更多详情请查看 v0.21.5](https://github.com/VisActor/VRender/releases/tag/v0.21.5) + # v0.21.4 2024-12-23 From 55637a84c01f7af8f4b64ccdfc8cd7215a257c03 Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Tue, 24 Dec 2024 18:55:56 +0800 Subject: [PATCH 13/51] fix: fix the bug of axis pickable --- packages/vrender-components/src/axis/base.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/vrender-components/src/axis/base.ts b/packages/vrender-components/src/axis/base.ts index 9fc851f29..b5ee44b79 100644 --- a/packages/vrender-components/src/axis/base.ts +++ b/packages/vrender-components/src/axis/base.ts @@ -135,6 +135,7 @@ export abstract class AxisBase extends AbstractCom this.add(this._innerView); this._renderInner(this._innerView); + this.setAttribute('pickable', false); this._bindEvent(); } From 48f34dabb74dc4c3f620c0b5529a2d957132cf54 Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Tue, 24 Dec 2024 19:21:36 +0800 Subject: [PATCH 14/51] docs: update changlog of rush --- .../fix-fix-bug-of-axis-pick_2024-12-24-11-21.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vrender-components/fix-fix-bug-of-axis-pick_2024-12-24-11-21.json diff --git a/common/changes/@visactor/vrender-components/fix-fix-bug-of-axis-pick_2024-12-24-11-21.json b/common/changes/@visactor/vrender-components/fix-fix-bug-of-axis-pick_2024-12-24-11-21.json new file mode 100644 index 000000000..c47e2b2e9 --- /dev/null +++ b/common/changes/@visactor/vrender-components/fix-fix-bug-of-axis-pick_2024-12-24-11-21.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: fix the bug of axis pickable\n\n", + "type": "none", + "packageName": "@visactor/vrender-components" + } + ], + "packageName": "@visactor/vrender-components", + "email": "lixuef1313@163.com" +} \ No newline at end of file From 47813929290ec1e597acec40f891d9d182e9b783 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 24 Dec 2024 18:34:37 +0800 Subject: [PATCH 15/51] fix: fix issue with stroke clip --- ...ix-image-stroke-clip_2024-12-24-12-00.json | 10 ++++++++ .../contributions/render/image-render.ts | 24 ++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) create mode 100644 common/changes/@visactor/vrender-core/fix-image-stroke-clip_2024-12-24-12-00.json diff --git a/common/changes/@visactor/vrender-core/fix-image-stroke-clip_2024-12-24-12-00.json b/common/changes/@visactor/vrender-core/fix-image-stroke-clip_2024-12-24-12-00.json new file mode 100644 index 000000000..d195117c9 --- /dev/null +++ b/common/changes/@visactor/vrender-core/fix-image-stroke-clip_2024-12-24-12-00.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-core", + "comment": "fix: fix issue with stroke clip", + "type": "none" + } + ], + "packageName": "@visactor/vrender-core" +} \ No newline at end of file diff --git a/packages/vrender-core/src/render/contributions/render/image-render.ts b/packages/vrender-core/src/render/contributions/render/image-render.ts index 7155d0cbf..9ba01bdce 100644 --- a/packages/vrender-core/src/render/contributions/render/image-render.ts +++ b/packages/vrender-core/src/render/contributions/render/image-render.ts @@ -95,13 +95,9 @@ export class DefaultCanvasImageRender extends BaseRender implements IGra } else { context.beginPath(); createRectPath(context, x, y, width, height, cornerRadius); - context.save(); - context.clip(); needRestore = true; } - this.beforeRenderStep(image, context, x, y, doFill, false, fVisible, false, imageAttribute, drawContext, fillCb); - // shadow context.setShadowBlendStyle && context.setShadowBlendStyle(image, image.attribute, imageAttribute); // context.beginPath(); @@ -145,18 +141,30 @@ export class DefaultCanvasImageRender extends BaseRender implements IGra }; if (!fillStrokeOrder) { + if (needRestore) { + context.save(); + context.clip(); + } + this.beforeRenderStep(image, context, x, y, doFill, false, fVisible, false, imageAttribute, drawContext, fillCb); _runFill(); + if (needRestore) { + context.restore(); + } _runStroke(); } else { _runStroke(); + if (needRestore) { + context.save(); + context.clip(); + } + this.beforeRenderStep(image, context, x, y, doFill, false, fVisible, false, imageAttribute, drawContext, fillCb); _runFill(); + if (needRestore) { + context.restore(); + } } this.afterRenderStep(image, context, x, y, doFill, false, fVisible, false, imageAttribute, drawContext, fillCb); - - if (needRestore) { - context.restore(); - } } draw(image: IImage, renderService: IRenderService, drawContext: IDrawContext) { From 3f648cd9dd91b0ddb61580bfaf2a7245d89b327f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Tue, 24 Dec 2024 12:51:53 +0000 Subject: [PATCH 16/51] build: prelease version 0.21.6 --- ...eforeAttributeUpdate_2024-12-18-11-28.json | 10 ------- ...fix-bug-of-axis-pick_2024-12-24-11-21.json | 11 -------- ...ix-image-stroke-clip_2024-12-24-12-00.json | 10 ------- common/config/rush/pnpm-lock.yaml | 26 +++++++++---------- common/config/rush/version-policies.json | 2 +- docs/package.json | 2 +- packages/react-vrender-utils/CHANGELOG.json | 6 +++++ packages/react-vrender-utils/CHANGELOG.md | 7 ++++- packages/react-vrender-utils/package.json | 6 ++--- packages/react-vrender/CHANGELOG.json | 6 +++++ packages/react-vrender/CHANGELOG.md | 7 ++++- packages/react-vrender/package.json | 4 +-- packages/vrender-components/CHANGELOG.json | 15 +++++++++++ packages/vrender-components/CHANGELOG.md | 12 ++++++++- packages/vrender-components/package.json | 6 ++--- packages/vrender-core/CHANGELOG.json | 12 +++++++++ packages/vrender-core/CHANGELOG.md | 9 ++++++- packages/vrender-core/package.json | 2 +- packages/vrender-kits/CHANGELOG.json | 6 +++++ packages/vrender-kits/CHANGELOG.md | 7 ++++- packages/vrender-kits/package.json | 4 +-- packages/vrender/CHANGELOG.json | 6 +++++ packages/vrender/CHANGELOG.md | 7 ++++- packages/vrender/package.json | 6 ++--- tools/bugserver-trigger/package.json | 8 +++--- 25 files changed, 127 insertions(+), 70 deletions(-) delete mode 100644 common/changes/@visactor/vrender-components/fix-base-onBeforeAttributeUpdate_2024-12-18-11-28.json delete mode 100644 common/changes/@visactor/vrender-components/fix-fix-bug-of-axis-pick_2024-12-24-11-21.json delete mode 100644 common/changes/@visactor/vrender-core/fix-image-stroke-clip_2024-12-24-12-00.json diff --git a/common/changes/@visactor/vrender-components/fix-base-onBeforeAttributeUpdate_2024-12-18-11-28.json b/common/changes/@visactor/vrender-components/fix-base-onBeforeAttributeUpdate_2024-12-18-11-28.json deleted file mode 100644 index aecfde658..000000000 --- a/common/changes/@visactor/vrender-components/fix-base-onBeforeAttributeUpdate_2024-12-18-11-28.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vrender-components", - "comment": "fix: add onBeforeAttributeUpdate in base-component", - "type": "none" - } - ], - "packageName": "@visactor/vrender-components" -} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-components/fix-fix-bug-of-axis-pick_2024-12-24-11-21.json b/common/changes/@visactor/vrender-components/fix-fix-bug-of-axis-pick_2024-12-24-11-21.json deleted file mode 100644 index c47e2b2e9..000000000 --- a/common/changes/@visactor/vrender-components/fix-fix-bug-of-axis-pick_2024-12-24-11-21.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: fix the bug of axis pickable\n\n", - "type": "none", - "packageName": "@visactor/vrender-components" - } - ], - "packageName": "@visactor/vrender-components", - "email": "lixuef1313@163.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-core/fix-image-stroke-clip_2024-12-24-12-00.json b/common/changes/@visactor/vrender-core/fix-image-stroke-clip_2024-12-24-12-00.json deleted file mode 100644 index d195117c9..000000000 --- a/common/changes/@visactor/vrender-core/fix-image-stroke-clip_2024-12-24-12-00.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vrender-core", - "comment": "fix: fix issue with stroke clip", - "type": "none" - } - ], - "packageName": "@visactor/vrender-core" -} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index b69038d6a..a9adf97bb 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -14,7 +14,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vchart': 1.3.0 '@visactor/vgrammar': ~0.5.7 - '@visactor/vrender': workspace:0.21.5 + '@visactor/vrender': workspace:0.21.6 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 axios: ^1.4.0 @@ -71,7 +71,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@types/react-reconciler': ^0.28.2 - '@visactor/vrender': workspace:0.21.5 + '@visactor/vrender': workspace:0.21.6 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 @@ -111,8 +111,8 @@ importers: '@rushstack/eslint-patch': ~1.1.4 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/react-vrender': workspace:0.21.5 - '@visactor/vrender': workspace:0.21.5 + '@visactor/react-vrender': workspace:0.21.6 + '@visactor/vrender': workspace:0.21.6 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 @@ -153,8 +153,8 @@ importers: '@types/jest': ^26.0.0 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vrender-core': workspace:0.21.5 - '@visactor/vrender-kits': workspace:0.21.5 + '@visactor/vrender-core': workspace:0.21.6 + '@visactor/vrender-kits': workspace:0.21.6 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 @@ -200,8 +200,8 @@ importers: '@internal/ts-config': workspace:* '@rushstack/eslint-patch': ~1.1.4 '@types/jest': ^26.0.0 - '@visactor/vrender-core': workspace:0.21.5 - '@visactor/vrender-kits': workspace:0.21.5 + '@visactor/vrender-core': workspace:0.21.6 + '@visactor/vrender-kits': workspace:0.21.6 '@visactor/vscale': ~0.19.2 '@visactor/vutils': ~0.19.2 cross-env: ^7.0.3 @@ -287,7 +287,7 @@ importers: '@types/node-fetch': 2.6.4 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vrender-core': workspace:0.21.5 + '@visactor/vrender-core': workspace:0.21.6 '@visactor/vutils': ~0.19.2 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 @@ -369,10 +369,10 @@ importers: '@rushstack/eslint-patch': ~1.1.4 '@types/node': '*' '@types/node-fetch': 2.6.4 - '@visactor/vrender': workspace:0.21.5 - '@visactor/vrender-components': workspace:0.21.5 - '@visactor/vrender-core': workspace:0.21.5 - '@visactor/vrender-kits': workspace:0.21.5 + '@visactor/vrender': workspace:0.21.6 + '@visactor/vrender-components': workspace:0.21.6 + '@visactor/vrender-core': workspace:0.21.6 + '@visactor/vrender-kits': workspace:0.21.6 cross-env: ^7.0.3 eslint: ~8.18.0 form-data: ~4.0.0 diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json index 88114a5db..9c89f9811 100644 --- a/common/config/rush/version-policies.json +++ b/common/config/rush/version-policies.json @@ -1 +1 @@ -[{"definitionName":"lockStepVersion","policyName":"vrenderMain","version":"0.21.5","nextBump":"patch"}] +[{"definitionName":"lockStepVersion","policyName":"vrenderMain","version":"0.21.6","nextBump":"patch"}] diff --git a/docs/package.json b/docs/package.json index 4f83bec33..c9c7a31b8 100644 --- a/docs/package.json +++ b/docs/package.json @@ -13,7 +13,7 @@ "@visactor/vchart": "1.3.0", "@visactor/vutils": "~0.19.2", "@visactor/vgrammar": "~0.5.7", - "@visactor/vrender": "workspace:0.21.5", + "@visactor/vrender": "workspace:0.21.6", "markdown-it": "^13.0.0", "highlight.js": "^11.8.0", "axios": "^1.4.0", diff --git a/packages/react-vrender-utils/CHANGELOG.json b/packages/react-vrender-utils/CHANGELOG.json index 93133638b..746010a61 100644 --- a/packages/react-vrender-utils/CHANGELOG.json +++ b/packages/react-vrender-utils/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/react-vrender-utils", "entries": [ + { + "version": "0.21.6", + "tag": "@visactor/react-vrender-utils_v0.21.6", + "date": "Tue, 24 Dec 2024 12:46:37 GMT", + "comments": {} + }, { "version": "0.21.5", "tag": "@visactor/react-vrender-utils_v0.21.5", diff --git a/packages/react-vrender-utils/CHANGELOG.md b/packages/react-vrender-utils/CHANGELOG.md index 4d04e29eb..50c175b78 100644 --- a/packages/react-vrender-utils/CHANGELOG.md +++ b/packages/react-vrender-utils/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/react-vrender-utils -This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. + +## 0.21.6 +Tue, 24 Dec 2024 12:46:37 GMT + +_Version update only_ ## 0.21.5 Tue, 24 Dec 2024 07:53:11 GMT diff --git a/packages/react-vrender-utils/package.json b/packages/react-vrender-utils/package.json index 0b9e18757..e58c94a50 100644 --- a/packages/react-vrender-utils/package.json +++ b/packages/react-vrender-utils/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vrender-utils", - "version": "0.21.5", + "version": "0.21.6", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -24,8 +24,8 @@ "react-dom": "^18.2.0" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.5", - "@visactor/react-vrender": "workspace:0.21.5", + "@visactor/vrender": "workspace:0.21.6", + "@visactor/react-vrender": "workspace:0.21.6", "@visactor/vutils": "~0.19.2", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" diff --git a/packages/react-vrender/CHANGELOG.json b/packages/react-vrender/CHANGELOG.json index ee59616da..bd0a4ff47 100644 --- a/packages/react-vrender/CHANGELOG.json +++ b/packages/react-vrender/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/react-vrender", "entries": [ + { + "version": "0.21.6", + "tag": "@visactor/react-vrender_v0.21.6", + "date": "Tue, 24 Dec 2024 12:46:37 GMT", + "comments": {} + }, { "version": "0.21.5", "tag": "@visactor/react-vrender_v0.21.5", diff --git a/packages/react-vrender/CHANGELOG.md b/packages/react-vrender/CHANGELOG.md index dd3eff19f..487b52673 100644 --- a/packages/react-vrender/CHANGELOG.md +++ b/packages/react-vrender/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/react-vrender -This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. + +## 0.21.6 +Tue, 24 Dec 2024 12:46:37 GMT + +_Version update only_ ## 0.21.5 Tue, 24 Dec 2024 07:53:11 GMT diff --git a/packages/react-vrender/package.json b/packages/react-vrender/package.json index 6a6b46280..7e599888a 100644 --- a/packages/react-vrender/package.json +++ b/packages/react-vrender/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vrender", - "version": "0.21.5", + "version": "0.21.6", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -23,7 +23,7 @@ "react": "^18.2.0" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.5", + "@visactor/vrender": "workspace:0.21.6", "@visactor/vutils": "~0.19.2", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" diff --git a/packages/vrender-components/CHANGELOG.json b/packages/vrender-components/CHANGELOG.json index 5cb287cd7..f960c19e9 100644 --- a/packages/vrender-components/CHANGELOG.json +++ b/packages/vrender-components/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@visactor/vrender-components", "entries": [ + { + "version": "0.21.6", + "tag": "@visactor/vrender-components_v0.21.6", + "date": "Tue, 24 Dec 2024 12:46:37 GMT", + "comments": { + "none": [ + { + "comment": "fix: add onBeforeAttributeUpdate in base-component" + }, + { + "comment": "fix: fix the bug of axis pickable\n\n" + } + ] + } + }, { "version": "0.21.5", "tag": "@visactor/vrender-components_v0.21.5", diff --git a/packages/vrender-components/CHANGELOG.md b/packages/vrender-components/CHANGELOG.md index d80d802d4..ed4bbeaf8 100644 --- a/packages/vrender-components/CHANGELOG.md +++ b/packages/vrender-components/CHANGELOG.md @@ -1,6 +1,16 @@ # Change Log - @visactor/vrender-components -This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. + +## 0.21.6 +Tue, 24 Dec 2024 12:46:37 GMT + +### Updates + +- fix: add onBeforeAttributeUpdate in base-component +- fix: fix the bug of axis pickable + + ## 0.21.5 Tue, 24 Dec 2024 07:53:11 GMT diff --git a/packages/vrender-components/package.json b/packages/vrender-components/package.json index af0c95fa6..f7805de42 100644 --- a/packages/vrender-components/package.json +++ b/packages/vrender-components/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-components", - "version": "0.21.5", + "version": "0.21.6", "description": "components library for dp visualization", "sideEffects": false, "main": "cjs/index.js", @@ -27,8 +27,8 @@ "dependencies": { "@visactor/vutils": "~0.19.2", "@visactor/vscale": "~0.19.2", - "@visactor/vrender-core": "workspace:0.21.5", - "@visactor/vrender-kits": "workspace:0.21.5" + "@visactor/vrender-core": "workspace:0.21.6", + "@visactor/vrender-kits": "workspace:0.21.6" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/packages/vrender-core/CHANGELOG.json b/packages/vrender-core/CHANGELOG.json index 5dec233a8..224344a51 100644 --- a/packages/vrender-core/CHANGELOG.json +++ b/packages/vrender-core/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/vrender-core", "entries": [ + { + "version": "0.21.6", + "tag": "@visactor/vrender-core_v0.21.6", + "date": "Tue, 24 Dec 2024 12:46:37 GMT", + "comments": { + "none": [ + { + "comment": "fix: fix issue with stroke clip" + } + ] + } + }, { "version": "0.21.5", "tag": "@visactor/vrender-core_v0.21.5", diff --git a/packages/vrender-core/CHANGELOG.md b/packages/vrender-core/CHANGELOG.md index 1e98bfc1e..89415ce88 100644 --- a/packages/vrender-core/CHANGELOG.md +++ b/packages/vrender-core/CHANGELOG.md @@ -1,6 +1,13 @@ # Change Log - @visactor/vrender-core -This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. + +## 0.21.6 +Tue, 24 Dec 2024 12:46:37 GMT + +### Updates + +- fix: fix issue with stroke clip ## 0.21.5 Tue, 24 Dec 2024 07:53:11 GMT diff --git a/packages/vrender-core/package.json b/packages/vrender-core/package.json index cc081151d..08b52d78d 100644 --- a/packages/vrender-core/package.json +++ b/packages/vrender-core/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-core", - "version": "0.21.5", + "version": "0.21.6", "description": "", "sideEffects": [ "./src/modules.ts", diff --git a/packages/vrender-kits/CHANGELOG.json b/packages/vrender-kits/CHANGELOG.json index 82b69454e..cf129dc91 100644 --- a/packages/vrender-kits/CHANGELOG.json +++ b/packages/vrender-kits/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/vrender-kits", "entries": [ + { + "version": "0.21.6", + "tag": "@visactor/vrender-kits_v0.21.6", + "date": "Tue, 24 Dec 2024 12:46:37 GMT", + "comments": {} + }, { "version": "0.21.5", "tag": "@visactor/vrender-kits_v0.21.5", diff --git a/packages/vrender-kits/CHANGELOG.md b/packages/vrender-kits/CHANGELOG.md index 162c3e485..b8d6660c9 100644 --- a/packages/vrender-kits/CHANGELOG.md +++ b/packages/vrender-kits/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/vrender-kits -This log was last generated on Tue, 24 Dec 2024 07:53:11 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. + +## 0.21.6 +Tue, 24 Dec 2024 12:46:37 GMT + +_Version update only_ ## 0.21.5 Tue, 24 Dec 2024 07:53:11 GMT diff --git a/packages/vrender-kits/package.json b/packages/vrender-kits/package.json index 5a05f137c..4144b1449 100644 --- a/packages/vrender-kits/package.json +++ b/packages/vrender-kits/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-kits", - "version": "0.21.5", + "version": "0.21.6", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -21,7 +21,7 @@ }, "dependencies": { "@visactor/vutils": "~0.19.2", - "@visactor/vrender-core": "workspace:0.21.5", + "@visactor/vrender-core": "workspace:0.21.6", "@resvg/resvg-js": "2.4.1", "roughjs": "4.5.2" }, diff --git a/packages/vrender/CHANGELOG.json b/packages/vrender/CHANGELOG.json index 6a166b8fe..6e72aeb5b 100644 --- a/packages/vrender/CHANGELOG.json +++ b/packages/vrender/CHANGELOG.json @@ -1,6 +1,12 @@ { "name": "@visactor/vrender", "entries": [ + { + "version": "0.21.6", + "tag": "@visactor/vrender_v0.21.6", + "date": "Tue, 24 Dec 2024 12:46:37 GMT", + "comments": {} + }, { "version": "0.21.5", "tag": "@visactor/vrender_v0.21.5", diff --git a/packages/vrender/CHANGELOG.md b/packages/vrender/CHANGELOG.md index 7049f5a53..734c45c6e 100644 --- a/packages/vrender/CHANGELOG.md +++ b/packages/vrender/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log - @visactor/vrender -This log was last generated on Tue, 24 Dec 2024 07:53:12 GMT and should not be manually modified. +This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. + +## 0.21.6 +Tue, 24 Dec 2024 12:46:37 GMT + +_Version update only_ ## 0.21.5 Tue, 24 Dec 2024 07:53:11 GMT diff --git a/packages/vrender/package.json b/packages/vrender/package.json index 3e70dc72c..485429c80 100644 --- a/packages/vrender/package.json +++ b/packages/vrender/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender", - "version": "0.21.5", + "version": "0.21.6", "description": "", "sideEffects": true, "main": "cjs/index.js", @@ -24,8 +24,8 @@ "test-watch": "cross-env DEBUG_MODE=1 jest --watch" }, "dependencies": { - "@visactor/vrender-core": "workspace:0.21.5", - "@visactor/vrender-kits": "workspace:0.21.5" + "@visactor/vrender-core": "workspace:0.21.6", + "@visactor/vrender-kits": "workspace:0.21.6" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/tools/bugserver-trigger/package.json b/tools/bugserver-trigger/package.json index 81b2d53de..f2ac8cf55 100644 --- a/tools/bugserver-trigger/package.json +++ b/tools/bugserver-trigger/package.json @@ -8,10 +8,10 @@ "ci": "ts-node --transpileOnly --skipProject ./scripts/trigger-test.ts" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.5", - "@visactor/vrender-core": "workspace:0.21.5", - "@visactor/vrender-kits": "workspace:0.21.5", - "@visactor/vrender-components": "workspace:0.21.5" + "@visactor/vrender": "workspace:0.21.6", + "@visactor/vrender-core": "workspace:0.21.6", + "@visactor/vrender-kits": "workspace:0.21.6", + "@visactor/vrender-components": "workspace:0.21.6" }, "devDependencies": { "@rushstack/eslint-patch": "~1.1.4", From 19a010526d755136f688dec901610f47bfe91dab Mon Sep 17 00:00:00 2001 From: neuqzxy Date: Wed, 25 Dec 2024 02:41:08 +0000 Subject: [PATCH 17/51] docs: generate changelog of release v0.21.6 --- docs/assets/changelog/en/changelog.md | 15 +++++++++++++++ docs/assets/changelog/zh/changelog.md | 15 +++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/docs/assets/changelog/en/changelog.md b/docs/assets/changelog/en/changelog.md index 5466e3a06..a73554114 100644 --- a/docs/assets/changelog/en/changelog.md +++ b/docs/assets/changelog/en/changelog.md @@ -1,3 +1,18 @@ +# v0.21.6 + +2024-12-25 + + +**🐛 Bug fix** + +- **@visactor/vrender-components**: add onBeforeAttributeUpdate in base-component +- **@visactor/vrender-components**: fix the bug of axis pickable +- **@visactor/vrender-core**: fix issue with stroke clip + + + +[more detail about v0.21.6](https://github.com/VisActor/VRender/releases/tag/v0.21.6) + # v0.21.5 2024-12-24 diff --git a/docs/assets/changelog/zh/changelog.md b/docs/assets/changelog/zh/changelog.md index 54beae205..4d413bc94 100644 --- a/docs/assets/changelog/zh/changelog.md +++ b/docs/assets/changelog/zh/changelog.md @@ -1,3 +1,18 @@ +# v0.21.6 + +2024-12-25 + + +**🐛 功能修复** + +- **@visactor/vrender-components**: add onBeforeAttributeUpdate in base-component +- **@visactor/vrender-components**: fix the bug of axis pickable +- **@visactor/vrender-core**: fix issue with stroke clip + + + +[更多详情请查看 v0.21.6](https://github.com/VisActor/VRender/releases/tag/v0.21.6) + # v0.21.5 2024-12-24 From f76c91afd70740a9d2eef2caef79832569d167f9 Mon Sep 17 00:00:00 2001 From: xile611 Date: Wed, 25 Dec 2024 11:13:23 +0800 Subject: [PATCH 18/51] fix: upgrade vutils to 0.19.3 --- docs/demos/package.json | 2 +- docs/package.json | 2 +- packages/react-vrender-utils/package.json | 2 +- packages/react-vrender/package.json | 2 +- packages/vrender-components/package.json | 6 +++--- packages/vrender-core/package.json | 2 +- packages/vrender-kits/package.json | 2 +- packages/vrender/package.json | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/demos/package.json b/docs/demos/package.json index d7e382216..cb21b2bd3 100644 --- a/docs/demos/package.json +++ b/docs/demos/package.json @@ -12,7 +12,7 @@ "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", "@visactor/vrender-kits": "workspace:0.14.8", - "@visactor/vutils": "~0.19.2", + "@visactor/vutils": "~0.19.3", "d3-scale-chromatic": "^3.0.0", "lodash": "4.17.21", "dat.gui": "^0.7.9", diff --git a/docs/package.json b/docs/package.json index c9c7a31b8..6b7fe1344 100644 --- a/docs/package.json +++ b/docs/package.json @@ -11,7 +11,7 @@ "dependencies": { "@arco-design/web-react": "2.46.1", "@visactor/vchart": "1.3.0", - "@visactor/vutils": "~0.19.2", + "@visactor/vutils": "~0.19.3", "@visactor/vgrammar": "~0.5.7", "@visactor/vrender": "workspace:0.21.6", "markdown-it": "^13.0.0", diff --git a/packages/react-vrender-utils/package.json b/packages/react-vrender-utils/package.json index e58c94a50..ba5cab75e 100644 --- a/packages/react-vrender-utils/package.json +++ b/packages/react-vrender-utils/package.json @@ -26,7 +26,7 @@ "dependencies": { "@visactor/vrender": "workspace:0.21.6", "@visactor/react-vrender": "workspace:0.21.6", - "@visactor/vutils": "~0.19.2", + "@visactor/vutils": "~0.19.3", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" }, diff --git a/packages/react-vrender/package.json b/packages/react-vrender/package.json index 7e599888a..65e231547 100644 --- a/packages/react-vrender/package.json +++ b/packages/react-vrender/package.json @@ -24,7 +24,7 @@ }, "dependencies": { "@visactor/vrender": "workspace:0.21.6", - "@visactor/vutils": "~0.19.2", + "@visactor/vutils": "~0.19.3", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" }, diff --git a/packages/vrender-components/package.json b/packages/vrender-components/package.json index f7805de42..0a0bcc2cf 100644 --- a/packages/vrender-components/package.json +++ b/packages/vrender-components/package.json @@ -25,8 +25,8 @@ "build:spec-types": "rm -rf ./spec-types && tsc -p ./tsconfig.spec.json --declaration --emitDeclarationOnly --outDir ./spec-types" }, "dependencies": { - "@visactor/vutils": "~0.19.2", - "@visactor/vscale": "~0.19.2", + "@visactor/vutils": "~0.19.3", + "@visactor/vscale": "~0.19.3", "@visactor/vrender-core": "workspace:0.21.6", "@visactor/vrender-kits": "workspace:0.21.6" }, @@ -35,7 +35,7 @@ "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", "@rushstack/eslint-patch": "~1.1.4", - "@visactor/vscale": "~0.19.2", + "@visactor/vscale": "~0.19.3", "@types/jest": "^26.0.0", "jest": "^26.0.0", "jest-electron": "^0.1.12", diff --git a/packages/vrender-core/package.json b/packages/vrender-core/package.json index 08b52d78d..56a7eb4f7 100644 --- a/packages/vrender-core/package.json +++ b/packages/vrender-core/package.json @@ -30,7 +30,7 @@ }, "dependencies": { "color-convert": "2.0.1", - "@visactor/vutils": "~0.19.2" + "@visactor/vutils": "~0.19.3" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/packages/vrender-kits/package.json b/packages/vrender-kits/package.json index 4144b1449..3f3561c81 100644 --- a/packages/vrender-kits/package.json +++ b/packages/vrender-kits/package.json @@ -20,7 +20,7 @@ "test": "" }, "dependencies": { - "@visactor/vutils": "~0.19.2", + "@visactor/vutils": "~0.19.3", "@visactor/vrender-core": "workspace:0.21.6", "@resvg/resvg-js": "2.4.1", "roughjs": "4.5.2" diff --git a/packages/vrender/package.json b/packages/vrender/package.json index 485429c80..245b47a08 100644 --- a/packages/vrender/package.json +++ b/packages/vrender/package.json @@ -32,7 +32,7 @@ "@internal/eslint-config": "workspace:*", "@internal/ts-config": "workspace:*", "@rushstack/eslint-patch": "~1.1.4", - "@visactor/vutils": "~0.19.2", + "@visactor/vutils": "~0.19.3", "canvas": "2.11.2", "react": "^18.0.0", "react-dom": "^18.0.0", From 4ab5e820847533fffa14fbb1b11ff0488c2ff66e Mon Sep 17 00:00:00 2001 From: xile611 Date: Wed, 25 Dec 2024 11:23:48 +0800 Subject: [PATCH 19/51] docs: update changlog of rush --- .../fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 +++++++++++ .../fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 +++++++++++ .../fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 +++++++++++ .../fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 +++++++++++ .../fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 +++++++++++ .../fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 +++++++++++ 6 files changed, 66 insertions(+) create mode 100644 common/changes/@visactor/react-vrender-utils/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json create mode 100644 common/changes/@visactor/react-vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json create mode 100644 common/changes/@visactor/vrender-components/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json create mode 100644 common/changes/@visactor/vrender-core/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json create mode 100644 common/changes/@visactor/vrender-kits/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json create mode 100644 common/changes/@visactor/vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json diff --git a/common/changes/@visactor/react-vrender-utils/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/react-vrender-utils/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json new file mode 100644 index 000000000..2aff236b0 --- /dev/null +++ b/common/changes/@visactor/react-vrender-utils/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n", + "type": "none", + "packageName": "@visactor/react-vrender-utils" + } + ], + "packageName": "@visactor/react-vrender-utils", + "email": "dingling112@gmail.com" +} \ No newline at end of file diff --git a/common/changes/@visactor/react-vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/react-vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json new file mode 100644 index 000000000..9066cf7bd --- /dev/null +++ b/common/changes/@visactor/react-vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n", + "type": "none", + "packageName": "@visactor/react-vrender" + } + ], + "packageName": "@visactor/react-vrender", + "email": "dingling112@gmail.com" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-components/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/vrender-components/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json new file mode 100644 index 000000000..09bc1749e --- /dev/null +++ b/common/changes/@visactor/vrender-components/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n", + "type": "none", + "packageName": "@visactor/vrender-components" + } + ], + "packageName": "@visactor/vrender-components", + "email": "dingling112@gmail.com" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-core/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/vrender-core/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json new file mode 100644 index 000000000..98246981a --- /dev/null +++ b/common/changes/@visactor/vrender-core/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n", + "type": "none", + "packageName": "@visactor/vrender-core" + } + ], + "packageName": "@visactor/vrender-core", + "email": "dingling112@gmail.com" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-kits/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/vrender-kits/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json new file mode 100644 index 000000000..2474170fb --- /dev/null +++ b/common/changes/@visactor/vrender-kits/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n", + "type": "none", + "packageName": "@visactor/vrender-kits" + } + ], + "packageName": "@visactor/vrender-kits", + "email": "dingling112@gmail.com" +} \ No newline at end of file diff --git a/common/changes/@visactor/vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json new file mode 100644 index 000000000..0f2de2b8a --- /dev/null +++ b/common/changes/@visactor/vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n", + "type": "none", + "packageName": "@visactor/vrender" + } + ], + "packageName": "@visactor/vrender", + "email": "dingling112@gmail.com" +} \ No newline at end of file From 8607671d58916b09c69759a7e836d1e1cf8aac7e Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Wed, 25 Dec 2024 11:23:52 +0800 Subject: [PATCH 20/51] Revert "fix: fix the bug of axis pickable" This reverts commit 55637a84c01f7af8f4b64ccdfc8cd7215a257c03. --- packages/vrender-components/src/axis/base.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/vrender-components/src/axis/base.ts b/packages/vrender-components/src/axis/base.ts index 0293486b6..963a541ff 100644 --- a/packages/vrender-components/src/axis/base.ts +++ b/packages/vrender-components/src/axis/base.ts @@ -135,7 +135,6 @@ export abstract class AxisBase extends AbstractCom this.add(this._innerView); this._renderInner(this._innerView); - this.setAttribute('pickable', false); this._bindEvent(); } From 0ac69c3ea18772856027d5cb9f5f526152fb44fe Mon Sep 17 00:00:00 2001 From: "lixuefei.1313" Date: Wed, 25 Dec 2024 11:24:03 +0800 Subject: [PATCH 21/51] docs: update changlog of rush --- .../fix-revert-axis-pickable_2024-12-25-03-24.json | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 common/changes/@visactor/vrender-components/fix-revert-axis-pickable_2024-12-25-03-24.json diff --git a/common/changes/@visactor/vrender-components/fix-revert-axis-pickable_2024-12-25-03-24.json b/common/changes/@visactor/vrender-components/fix-revert-axis-pickable_2024-12-25-03-24.json new file mode 100644 index 000000000..1091fd7e9 --- /dev/null +++ b/common/changes/@visactor/vrender-components/fix-revert-axis-pickable_2024-12-25-03-24.json @@ -0,0 +1,11 @@ +{ + "changes": [ + { + "comment": "Revert \"fix: fix the bug of axis pickable\"\n\nThis reverts commit 55637a84c01f7af8f4b64ccdfc8cd7215a257c03.\n\n", + "type": "none", + "packageName": "@visactor/vrender-components" + } + ], + "packageName": "@visactor/vrender-components", + "email": "lixuef1313@163.com" +} \ No newline at end of file From 00c3335bbe06814d631b05e1b86c4a325b439cbf Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Wed, 25 Dec 2024 15:50:07 +0800 Subject: [PATCH 22/51] fix: fix issue with forget update pnpm-lock --- common/config/rush/pnpm-lock.yaml | 42 +++++++++++++++---------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index a9adf97bb..02f5b11d1 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -15,7 +15,7 @@ importers: '@visactor/vchart': 1.3.0 '@visactor/vgrammar': ~0.5.7 '@visactor/vrender': workspace:0.21.6 - '@visactor/vutils': ~0.19.2 + '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 axios: ^1.4.0 chalk: ^3.0.0 @@ -38,7 +38,7 @@ importers: '@visactor/vchart': 1.3.0 '@visactor/vgrammar': 0.5.7 '@visactor/vrender': link:../packages/vrender - '@visactor/vutils': 0.19.2 + '@visactor/vutils': 0.19.3 axios: 1.7.8 highlight.js: 11.10.0 lodash: 4.17.21 @@ -72,7 +72,7 @@ importers: '@types/react-dom': ^18.0.0 '@types/react-reconciler': ^0.28.2 '@visactor/vrender': workspace:0.21.6 - '@visactor/vutils': ~0.19.2 + '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 eslint: ~8.18.0 @@ -84,7 +84,7 @@ importers: vite: 3.2.6 dependencies: '@visactor/vrender': link:../vrender - '@visactor/vutils': 0.19.2 + '@visactor/vutils': 0.19.3 react-reconciler: 0.29.2_react@18.3.1 tslib: 2.8.1 devDependencies: @@ -113,7 +113,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/react-vrender': workspace:0.21.6 '@visactor/vrender': workspace:0.21.6 - '@visactor/vutils': ~0.19.2 + '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 eslint: ~8.18.0 @@ -126,7 +126,7 @@ importers: dependencies: '@visactor/react-vrender': link:../react-vrender '@visactor/vrender': link:../vrender - '@visactor/vutils': 0.19.2 + '@visactor/vutils': 0.19.3 react-reconciler: 0.29.2_react@18.3.1 tslib: 2.8.1 devDependencies: @@ -155,7 +155,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vrender-core': workspace:0.21.6 '@visactor/vrender-kits': workspace:0.21.6 - '@visactor/vutils': ~0.19.2 + '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 cross-env: ^7.0.3 @@ -179,7 +179,7 @@ importers: '@types/jest': 26.0.24 '@types/react': 18.3.12 '@types/react-dom': 18.3.1 - '@visactor/vutils': 0.19.2 + '@visactor/vutils': 0.19.3 '@vitejs/plugin-react': 3.1.0_vite@3.2.6 canvas: 2.11.2 cross-env: 7.0.3 @@ -202,8 +202,8 @@ importers: '@types/jest': ^26.0.0 '@visactor/vrender-core': workspace:0.21.6 '@visactor/vrender-kits': workspace:0.21.6 - '@visactor/vscale': ~0.19.2 - '@visactor/vutils': ~0.19.2 + '@visactor/vscale': ~0.19.3 + '@visactor/vutils': ~0.19.3 cross-env: ^7.0.3 eslint: ~8.18.0 jest: ^26.0.0 @@ -215,8 +215,8 @@ importers: dependencies: '@visactor/vrender-core': link:../vrender-core '@visactor/vrender-kits': link:../vrender-kits - '@visactor/vscale': 0.19.2 - '@visactor/vutils': 0.19.2 + '@visactor/vscale': 0.19.3 + '@visactor/vutils': 0.19.3 devDependencies: '@internal/bundler': link:../../tools/bundler '@internal/eslint-config': link:../../share/eslint-config @@ -241,7 +241,7 @@ importers: '@types/jest': ^26.0.0 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vutils': ~0.19.2 + '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 color-convert: 2.0.1 cross-env: ^7.0.3 @@ -255,7 +255,7 @@ importers: typescript: 4.9.5 vite: 3.2.6 dependencies: - '@visactor/vutils': 0.19.2 + '@visactor/vutils': 0.19.3 color-convert: 2.0.1 devDependencies: '@internal/bundler': link:../../tools/bundler @@ -288,7 +288,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@visactor/vrender-core': workspace:0.21.6 - '@visactor/vutils': ~0.19.2 + '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 cross-env: ^7.0.3 @@ -302,7 +302,7 @@ importers: dependencies: '@resvg/resvg-js': 2.4.1 '@visactor/vrender-core': link:../vrender-core - '@visactor/vutils': 0.19.2 + '@visactor/vutils': 0.19.3 roughjs: 4.5.2 devDependencies: '@internal/bundler': link:../../tools/bundler @@ -3409,10 +3409,10 @@ packages: '@visactor/vutils': 0.15.14 dev: false - /@visactor/vscale/0.19.2: - resolution: {integrity: sha512-grS2nI/dyky9+YWt6EbtBS7aPiHmJrnGnleeRLvaaa6uZN9ItLsuP7oSv63k1arJzkyJ0xcLH4ze/nZmrWopzA==} + /@visactor/vscale/0.19.3: + resolution: {integrity: sha512-gLf1ocsgDXcavGqtYYE62N6fH9vXRV/Cd+TeSt0eh2SR1swvi4z5effLS0rpUzjAnGr97h6QaUmhJ1acShLA8Q==} dependencies: - '@visactor/vutils': 0.19.2 + '@visactor/vutils': 0.19.3 dev: false /@visactor/vutils/0.13.3: @@ -3431,8 +3431,8 @@ packages: eventemitter3: 4.0.7 dev: false - /@visactor/vutils/0.19.2: - resolution: {integrity: sha512-RIg+cZTLvTRNbj0f3pc/4W5ASXhuM6G5XJU4JJ2Ghdqt8YGaGzdLFrqOIu5MaHfm8EuJun0oPapDk8PXt4ZQgQ==} + /@visactor/vutils/0.19.3: + resolution: {integrity: sha512-tJAn7HWSX4hv9cDuCg4wGUvXWO7/zHwA4PLfJ45C0n4SJa0HPgIPJ2TtyYfsj54Mt7gkUx0XZpaeAVr6N4wWug==} dependencies: '@turf/helpers': 6.5.0 '@turf/invariant': 6.5.0 From d0ca427e1a59bc9c994e787442aefc7184d7b139 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 25 Dec 2024 07:58:50 +0000 Subject: [PATCH 23/51] build: prelease version 0.21.7 --- ...pgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 -------- ...pgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 -------- ...gon-sector-crosshair_2024-12-23-12-33.json | 10 ------- ...eat-switch-component_2024-11-20-13-07.json | 10 ------- ...revert-axis-pickable_2024-12-25-03-24.json | 11 -------- ...pgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 -------- ...pgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 -------- ...pgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 -------- ...pgrade-vutils-0.19.3_2024-12-25-03-23.json | 11 -------- common/config/rush/pnpm-lock.yaml | 26 +++++++++---------- common/config/rush/version-policies.json | 2 +- docs/package.json | 2 +- packages/react-vrender-utils/CHANGELOG.json | 12 +++++++++ packages/react-vrender-utils/CHANGELOG.md | 11 +++++++- packages/react-vrender-utils/package.json | 6 ++--- packages/react-vrender/CHANGELOG.json | 12 +++++++++ packages/react-vrender/CHANGELOG.md | 11 +++++++- packages/react-vrender/package.json | 4 +-- packages/vrender-components/CHANGELOG.json | 21 +++++++++++++++ packages/vrender-components/CHANGELOG.md | 18 ++++++++++++- packages/vrender-components/package.json | 6 ++--- packages/vrender-core/CHANGELOG.json | 12 +++++++++ packages/vrender-core/CHANGELOG.md | 11 +++++++- packages/vrender-core/package.json | 2 +- packages/vrender-kits/CHANGELOG.json | 12 +++++++++ packages/vrender-kits/CHANGELOG.md | 11 +++++++- packages/vrender-kits/package.json | 4 +-- packages/vrender/CHANGELOG.json | 12 +++++++++ packages/vrender/CHANGELOG.md | 11 +++++++- packages/vrender/package.json | 6 ++--- tools/bugserver-trigger/package.json | 8 +++--- 31 files changed, 181 insertions(+), 136 deletions(-) delete mode 100644 common/changes/@visactor/react-vrender-utils/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json delete mode 100644 common/changes/@visactor/react-vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json delete mode 100644 common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json delete mode 100644 common/changes/@visactor/vrender-components/feat-switch-component_2024-11-20-13-07.json delete mode 100644 common/changes/@visactor/vrender-components/fix-revert-axis-pickable_2024-12-25-03-24.json delete mode 100644 common/changes/@visactor/vrender-components/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json delete mode 100644 common/changes/@visactor/vrender-core/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json delete mode 100644 common/changes/@visactor/vrender-kits/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json delete mode 100644 common/changes/@visactor/vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json diff --git a/common/changes/@visactor/react-vrender-utils/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/react-vrender-utils/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json deleted file mode 100644 index 2aff236b0..000000000 --- a/common/changes/@visactor/react-vrender-utils/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: upgrade vutils to 0.19.3\n\n", - "type": "none", - "packageName": "@visactor/react-vrender-utils" - } - ], - "packageName": "@visactor/react-vrender-utils", - "email": "dingling112@gmail.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/react-vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/react-vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json deleted file mode 100644 index 9066cf7bd..000000000 --- a/common/changes/@visactor/react-vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: upgrade vutils to 0.19.3\n\n", - "type": "none", - "packageName": "@visactor/react-vrender" - } - ], - "packageName": "@visactor/react-vrender", - "email": "dingling112@gmail.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json b/common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json deleted file mode 100644 index 11ea174bb..000000000 --- a/common/changes/@visactor/vrender-components/feat-polygon-sector-crosshair_2024-12-23-12-33.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vrender-components", - "comment": "feat: support polygon sector crosshair for non-smooth angle axis", - "type": "none" - } - ], - "packageName": "@visactor/vrender-components" -} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-components/feat-switch-component_2024-11-20-13-07.json b/common/changes/@visactor/vrender-components/feat-switch-component_2024-11-20-13-07.json deleted file mode 100644 index cb6498c4b..000000000 --- a/common/changes/@visactor/vrender-components/feat-switch-component_2024-11-20-13-07.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "changes": [ - { - "packageName": "@visactor/vrender-components", - "comment": "feat: add switch component", - "type": "none" - } - ], - "packageName": "@visactor/vrender-components" -} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-components/fix-revert-axis-pickable_2024-12-25-03-24.json b/common/changes/@visactor/vrender-components/fix-revert-axis-pickable_2024-12-25-03-24.json deleted file mode 100644 index 1091fd7e9..000000000 --- a/common/changes/@visactor/vrender-components/fix-revert-axis-pickable_2024-12-25-03-24.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "Revert \"fix: fix the bug of axis pickable\"\n\nThis reverts commit 55637a84c01f7af8f4b64ccdfc8cd7215a257c03.\n\n", - "type": "none", - "packageName": "@visactor/vrender-components" - } - ], - "packageName": "@visactor/vrender-components", - "email": "lixuef1313@163.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-components/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/vrender-components/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json deleted file mode 100644 index 09bc1749e..000000000 --- a/common/changes/@visactor/vrender-components/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: upgrade vutils to 0.19.3\n\n", - "type": "none", - "packageName": "@visactor/vrender-components" - } - ], - "packageName": "@visactor/vrender-components", - "email": "dingling112@gmail.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-core/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/vrender-core/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json deleted file mode 100644 index 98246981a..000000000 --- a/common/changes/@visactor/vrender-core/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: upgrade vutils to 0.19.3\n\n", - "type": "none", - "packageName": "@visactor/vrender-core" - } - ], - "packageName": "@visactor/vrender-core", - "email": "dingling112@gmail.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vrender-kits/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/vrender-kits/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json deleted file mode 100644 index 2474170fb..000000000 --- a/common/changes/@visactor/vrender-kits/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: upgrade vutils to 0.19.3\n\n", - "type": "none", - "packageName": "@visactor/vrender-kits" - } - ], - "packageName": "@visactor/vrender-kits", - "email": "dingling112@gmail.com" -} \ No newline at end of file diff --git a/common/changes/@visactor/vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json b/common/changes/@visactor/vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json deleted file mode 100644 index 0f2de2b8a..000000000 --- a/common/changes/@visactor/vrender/fix-upgrade-vutils-0.19.3_2024-12-25-03-23.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "changes": [ - { - "comment": "fix: upgrade vutils to 0.19.3\n\n", - "type": "none", - "packageName": "@visactor/vrender" - } - ], - "packageName": "@visactor/vrender", - "email": "dingling112@gmail.com" -} \ No newline at end of file diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 02f5b11d1..f83c7f160 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -14,7 +14,7 @@ importers: '@types/react-dom': ^18.0.0 '@visactor/vchart': 1.3.0 '@visactor/vgrammar': ~0.5.7 - '@visactor/vrender': workspace:0.21.6 + '@visactor/vrender': workspace:0.21.7 '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 axios: ^1.4.0 @@ -71,7 +71,7 @@ importers: '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 '@types/react-reconciler': ^0.28.2 - '@visactor/vrender': workspace:0.21.6 + '@visactor/vrender': workspace:0.21.7 '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 @@ -111,8 +111,8 @@ importers: '@rushstack/eslint-patch': ~1.1.4 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/react-vrender': workspace:0.21.6 - '@visactor/vrender': workspace:0.21.6 + '@visactor/react-vrender': workspace:0.21.7 + '@visactor/vrender': workspace:0.21.7 '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 cross-env: ^7.0.3 @@ -153,8 +153,8 @@ importers: '@types/jest': ^26.0.0 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vrender-core': workspace:0.21.6 - '@visactor/vrender-kits': workspace:0.21.6 + '@visactor/vrender-core': workspace:0.21.7 + '@visactor/vrender-kits': workspace:0.21.7 '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 @@ -200,8 +200,8 @@ importers: '@internal/ts-config': workspace:* '@rushstack/eslint-patch': ~1.1.4 '@types/jest': ^26.0.0 - '@visactor/vrender-core': workspace:0.21.6 - '@visactor/vrender-kits': workspace:0.21.6 + '@visactor/vrender-core': workspace:0.21.7 + '@visactor/vrender-kits': workspace:0.21.7 '@visactor/vscale': ~0.19.3 '@visactor/vutils': ~0.19.3 cross-env: ^7.0.3 @@ -287,7 +287,7 @@ importers: '@types/node-fetch': 2.6.4 '@types/react': ^18.0.0 '@types/react-dom': ^18.0.0 - '@visactor/vrender-core': workspace:0.21.6 + '@visactor/vrender-core': workspace:0.21.7 '@visactor/vutils': ~0.19.3 '@vitejs/plugin-react': 3.1.0 canvas: 2.11.2 @@ -369,10 +369,10 @@ importers: '@rushstack/eslint-patch': ~1.1.4 '@types/node': '*' '@types/node-fetch': 2.6.4 - '@visactor/vrender': workspace:0.21.6 - '@visactor/vrender-components': workspace:0.21.6 - '@visactor/vrender-core': workspace:0.21.6 - '@visactor/vrender-kits': workspace:0.21.6 + '@visactor/vrender': workspace:0.21.7 + '@visactor/vrender-components': workspace:0.21.7 + '@visactor/vrender-core': workspace:0.21.7 + '@visactor/vrender-kits': workspace:0.21.7 cross-env: ^7.0.3 eslint: ~8.18.0 form-data: ~4.0.0 diff --git a/common/config/rush/version-policies.json b/common/config/rush/version-policies.json index 9c89f9811..8134a70d5 100644 --- a/common/config/rush/version-policies.json +++ b/common/config/rush/version-policies.json @@ -1 +1 @@ -[{"definitionName":"lockStepVersion","policyName":"vrenderMain","version":"0.21.6","nextBump":"patch"}] +[{"definitionName":"lockStepVersion","policyName":"vrenderMain","version":"0.21.7","nextBump":"patch"}] diff --git a/docs/package.json b/docs/package.json index 6b7fe1344..3c0ef46a3 100644 --- a/docs/package.json +++ b/docs/package.json @@ -13,7 +13,7 @@ "@visactor/vchart": "1.3.0", "@visactor/vutils": "~0.19.3", "@visactor/vgrammar": "~0.5.7", - "@visactor/vrender": "workspace:0.21.6", + "@visactor/vrender": "workspace:0.21.7", "markdown-it": "^13.0.0", "highlight.js": "^11.8.0", "axios": "^1.4.0", diff --git a/packages/react-vrender-utils/CHANGELOG.json b/packages/react-vrender-utils/CHANGELOG.json index 746010a61..dc40d6050 100644 --- a/packages/react-vrender-utils/CHANGELOG.json +++ b/packages/react-vrender-utils/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/react-vrender-utils", "entries": [ + { + "version": "0.21.7", + "tag": "@visactor/react-vrender-utils_v0.21.7", + "date": "Wed, 25 Dec 2024 07:53:11 GMT", + "comments": { + "none": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n" + } + ] + } + }, { "version": "0.21.6", "tag": "@visactor/react-vrender-utils_v0.21.6", diff --git a/packages/react-vrender-utils/CHANGELOG.md b/packages/react-vrender-utils/CHANGELOG.md index 50c175b78..6a218ef71 100644 --- a/packages/react-vrender-utils/CHANGELOG.md +++ b/packages/react-vrender-utils/CHANGELOG.md @@ -1,6 +1,15 @@ # Change Log - @visactor/react-vrender-utils -This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. +This log was last generated on Wed, 25 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.7 +Wed, 25 Dec 2024 07:53:11 GMT + +### Updates + +- fix: upgrade vutils to 0.19.3 + + ## 0.21.6 Tue, 24 Dec 2024 12:46:37 GMT diff --git a/packages/react-vrender-utils/package.json b/packages/react-vrender-utils/package.json index ba5cab75e..098d72eb0 100644 --- a/packages/react-vrender-utils/package.json +++ b/packages/react-vrender-utils/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vrender-utils", - "version": "0.21.6", + "version": "0.21.7", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -24,8 +24,8 @@ "react-dom": "^18.2.0" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.6", - "@visactor/react-vrender": "workspace:0.21.6", + "@visactor/vrender": "workspace:0.21.7", + "@visactor/react-vrender": "workspace:0.21.7", "@visactor/vutils": "~0.19.3", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" diff --git a/packages/react-vrender/CHANGELOG.json b/packages/react-vrender/CHANGELOG.json index bd0a4ff47..50b557578 100644 --- a/packages/react-vrender/CHANGELOG.json +++ b/packages/react-vrender/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/react-vrender", "entries": [ + { + "version": "0.21.7", + "tag": "@visactor/react-vrender_v0.21.7", + "date": "Wed, 25 Dec 2024 07:53:11 GMT", + "comments": { + "none": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n" + } + ] + } + }, { "version": "0.21.6", "tag": "@visactor/react-vrender_v0.21.6", diff --git a/packages/react-vrender/CHANGELOG.md b/packages/react-vrender/CHANGELOG.md index 487b52673..526b40251 100644 --- a/packages/react-vrender/CHANGELOG.md +++ b/packages/react-vrender/CHANGELOG.md @@ -1,6 +1,15 @@ # Change Log - @visactor/react-vrender -This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. +This log was last generated on Wed, 25 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.7 +Wed, 25 Dec 2024 07:53:11 GMT + +### Updates + +- fix: upgrade vutils to 0.19.3 + + ## 0.21.6 Tue, 24 Dec 2024 12:46:37 GMT diff --git a/packages/react-vrender/package.json b/packages/react-vrender/package.json index 65e231547..32ef0e261 100644 --- a/packages/react-vrender/package.json +++ b/packages/react-vrender/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/react-vrender", - "version": "0.21.6", + "version": "0.21.7", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -23,7 +23,7 @@ "react": "^18.2.0" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.6", + "@visactor/vrender": "workspace:0.21.7", "@visactor/vutils": "~0.19.3", "react-reconciler": "^0.29.0", "tslib": "^2.3.1" diff --git a/packages/vrender-components/CHANGELOG.json b/packages/vrender-components/CHANGELOG.json index f960c19e9..e67d654fe 100644 --- a/packages/vrender-components/CHANGELOG.json +++ b/packages/vrender-components/CHANGELOG.json @@ -1,6 +1,27 @@ { "name": "@visactor/vrender-components", "entries": [ + { + "version": "0.21.7", + "tag": "@visactor/vrender-components_v0.21.7", + "date": "Wed, 25 Dec 2024 07:53:11 GMT", + "comments": { + "none": [ + { + "comment": "feat: support polygon sector crosshair for non-smooth angle axis" + }, + { + "comment": "feat: add switch component" + }, + { + "comment": "Revert \"fix: fix the bug of axis pickable\"\n\nThis reverts commit 55637a84c01f7af8f4b64ccdfc8cd7215a257c03.\n\n" + }, + { + "comment": "fix: upgrade vutils to 0.19.3\n\n" + } + ] + } + }, { "version": "0.21.6", "tag": "@visactor/vrender-components_v0.21.6", diff --git a/packages/vrender-components/CHANGELOG.md b/packages/vrender-components/CHANGELOG.md index ed4bbeaf8..b80e036cb 100644 --- a/packages/vrender-components/CHANGELOG.md +++ b/packages/vrender-components/CHANGELOG.md @@ -1,6 +1,22 @@ # Change Log - @visactor/vrender-components -This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. +This log was last generated on Wed, 25 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.7 +Wed, 25 Dec 2024 07:53:11 GMT + +### Updates + +- feat: support polygon sector crosshair for non-smooth angle axis +- feat: add switch component +- Revert "fix: fix the bug of axis pickable" + +This reverts commit 55637a84c01f7af8f4b64ccdfc8cd7215a257c03. + + +- fix: upgrade vutils to 0.19.3 + + ## 0.21.6 Tue, 24 Dec 2024 12:46:37 GMT diff --git a/packages/vrender-components/package.json b/packages/vrender-components/package.json index 0a0bcc2cf..0e0f05e6a 100644 --- a/packages/vrender-components/package.json +++ b/packages/vrender-components/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-components", - "version": "0.21.6", + "version": "0.21.7", "description": "components library for dp visualization", "sideEffects": false, "main": "cjs/index.js", @@ -27,8 +27,8 @@ "dependencies": { "@visactor/vutils": "~0.19.3", "@visactor/vscale": "~0.19.3", - "@visactor/vrender-core": "workspace:0.21.6", - "@visactor/vrender-kits": "workspace:0.21.6" + "@visactor/vrender-core": "workspace:0.21.7", + "@visactor/vrender-kits": "workspace:0.21.7" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/packages/vrender-core/CHANGELOG.json b/packages/vrender-core/CHANGELOG.json index 224344a51..df3cf244e 100644 --- a/packages/vrender-core/CHANGELOG.json +++ b/packages/vrender-core/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/vrender-core", "entries": [ + { + "version": "0.21.7", + "tag": "@visactor/vrender-core_v0.21.7", + "date": "Wed, 25 Dec 2024 07:53:11 GMT", + "comments": { + "none": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n" + } + ] + } + }, { "version": "0.21.6", "tag": "@visactor/vrender-core_v0.21.6", diff --git a/packages/vrender-core/CHANGELOG.md b/packages/vrender-core/CHANGELOG.md index 89415ce88..2cc185b28 100644 --- a/packages/vrender-core/CHANGELOG.md +++ b/packages/vrender-core/CHANGELOG.md @@ -1,6 +1,15 @@ # Change Log - @visactor/vrender-core -This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. +This log was last generated on Wed, 25 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.7 +Wed, 25 Dec 2024 07:53:11 GMT + +### Updates + +- fix: upgrade vutils to 0.19.3 + + ## 0.21.6 Tue, 24 Dec 2024 12:46:37 GMT diff --git a/packages/vrender-core/package.json b/packages/vrender-core/package.json index 56a7eb4f7..6d80b2246 100644 --- a/packages/vrender-core/package.json +++ b/packages/vrender-core/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-core", - "version": "0.21.6", + "version": "0.21.7", "description": "", "sideEffects": [ "./src/modules.ts", diff --git a/packages/vrender-kits/CHANGELOG.json b/packages/vrender-kits/CHANGELOG.json index cf129dc91..34576c877 100644 --- a/packages/vrender-kits/CHANGELOG.json +++ b/packages/vrender-kits/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/vrender-kits", "entries": [ + { + "version": "0.21.7", + "tag": "@visactor/vrender-kits_v0.21.7", + "date": "Wed, 25 Dec 2024 07:53:11 GMT", + "comments": { + "none": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n" + } + ] + } + }, { "version": "0.21.6", "tag": "@visactor/vrender-kits_v0.21.6", diff --git a/packages/vrender-kits/CHANGELOG.md b/packages/vrender-kits/CHANGELOG.md index b8d6660c9..26d9233df 100644 --- a/packages/vrender-kits/CHANGELOG.md +++ b/packages/vrender-kits/CHANGELOG.md @@ -1,6 +1,15 @@ # Change Log - @visactor/vrender-kits -This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. +This log was last generated on Wed, 25 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.7 +Wed, 25 Dec 2024 07:53:11 GMT + +### Updates + +- fix: upgrade vutils to 0.19.3 + + ## 0.21.6 Tue, 24 Dec 2024 12:46:37 GMT diff --git a/packages/vrender-kits/package.json b/packages/vrender-kits/package.json index 3f3561c81..a378737bc 100644 --- a/packages/vrender-kits/package.json +++ b/packages/vrender-kits/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender-kits", - "version": "0.21.6", + "version": "0.21.7", "description": "", "sideEffects": false, "main": "cjs/index.js", @@ -21,7 +21,7 @@ }, "dependencies": { "@visactor/vutils": "~0.19.3", - "@visactor/vrender-core": "workspace:0.21.6", + "@visactor/vrender-core": "workspace:0.21.7", "@resvg/resvg-js": "2.4.1", "roughjs": "4.5.2" }, diff --git a/packages/vrender/CHANGELOG.json b/packages/vrender/CHANGELOG.json index 6e72aeb5b..f29a28848 100644 --- a/packages/vrender/CHANGELOG.json +++ b/packages/vrender/CHANGELOG.json @@ -1,6 +1,18 @@ { "name": "@visactor/vrender", "entries": [ + { + "version": "0.21.7", + "tag": "@visactor/vrender_v0.21.7", + "date": "Wed, 25 Dec 2024 07:53:11 GMT", + "comments": { + "none": [ + { + "comment": "fix: upgrade vutils to 0.19.3\n\n" + } + ] + } + }, { "version": "0.21.6", "tag": "@visactor/vrender_v0.21.6", diff --git a/packages/vrender/CHANGELOG.md b/packages/vrender/CHANGELOG.md index 734c45c6e..d92e18c88 100644 --- a/packages/vrender/CHANGELOG.md +++ b/packages/vrender/CHANGELOG.md @@ -1,6 +1,15 @@ # Change Log - @visactor/vrender -This log was last generated on Tue, 24 Dec 2024 12:46:37 GMT and should not be manually modified. +This log was last generated on Wed, 25 Dec 2024 07:53:11 GMT and should not be manually modified. + +## 0.21.7 +Wed, 25 Dec 2024 07:53:11 GMT + +### Updates + +- fix: upgrade vutils to 0.19.3 + + ## 0.21.6 Tue, 24 Dec 2024 12:46:37 GMT diff --git a/packages/vrender/package.json b/packages/vrender/package.json index 245b47a08..10c0ef859 100644 --- a/packages/vrender/package.json +++ b/packages/vrender/package.json @@ -1,6 +1,6 @@ { "name": "@visactor/vrender", - "version": "0.21.6", + "version": "0.21.7", "description": "", "sideEffects": true, "main": "cjs/index.js", @@ -24,8 +24,8 @@ "test-watch": "cross-env DEBUG_MODE=1 jest --watch" }, "dependencies": { - "@visactor/vrender-core": "workspace:0.21.6", - "@visactor/vrender-kits": "workspace:0.21.6" + "@visactor/vrender-core": "workspace:0.21.7", + "@visactor/vrender-kits": "workspace:0.21.7" }, "devDependencies": { "@internal/bundler": "workspace:*", diff --git a/tools/bugserver-trigger/package.json b/tools/bugserver-trigger/package.json index f2ac8cf55..9da2af299 100644 --- a/tools/bugserver-trigger/package.json +++ b/tools/bugserver-trigger/package.json @@ -8,10 +8,10 @@ "ci": "ts-node --transpileOnly --skipProject ./scripts/trigger-test.ts" }, "dependencies": { - "@visactor/vrender": "workspace:0.21.6", - "@visactor/vrender-core": "workspace:0.21.6", - "@visactor/vrender-kits": "workspace:0.21.6", - "@visactor/vrender-components": "workspace:0.21.6" + "@visactor/vrender": "workspace:0.21.7", + "@visactor/vrender-core": "workspace:0.21.7", + "@visactor/vrender-kits": "workspace:0.21.7", + "@visactor/vrender-components": "workspace:0.21.7" }, "devDependencies": { "@rushstack/eslint-patch": "~1.1.4", From 1ccbab1443b1471d2be60c91c6b0aa01d752977a Mon Sep 17 00:00:00 2001 From: neuqzxy Date: Wed, 25 Dec 2024 08:33:28 +0000 Subject: [PATCH 24/51] docs: generate changelog of release v0.21.7 --- docs/assets/changelog/en/changelog.md | 29 +++++++++++++++++++++++++++ docs/assets/changelog/zh/changelog.md | 29 +++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/docs/assets/changelog/en/changelog.md b/docs/assets/changelog/en/changelog.md index a73554114..5104b8b34 100644 --- a/docs/assets/changelog/en/changelog.md +++ b/docs/assets/changelog/en/changelog.md @@ -1,3 +1,32 @@ +# v0.21.7 + +2024-12-25 + + +**🆕 New feature** + +- **@visactor/vrender-components**: support polygon sector crosshair for non-smooth angle axis +- **@visactor/vrender-components**: add switch component + +**🐛 Bug fix** + +- **@visactor/vrender-components**: upgrade vutils to 0.19.3 +- **@visactor/react-vrender-utils**: upgrade vutils to 0.19.3 +- **@visactor/react-vrender**: upgrade vutils to 0.19.3 +- **@visactor/vrender-kits**: upgrade vutils to 0.19.3 +- **@visactor/vrender-core**: upgrade vutils to 0.19.3 +- **@visactor/vrender**: upgrade vutils to 0.19.3 + +**🔖 other** + +- **@visactor/vrender-components**: Revert "fix: fix the bug of axis pickable" + +This reverts commit 55637a84c01f7af8f4b64ccdfc8cd7215a257c03. + + + +[more detail about v0.21.7](https://github.com/VisActor/VRender/releases/tag/v0.21.7) + # v0.21.6 2024-12-25 diff --git a/docs/assets/changelog/zh/changelog.md b/docs/assets/changelog/zh/changelog.md index 4d413bc94..2d6d0d56b 100644 --- a/docs/assets/changelog/zh/changelog.md +++ b/docs/assets/changelog/zh/changelog.md @@ -1,3 +1,32 @@ +# v0.21.7 + +2024-12-25 + + +**🆕 新增功能** + +- **@visactor/vrender-components**: support polygon sector crosshair for non-smooth angle axis +- **@visactor/vrender-components**: add switch component + +**🐛 功能修复** + +- **@visactor/vrender-components**: upgrade vutils to 0.19.3 +- **@visactor/react-vrender-utils**: upgrade vutils to 0.19.3 +- **@visactor/react-vrender**: upgrade vutils to 0.19.3 +- **@visactor/vrender-kits**: upgrade vutils to 0.19.3 +- **@visactor/vrender-core**: upgrade vutils to 0.19.3 +- **@visactor/vrender**: upgrade vutils to 0.19.3 + +**🔖 其他** + +- **@visactor/vrender-components**: Revert "fix: fix the bug of axis pickable" + +This reverts commit 55637a84c01f7af8f4b64ccdfc8cd7215a257c03. + + + +[更多详情请查看 v0.21.7](https://github.com/VisActor/VRender/releases/tag/v0.21.7) + # v0.21.6 2024-12-25 From e34641febca816d71e0d4ed18f4244604fa5f4d0 Mon Sep 17 00:00:00 2001 From: xiaoluoHe Date: Wed, 25 Dec 2024 17:00:06 +0800 Subject: [PATCH 25/51] feat: support label for 3d arc --- packages/vrender-components/src/label/arc.ts | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/packages/vrender-components/src/label/arc.ts b/packages/vrender-components/src/label/arc.ts index f935fd928..5b71b46ee 100644 --- a/packages/vrender-components/src/label/arc.ts +++ b/packages/vrender-components/src/label/arc.ts @@ -29,6 +29,7 @@ import { isFunction } from '@visactor/vutils'; export class ArcInfo { key!: string; refDatum!: any; + refArc!: IArc; /** * 绘图区圆弧中点 */ @@ -239,6 +240,14 @@ export class ArcLabel extends LabelBase { basedArc.labelLimit ?? (labels[i].attribute as ITextAttribute).maxLineWidth; } + if (basedArc.refArc && basedArc.refArc.type === 'arc3d') { + (labelAttribute as any).anchor3d = [ + basedArc.circleCenter.x - labelAttribute.x, + basedArc.circleCenter.y - labelAttribute.y + ]; + (labelAttribute as any).beta = basedArc.refArc.attribute.beta; + } + labels[i].setAttributes(labelAttribute); } } @@ -290,7 +299,7 @@ export class ArcLabel extends LabelBase { graphicAttribute.outerRadius, center ); - + arc.refArc = currentMark; arc.pointA = polarToCartesian( center as IPoint, this.computeDatumRadius(center.x * 2, center.y * 2, graphicAttribute.outerRadius), @@ -1006,6 +1015,14 @@ export class ArcLabel extends LabelBase { curveType: 'basis' }); } + + if (baseMark.type === 'arc3d' && baseMark) { + const { beta, x, y } = baseMark.attribute; + lineGraphic.setAttributes({ + beta, + anchor3d: [x, y] + }); + } } return lineGraphic; From 61c02e6603ad95e34ee7657d88d430efef1952b5 Mon Sep 17 00:00:00 2001 From: xiaoluoHe Date: Wed, 25 Dec 2024 17:02:22 +0800 Subject: [PATCH 26/51] docs: add changelog --- .../fix-3d-arc-label_2024-12-25-09-02.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 common/changes/@visactor/vrender-components/fix-3d-arc-label_2024-12-25-09-02.json diff --git a/common/changes/@visactor/vrender-components/fix-3d-arc-label_2024-12-25-09-02.json b/common/changes/@visactor/vrender-components/fix-3d-arc-label_2024-12-25-09-02.json new file mode 100644 index 000000000..c198bcc2a --- /dev/null +++ b/common/changes/@visactor/vrender-components/fix-3d-arc-label_2024-12-25-09-02.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@visactor/vrender-components", + "comment": "fix: handle the additional logic of 3d arc label layout", + "type": "none" + } + ], + "packageName": "@visactor/vrender-components" +} \ No newline at end of file From 48bab12e586a413a469b1c68f86d5f8c309bbba9 Mon Sep 17 00:00:00 2001 From: xiaoluoHe Date: Wed, 25 Dec 2024 17:04:53 +0800 Subject: [PATCH 27/51] fix: fix type error --- packages/vrender-components/src/label/arc.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vrender-components/src/label/arc.ts b/packages/vrender-components/src/label/arc.ts index 5b71b46ee..3d0879474 100644 --- a/packages/vrender-components/src/label/arc.ts +++ b/packages/vrender-components/src/label/arc.ts @@ -299,7 +299,7 @@ export class ArcLabel extends LabelBase { graphicAttribute.outerRadius, center ); - arc.refArc = currentMark; + arc.refArc = currentMark as IArc; arc.pointA = polarToCartesian( center as IPoint, this.computeDatumRadius(center.x * 2, center.y * 2, graphicAttribute.outerRadius), From 69498af649299ea76f51fc72ad61c3e0d4f01a98 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Sat, 12 Oct 2024 15:08:36 +0800 Subject: [PATCH 28/51] feat: support forceFocus function --- .../builtin-plugin/richtext-edit-plugin.ts | 111 ++++++++++++++---- 1 file changed, 88 insertions(+), 23 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index a4ff463ef..32b0677e3 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -14,9 +14,12 @@ import type { IRichTextIcon, IRichTextLine, IRichTextParagraph, - IRichTextParagraphCharacter + IRichTextParagraphCharacter, + ITicker, + ITimeline } from '../../interface'; import { EditModule, findCursorIndexIgnoreLinebreak } from './edit-module'; +import { Animate, DefaultTicker, DefaultTimeline } from '../../animate'; type UpdateType = 'input' | 'change' | 'onfocus' | 'defocus' | 'selection' | 'dispatch'; @@ -41,6 +44,10 @@ class Selection { this.rt = rt; } + isEmpty(): boolean { + return this.selectionStartCursorIdx === this.curCursorIdx; + } + hasFormat(key: string): boolean { return this.getFormat(key) != null; } @@ -48,7 +55,7 @@ class Selection { if (!this.rt) { return null; } - const config = this.rt.attribute.textConfig; + const config = this.rt.attribute.textConfig as any; const val: any = config[this.selectionStartCursorIdx + 1][key]; if (val == null) { return null; @@ -67,13 +74,17 @@ class Selection { if (!this.rt) { return []; } - const config = this.rt.attribute.textConfig; - const val: any = config[this.selectionStartCursorIdx + 1][key]; + const config = this.rt.attribute.textConfig as any; + const defaultV = (this.rt.attribute as any)[key]; + if (this.isEmpty()) { + return [config[this.selectionStartCursorIdx][key] ?? defaultV]; + } + const val: any = config[this.selectionStartCursorIdx + 1][key] ?? defaultV; const set = new Set(); set.add(val); for (let i = this.selectionStartCursorIdx + 2; i <= this.curCursorIdx; i++) { const item = config[i]; - set.add(item[key]); + set.add(item[key] ?? defaultV); } const list = Array.from(set.values()); return list; @@ -104,18 +115,36 @@ export class RichTextEditPlugin implements IPlugin { commandCbs: Map void>>; updateCbs: Array<(type: UpdateType, p: RichTextEditPlugin) => void>; + ticker: ITicker; + timeline: ITimeline; + + // 富文本有align或者baseline的时候,需要对光标做偏移 + protected declare deltaX: number; + protected declare deltaY: number; + constructor() { this.commandCbs = new Map(); this.commandCbs.set(FORMAT_TEXT_COMMAND, [this.formatTextCommandCb]); this.updateCbs = []; + this.timeline = new DefaultTimeline(); + this.ticker = new DefaultTicker([this.timeline]); + this.deltaX = 0; + this.deltaY = 0; } - getSelection() { + /** + * 获取当前选择的区间范围 + * @param defaultAll 如果force为true,又没有选择,则认为选择了所有然后进行匹配,如果为false,则认为什么都没有选择,返回null + * @returns + */ + getSelection(defaultAll: boolean = false) { + if (!this.currRt) { + return null; + } if ( - this.selectionStartCursorIdx && - this.curCursorIdx && - this.selectionStartCursorIdx !== this.curCursorIdx && - this.currRt + this.selectionStartCursorIdx != null && + this.curCursorIdx != null + // this.selectionStartCursorIdx !== this.curCursorIdx && ) { return new Selection( this.selectionStartCursorIdx, @@ -124,6 +153,14 @@ export class RichTextEditPlugin implements IPlugin { findCursorIndexIgnoreLinebreak(this.currRt.attribute.textConfig, this.curCursorIdx), this.currRt ); + } else if (defaultAll) { + return new Selection( + -1, + this.currRt.attribute.textConfig.length - 1, + findCursorIndexIgnoreLinebreak(this.currRt.attribute.textConfig, this.selectionStartCursorIdx), + findCursorIndexIgnoreLinebreak(this.currRt.attribute.textConfig, this.curCursorIdx), + this.currRt + ); } return null; } @@ -221,6 +258,9 @@ export class RichTextEditPlugin implements IPlugin { // 计算p1在字符中的位置 let p1 = this.getEventPosition(e); let line1Info = this.getLineByPoint(cache, p1); + if (!line1Info) { + return; + } const column1 = this.getColumnByLinePoint(line1Info, p1); const y1 = line1Info.top; const y2 = line1Info.top + line1Info.height; @@ -327,6 +367,12 @@ export class RichTextEditPlugin implements IPlugin { this.pointerDown = false; }; + forceFocus(e: PointerEvent) { + this.handleEnter(e); + this.handlePointerDown(e); + this.handlePointerUp(e); + } + // 鼠标进入 handleEnter = (e: PointerEvent) => { this.editing = true; @@ -348,6 +394,8 @@ export class RichTextEditPlugin implements IPlugin { const p1 = { x: 0, y: 0 }; (e.target as IRichText).globalTransMatrix.transformPoint(p, p1); + p1.x -= this.deltaX; + p1.y -= this.deltaY; return p1; } @@ -376,26 +424,41 @@ export class RichTextEditPlugin implements IPlugin { onFocus(e: PointerEvent) { this.deFocus(e); + this.currRt = e.target as IRichText; // 添加shadowGraphic const target = e.target as IRichText; - this.tryUpdateRichtext(target); + RichTextEditPlugin.tryUpdateRichtext(target); const shadowRoot = target.attachShadow(); - shadowRoot.setAttributes({ shadowRootIdx: -1 }); const cache = target.getFrameCache(); if (!cache) { return; } + + this.deltaX = 0; + this.deltaY = 0; + const height = cache.actualHeight; + const width = cache.lines.reduce((w, item) => Math.max(w, item.actualWidth), 0); + if (cache.globalAlign === 'center') { + this.deltaX = -width / 2; + } else if (cache.globalAlign === 'right') { + this.deltaX = -width; + } + if (cache.globalBaseline === 'middle') { + this.deltaY = -height / 2; + } else if (cache.globalBaseline === 'bottom') { + this.deltaY = -height; + } + + shadowRoot.setAttributes({ shadowRootIdx: -1, x: this.deltaX, y: this.deltaY }); if (!this.editLine) { const line = createLine({ x: 0, y: 0, lineWidth: 1, stroke: 'black' }); - line - .animate() - .to({ opacity: 1 }, 10, 'linear') - .wait(700) - .to({ opacity: 0 }, 10, 'linear') - .wait(700) - .loop(Infinity); + // 不使用stage的Ticker,避免影响其他的动画以及受到其他动画影响 + const animate = line.animate(); + animate.setTimeline(this.timeline); + animate.to({ opacity: 1 }, 10, 'linear').wait(700).to({ opacity: 0 }, 10, 'linear').wait(700).loop(Infinity); this.editLine = line; + this.ticker.start(true); const g = createGroup({ x: 0, y: 0, width: 0, height: 0 }); this.editBg = g; @@ -529,21 +592,23 @@ export class RichTextEditPlugin implements IPlugin { } } - splitText(text: string) { + static splitText(text: string) { // 😁这种emoji长度算两个,所以得处理一下 return Array.from(text); } - tryUpdateRichtext(richtext: IRichText) { + static tryUpdateRichtext(richtext: IRichText) { const cache = richtext.getFrameCache(); if ( !cache.lines.every(line => - line.paragraphs.every(item => !(item.text && isString(item.text) && this.splitText(item.text).length > 1)) + line.paragraphs.every( + item => !(item.text && isString(item.text) && RichTextEditPlugin.splitText(item.text).length > 1) + ) ) ) { const tc: IRichTextCharacter[] = []; richtext.attribute.textConfig.forEach((item: IRichTextParagraphCharacter) => { - const textList = this.splitText(item.text.toString()); + const textList = RichTextEditPlugin.splitText(item.text.toString()); if (isString(item.text) && textList.length > 1) { // 拆分 for (let i = 0; i < textList.length; i++) { From d87f5293470d4cebcc1fa70171bb021be017903d Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Sat, 12 Oct 2024 15:56:12 +0800 Subject: [PATCH 29/51] feat: support CreateSelection --- .../builtin-plugin/richtext-edit-plugin.ts | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 32b0677e3..14e71c88a 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -132,6 +132,20 @@ export class RichTextEditPlugin implements IPlugin { this.deltaY = 0; } + static CreateSelection(rt: IRichText) { + if (!rt) { + return null; + } + const { textConfig = [] } = rt.attribute; + return new Selection( + -1, + textConfig.length - 1, + findCursorIndexIgnoreLinebreak(textConfig, -1), + findCursorIndexIgnoreLinebreak(textConfig, textConfig.length - 1), + rt + ); + } + /** * 获取当前选择的区间范围 * @param defaultAll 如果force为true,又没有选择,则认为选择了所有然后进行匹配,如果为false,则认为什么都没有选择,返回null @@ -154,13 +168,7 @@ export class RichTextEditPlugin implements IPlugin { this.currRt ); } else if (defaultAll) { - return new Selection( - -1, - this.currRt.attribute.textConfig.length - 1, - findCursorIndexIgnoreLinebreak(this.currRt.attribute.textConfig, this.selectionStartCursorIdx), - findCursorIndexIgnoreLinebreak(this.currRt.attribute.textConfig, this.curCursorIdx), - this.currRt - ); + return RichTextEditPlugin.CreateSelection(this.currRt); } return null; } From 8a79a18ba6866ffcff83afdce44d9ec78fb25cf2 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 18 Oct 2024 19:31:31 +0800 Subject: [PATCH 30/51] refactor: refactor code for richtext editor plugin --- packages/vrender-core/src/graphic/richtext.ts | 4 + .../src/graphic/richtext/wrapper.ts | 3 +- .../src/plugins/builtin-plugin/edit-module.ts | 123 ++- .../richtext-edit-plugin-old.ts | 671 +++++++++++++++ .../builtin-plugin/richtext-edit-plugin.ts | 784 +++++++++--------- 5 files changed, 1177 insertions(+), 408 deletions(-) create mode 100644 packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin-old.ts diff --git a/packages/vrender-core/src/graphic/richtext.ts b/packages/vrender-core/src/graphic/richtext.ts index e7fe6d0a5..19f06243b 100644 --- a/packages/vrender-core/src/graphic/richtext.ts +++ b/packages/vrender-core/src/graphic/richtext.ts @@ -458,7 +458,11 @@ export class RichText extends Graphic implements IRic } } else { for (let i = 0; i < paragraphs.length; i++) { + if (i === paragraphs.length - 1) { + wrapper.newLine = true; + } wrapper.deal(paragraphs[i]); + wrapper.newLine = false; } } diff --git a/packages/vrender-core/src/graphic/richtext/wrapper.ts b/packages/vrender-core/src/graphic/richtext/wrapper.ts index 54246084e..64f6a3320 100644 --- a/packages/vrender-core/src/graphic/richtext/wrapper.ts +++ b/packages/vrender-core/src/graphic/richtext/wrapper.ts @@ -47,6 +47,7 @@ export default class Wrapper { lineBuffer: (Paragraph | RichTextIcon)[]; direction: 'horizontal' | 'vertical'; directionKey: { width: string; height: string }; + newLine: boolean; // 空换行符是否新增一行 constructor(frame: Frame) { this.frame = frame; @@ -164,7 +165,7 @@ export default class Wrapper { this.send(); } - if (paragraph.text.length === 0) { + if (paragraph.text.length === 0 && !this.newLine) { return; } // 换行符分割出的Paragraph不进入line diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 287f34d4f..331fc343e 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -1,17 +1,55 @@ import type { IRichText, IRichTextCharacter, IRichTextParagraphCharacter } from '../../interface'; import { IRichTextIcon, IRichTextParagraph } from '../../interface'; -export function findCursorIndexIgnoreLinebreak(textConfig: IRichTextCharacter[], cursorIndex: number): number { +function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) { + let idx = 0; + for (let i = 0; i < textConfig.length; i++) { + const c = textConfig[i] as IRichTextParagraphCharacter; + if (c.text !== '\n') { + idx++; + } + } + return Math.max(idx - 1, 0); +} + +/** + * 找到cursorIndex所在的textConfig的位置,忽略换行符 + * @param textConfig + * @param cursorIndex + * @returns + */ +export function findConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[], cursorIndex: number): number { let index = 0; + // 小于0是在最前面了 + if (cursorIndex < 0) { + return -1; + } + let idx = Math.round(cursorIndex); for (index = 0; index < textConfig.length; index++) { const c = textConfig[index] as IRichTextParagraphCharacter; - if (!(c.text && c.text === '\n')) { - cursorIndex--; + if (c.text !== '\n') { + idx--; } - if (cursorIndex < 0) { + if (idx < 0) { break; } } + if (cursorIndex - Math.round(cursorIndex) < 0) { + index--; + } + index = Math.max(index, 0); + // 避免超过限度,最后一个字符可能是换行符,算一个字符 + return Math.min(index, textConfig.length - 1); +} + +export function textConfigIgnoreLinebreakIdxToCursorIdx(textConfig: IRichTextCharacter[], cursorIndex: number): number { + let index = 0; + for (let i = 0; i < cursorIndex; i++) { + const c = textConfig[i] as IRichTextParagraphCharacter; + if (c.text !== '\n') { + index++; + } + } return index; } @@ -73,27 +111,40 @@ export class EditModule { handleCompositionStart = () => { const { textConfig = [] } = this.currRt.attribute; - const cursorIndex = findCursorIndexIgnoreLinebreak(textConfig, this.cursorIndex); - const lastConfig = textConfig[cursorIndex]; - textConfig.splice(cursorIndex + 1, 0, { ...lastConfig, text: '' }); + if (this.cursorIndex < 0) { + const config = textConfig[0]; + textConfig.unshift({ fill: 'black', ...config, text: '' }); + } else { + const cursorIndex = findConfigIndexIgnoreLinebreak(textConfig, this.cursorIndex); + const lastConfig = textConfig[cursorIndex]; + textConfig.splice(cursorIndex + 1, 0, { ...lastConfig, text: '' }); + } + this.isComposing = true; }; handleCompositionEnd = () => { this.isComposing = false; // 拆分上一次的内容 const { textConfig = [] } = this.currRt.attribute; - const curIdx = findCursorIndexIgnoreLinebreak(textConfig, this.cursorIndex + 1); + const configIdx = findConfigIndexIgnoreLinebreak(textConfig, this.cursorIndex + 1); - const lastConfig = textConfig[curIdx]; - textConfig.splice(curIdx, 1); + const lastConfig = textConfig[configIdx]; + textConfig.splice(configIdx, 1); const text = (lastConfig as any).text; - const textList: string[] = Array.from(text.toString()); + const textList: string[] = text ? Array.from(text.toString()) : []; for (let i = 0; i < textList.length; i++) { - textConfig.splice(i + curIdx, 0, { ...lastConfig, text: textList[i] }); + textConfig.splice(i + configIdx, 0, { ...lastConfig, text: textList[i] }); } this.currRt.setAttributes({ textConfig }); this.onChangeCbList.forEach(cb => { - cb(text, this.isComposing, this.cursorIndex + textList.length, this.currRt, 'right'); + cb( + text, + this.isComposing, + // TODO 当换行后刚开始输入会有问题,后续看这里具体Cursor变换逻辑 + Math.min(this.cursorIndex + textList.length, getMaxConfigIndexIgnoreLinebreak(textConfig) + 0.1), + this.currRt, + 'right' + ); }); }; @@ -101,12 +152,18 @@ export class EditModule { if (!this.currRt) { return; } + + // 如果是回车,那就不往后+1 + const { textConfig = [], ...rest } = this.currRt.attribute; + // 删完了,直接返回 + if (ev.type === 'Backspace' && !textConfig.length) { + return; + } + let str = (ev as any).data; - if (ev.type !== 'Backspace' && !str) { + if (!this.isComposing && ev.type !== 'Backspace' && !str) { str = '\n'; } - // 如果是回车,那就不往后+1 - const { textConfig = [] } = this.currRt.attribute; // 如果有选中多个文字,那就先删除 let startIdx = this.selectionStartCursorIdx; @@ -116,14 +173,28 @@ export class EditModule { } // 无论是否composition都立刻恢复到没有选中的idx状态 this.selectionStartCursorIdx = startIdx; - this.cursorIndex = startIdx; // 转换成基于textConfig的 - startIdx = findCursorIndexIgnoreLinebreak(textConfig, startIdx); - const delta = this.selectionStartCursorIdx - startIdx; - endIdx = findCursorIndexIgnoreLinebreak(textConfig, endIdx); - - const lastConfig = textConfig[startIdx + (this.isComposing ? 1 : 0)]; + // let delta = 0; + startIdx = findConfigIndexIgnoreLinebreak(textConfig, startIdx); + // delta = this.selectionStartCursorIdx - startIdx; + endIdx = findConfigIndexIgnoreLinebreak(textConfig, endIdx); + // console.log(startIdx, delta, endIdx); + + const lastConfigIdx = startIdx + (this.isComposing ? 1 : 0); + let lastConfig: any = textConfig[lastConfigIdx]; + if (!lastConfig) { + if (textConfig.length === 0) { + lastConfig = { + fill: rest.fill ?? 'black', + stroke: rest.stroke ?? false, + fontSize: rest.fontSize ?? 12, + fontWeight: rest.fontWeight ?? 'normal' + }; + } else { + lastConfig = textConfig[lastConfigIdx - 1] || textConfig[lastConfigIdx + 1]; + } + } let currConfig = lastConfig; if (ev.type === 'Backspace' && !this.isComposing) { if (startIdx !== endIdx) { @@ -143,16 +214,20 @@ export class EditModule { textConfig.splice(startIdx, 0, currConfig); } (currConfig as any).text = str; + if (!textConfig.length) { + textConfig.push(currConfig); + } } this.currRt.setAttributes({ textConfig }); + this.cursorIndex = textConfigIgnoreLinebreakIdxToCursorIdx(textConfig, startIdx) + 0.1; if (!this.isComposing) { this.onChangeCbList.forEach(cb => { - cb(str, this.isComposing, startIdx + delta, this.currRt, str === '\n' ? 'left' : 'right'); + cb(str, this.isComposing, this.cursorIndex, this.currRt, str === '\n' ? 'left' : 'right'); }); } else { this.onInputCbList.forEach(cb => { - cb(str, this.isComposing, startIdx + delta, this.currRt, str === '\n' ? 'left' : 'right'); + cb(str, this.isComposing, this.cursorIndex, this.currRt, str === '\n' ? 'left' : 'right'); }); } }; diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin-old.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin-old.ts new file mode 100644 index 000000000..5594309da --- /dev/null +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin-old.ts @@ -0,0 +1,671 @@ +// import type { IPointLike } from '@visactor/vutils'; +// import { isObject, isString, max, merge } from '@visactor/vutils'; +// import { Generator } from '../../common/generator'; +// import { createGroup, createLine, createRect } from '../../graphic'; +// import type { +// IGroup, +// ILine, +// IPlugin, +// IPluginService, +// IRect, +// IRichText, +// IRichTextCharacter, +// IRichTextFrame, +// IRichTextIcon, +// IRichTextLine, +// IRichTextParagraph, +// IRichTextParagraphCharacter, +// ITicker, +// ITimeline +// } from '../../interface'; +// import { EditModule, findCursorIndexIgnoreLinebreak } from './edit-module'; +// import { Animate, DefaultTicker, DefaultTimeline } from '../../animate'; + +// type UpdateType = 'input' | 'change' | 'onfocus' | 'defocus' | 'selection' | 'dispatch'; + +// class Selection { +// cacheSelectionStartCursorIdx: number; +// cacheCurCursorIdx: number; +// selectionStartCursorIdx: number; +// curCursorIdx: number; +// rt: IRichText; + +// constructor( +// cacheSelectionStartCursorIdx: number, +// cacheCurCursorIdx: number, +// selectionStartCursorIdx: number, +// curCursorIdx: number, +// rt: IRichText +// ) { +// this.curCursorIdx = curCursorIdx; +// this.selectionStartCursorIdx = selectionStartCursorIdx; +// this.cacheCurCursorIdx = cacheCurCursorIdx; +// this.cacheSelectionStartCursorIdx = cacheSelectionStartCursorIdx; +// this.rt = rt; +// } + +// isEmpty(): boolean { +// return this.selectionStartCursorIdx === this.curCursorIdx; +// } + +// hasFormat(key: string): boolean { +// return this.getFormat(key) != null; +// } + +// /** +// * 获取第idx中key的值 +// * @param key +// * @param idx cursor左侧字符的值,如果idx为-1则认为是特殊情况,为右侧字符的值 +// */ +// _getFormat(key: string, idx: number) { +// if (!this.rt) { +// return null; +// } +// const config = this.rt.attribute.textConfig as any; +// if (idx < 0) { +// idx = 0; +// } +// if (idx >= config.length) { +// return null; +// } +// return config[idx][key] ?? (this.rt.attribute as any)[key]; +// } +// getFormat(key: string): any { +// return this.getAllFormat(key)[0]; +// } + +// getAllFormat(key: string): any { +// const valSet = new Set(); +// let minCursorIdx = Math.min(this.selectionStartCursorIdx, this.curCursorIdx); +// let maxCursorIdx = Math.max(this.selectionStartCursorIdx, this.curCursorIdx); +// if (minCursorIdx === maxCursorIdx) { +// return [this._getFormat(key, minCursorIdx)]; +// } +// minCursorIdx++; +// maxCursorIdx++; +// const maxConfigIdx = this.rt.attribute.textConfig.length - 1; +// if (minCursorIdx > maxConfigIdx) { +// minCursorIdx = maxConfigIdx; +// } +// if (maxCursorIdx > maxConfigIdx) { +// maxCursorIdx = maxConfigIdx; +// } +// for (let i = minCursorIdx; i < maxCursorIdx; i++) { +// const val = this._getFormat(key, i); +// val && valSet.add(val); +// } +// return Array.from(valSet.values()); +// } +// } + +// export const FORMAT_TEXT_COMMAND = 'FORMAT_TEXT_COMMAND'; +// export const FORMAT_ELEMENT_COMMAND = 'FORMAT_ELEMENT_COMMAND'; +// export class RichTextEditPlugin implements IPlugin { +// name: 'RichTextEditPlugin' = 'RichTextEditPlugin'; +// activeEvent: 'onRegister' = 'onRegister'; +// pluginService: IPluginService; +// _uid: number = Generator.GenAutoIncrementId(); +// key: string = this.name + this._uid; +// editing: boolean = false; +// editLine: ILine; +// editBg: IGroup; +// pointerDown: boolean = false; +// // 用于selection中保存上一次click时候的位置 +// lastPoint?: IPointLike; +// editModule: EditModule; +// currRt: IRichText; + +// // 当前的cursor信息 +// // 0.1为第一个字符右侧, -0.1为第一个字符左侧 +// // 1.1为第二个字符右侧,0.9为第二个字符左侧 +// curCursorIdx: number; +// selectionStartCursorIdx: number; + +// commandCbs: Map void>>; +// updateCbs: Array<(type: UpdateType, p: RichTextEditPlugin) => void>; + +// ticker: ITicker; +// timeline: ITimeline; + +// // 富文本有align或者baseline的时候,需要对光标做偏移 +// protected declare deltaX: number; +// protected declare deltaY: number; + +// constructor() { +// this.commandCbs = new Map(); +// this.commandCbs.set(FORMAT_TEXT_COMMAND, [this.formatTextCommandCb]); +// this.updateCbs = []; +// this.timeline = new DefaultTimeline(); +// this.ticker = new DefaultTicker([this.timeline]); +// this.deltaX = 0; +// this.deltaY = 0; +// } + +// static CreateSelection(rt: IRichText) { +// if (!rt) { +// return null; +// } +// const { textConfig = [] } = rt.attribute; +// return new Selection( +// -1, +// textConfig.length - 1, +// findCursorIndexIgnoreLinebreak(textConfig, -1), +// findCursorIndexIgnoreLinebreak(textConfig, textConfig.length - 1), +// rt +// ); +// } + +// /** +// * 获取当前选择的区间范围 +// * @param defaultAll 如果force为true,又没有选择,则认为选择了所有然后进行匹配,如果为false,则认为什么都没有选择,返回null +// * @returns +// */ +// getSelection(defaultAll: boolean = false) { +// if (!this.currRt) { +// return null; +// } +// if ( +// this.selectionStartCursorIdx != null && +// this.curCursorIdx != null +// // this.selectionStartCursorIdx !== this.curCursorIdx && +// ) { +// return new Selection( +// this.selectionStartCursorIdx, +// this.curCursorIdx, +// findCursorIndexIgnoreLinebreak(this.currRt.attribute.textConfig, this.selectionStartCursorIdx), +// findCursorIndexIgnoreLinebreak(this.currRt.attribute.textConfig, this.curCursorIdx), +// this.currRt +// ); +// } else if (defaultAll) { +// return RichTextEditPlugin.CreateSelection(this.currRt); +// } +// return null; +// } + +// /* command */ +// formatTextCommandCb(payload: string, p: RichTextEditPlugin) { +// const rt = p.currRt; +// if (!rt) { +// return; +// } +// const selectionData = p.getSelection(); +// if (!selectionData) { +// return; +// } +// const { selectionStartCursorIdx, curCursorIdx } = selectionData; +// const minCursorIdx = Math.min(selectionStartCursorIdx, curCursorIdx); +// const maxCursorIdx = Math.max(selectionStartCursorIdx, curCursorIdx); +// const config = rt.attribute.textConfig.slice(minCursorIdx + 1, maxCursorIdx + 1); +// if (payload === 'bold') { +// config.forEach((item: IRichTextParagraphCharacter) => (item.fontWeight = 'bold')); +// } else if (payload === 'italic') { +// config.forEach((item: IRichTextParagraphCharacter) => (item.fontStyle = 'italic')); +// } else if (payload === 'underline') { +// config.forEach((item: IRichTextParagraphCharacter) => (item.underline = true)); +// } else if (payload === 'lineThrough') { +// config.forEach((item: IRichTextParagraphCharacter) => (item.lineThrough = true)); +// } else if (isObject(payload)) { +// config.forEach((item: IRichTextParagraphCharacter) => merge(item, payload)); +// } +// rt.setAttributes(rt.attribute); +// } + +// dispatchCommand(command: string, payload: any) { +// const cbs = this.commandCbs.get(command); +// cbs && cbs.forEach(cb => cb(payload, this)); +// this.updateCbs.forEach(cb => cb('dispatch', this)); +// } + +// registerCommand(command: string, cb: (payload: any, p: RichTextEditPlugin) => void) { +// const cbs: Array<(payload: any, p: RichTextEditPlugin) => void> = this.commandCbs.get(command) || []; +// cbs.push(cb); +// } + +// registerUpdateListener(cb: (type: UpdateType, p: RichTextEditPlugin) => void) { +// const cbs = this.updateCbs || []; +// cbs.push(cb); +// } + +// activate(context: IPluginService): void { +// this.pluginService = context; +// this.editModule = new EditModule(); +// // context.stage.on('click', this.handleClick); +// context.stage.on('pointermove', this.handleMove); +// context.stage.on('pointerdown', this.handlePointerDown); +// context.stage.on('pointerup', this.handlePointerUp); +// context.stage.on('pointerleave', this.handlePointerUp); + +// this.editModule.onInput(this.handleInput); +// this.editModule.onChange(this.handleChange); +// } + +// handleInput = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, orient: 'left' | 'right') => { +// // 修改cursor的位置,但并不同步,因为这可能是临时的 +// const p = this.getPointByColumnIdx(cursorIdx, rt, orient); +// this.hideSelection(); +// this.setCursor(p.x, p.y1, p.y2); +// this.updateCbs.forEach(cb => cb('input', this)); +// }; +// handleChange = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, orient: 'left' | 'right') => { +// // 修改cursor的位置,并同步到editModule +// const p = this.getPointByColumnIdx(cursorIdx, rt, orient); +// this.curCursorIdx = cursorIdx; +// this.selectionStartCursorIdx = cursorIdx; +// this.setCursorAndTextArea(p.x, p.y1, p.y2, rt); +// this.hideSelection(); +// this.updateCbs.forEach(cb => cb('change', this)); +// }; + +// handleMove = (e: PointerEvent) => { +// if (!this.isRichtext(e)) { +// return; +// } +// this.currRt = e.target as IRichText; +// this.handleEnter(e); +// (e.target as any).once('pointerleave', this.handleLeave); + +// this.showSelection(e); +// }; + +// showSelection(e: PointerEvent) { +// const cache = (e.target as IRichText).getFrameCache(); +// if (!(cache && this.editBg)) { +// return; +// } +// if (this.pointerDown) { +// let p0 = this.lastPoint; +// // 计算p1在字符中的位置 +// let p1 = this.getEventPosition(e); +// let line1Info = this.getLineByPoint(cache, p1); +// if (!line1Info) { +// return; +// } +// const column1 = this.getColumnByLinePoint(line1Info, p1); +// const y1 = line1Info.top; +// const y2 = line1Info.top + line1Info.height; +// let x = column1.left + column1.width; +// let cursorIndex = this.getColumnIndex(cache, column1); +// if (p1.x < column1.left + column1.width / 2) { +// x = column1.left; +// cursorIndex -= 1; +// } +// p1.x = x; +// p1.y = (y1 + y2) / 2; +// let line0Info = this.getLineByPoint(cache, p0); +// if (p0.y > p1.y || (p0.y === p1.y && p0.x > p1.x)) { +// [p0, p1] = [p1, p0]; +// [line1Info, line0Info] = [line0Info, line1Info]; +// } + +// this.editBg.removeAllChild(); +// if (line0Info === line1Info) { +// // const column0 = this.getColumnByLinePoint(line0Info, p0); +// this.editBg.setAttributes({ +// x: p0.x, +// y: line0Info.top, +// width: p1.x - p0.x, +// height: line0Info.height, +// fill: '#336df4', +// fillOpacity: 0.2 +// }); +// } else { +// this.editBg.setAttributes({ x: 0, y: line0Info.top, width: 0, height: 0 }); +// const startIdx = cache.lines.findIndex(item => item === line0Info); +// const endIdx = cache.lines.findIndex(item => item === line1Info); +// let y = 0; +// for (let i = startIdx; i <= endIdx; i++) { +// const line = cache.lines[i]; +// if (i === startIdx) { +// const p = line.paragraphs[line.paragraphs.length - 1]; +// this.editBg.add( +// createRect({ +// x: p0.x, +// y, +// width: p.left + p.width - p0.x, +// height: line.height, +// fill: '#336df4', +// fillOpacity: 0.2 +// }) +// ); +// } else if (i === endIdx) { +// const p = line.paragraphs[0]; +// this.editBg.add( +// createRect({ +// x: p.left, +// y, +// width: p1.x - p.left, +// height: line.height, +// fill: '#336df4', +// fillOpacity: 0.2 +// }) +// ); +// } else { +// const p0 = line.paragraphs[0]; +// const p1 = line.paragraphs[line.paragraphs.length - 1]; +// this.editBg.add( +// createRect({ +// x: p0.left, +// y, +// width: p1.left + p1.width - p0.left, +// height: line.height, +// fill: '#336df4', +// fillOpacity: 0.2 +// }) +// ); +// } +// y += line.height; +// } +// } + +// this.curCursorIdx = cursorIndex; +// this.setCursorAndTextArea(x, y1 + 2, y2 - 2, e.target as IRichText); + +// this.applyUpdate(); +// this.updateCbs.forEach(cb => cb('selection', this)); +// } +// } + +// hideSelection() { +// if (this.editBg) { +// this.editBg.removeAllChild(); +// this.editBg.setAttributes({ fill: 'transparent' }); +// } +// } + +// handlePointerDown = (e: PointerEvent) => { +// if (this.editing) { +// this.onFocus(e); +// } else { +// this.deFocus(e); +// } +// this.applyUpdate(); +// this.pointerDown = true; +// this.updateCbs.forEach(cb => cb(this.editing ? 'onfocus' : 'defocus', this)); +// console.log(this.selectionStartCursorIdx); +// }; +// handlePointerUp = (e: PointerEvent) => { +// this.pointerDown = false; +// }; + +// forceFocus(e: PointerEvent) { +// this.handleEnter(e); +// this.handlePointerDown(e); +// this.handlePointerUp(e); +// } + +// // 鼠标进入 +// handleEnter = (e: PointerEvent) => { +// this.editing = true; +// this.pluginService.stage.setCursor('text'); +// }; + +// // 鼠标离开 +// handleLeave = (e: PointerEvent) => { +// this.editing = false; +// this.pluginService.stage.setCursor('default'); +// }; + +// isRichtext(e: PointerEvent) { +// return !!(e.target && (e.target as any).type === 'richtext' && (e.target as any).attribute.editable); +// } + +// protected getEventPosition(e: PointerEvent): IPointLike { +// const p = this.pluginService.stage.eventPointTransform(e); + +// const p1 = { x: 0, y: 0 }; +// (e.target as IRichText).globalTransMatrix.transformPoint(p, p1); +// p1.x -= this.deltaX; +// p1.y -= this.deltaY; +// return p1; +// } + +// protected getLineByPoint(cache: IRichTextFrame, p1: IPointLike): IRichTextLine { +// let lineInfo = cache.lines[0]; +// for (let i = 0; i < cache.lines.length; i++) { +// if (lineInfo.top <= p1.y && lineInfo.top + lineInfo.height >= p1.y) { +// break; +// } +// lineInfo = cache.lines[i + 1]; +// } + +// return lineInfo; +// } +// protected getColumnByLinePoint(lineInfo: IRichTextLine, p1: IPointLike): IRichTextParagraph | IRichTextIcon { +// let columnInfo = lineInfo.paragraphs[0]; +// for (let i = 0; i < lineInfo.paragraphs.length; i++) { +// if (columnInfo.left <= p1.x && columnInfo.left + columnInfo.width >= p1.x) { +// break; +// } +// columnInfo = lineInfo.paragraphs[i]; +// } + +// return columnInfo; +// } + +// onFocus(e: PointerEvent) { +// this.deFocus(e); +// this.currRt = e.target as IRichText; + +// // 添加shadowGraphic +// const target = e.target as IRichText; +// RichTextEditPlugin.tryUpdateRichtext(target); +// const shadowRoot = target.attachShadow(); +// const cache = target.getFrameCache(); +// if (!cache) { +// return; +// } + +// this.deltaX = 0; +// this.deltaY = 0; +// const height = cache.actualHeight; +// const width = cache.lines.reduce((w, item) => Math.max(w, item.actualWidth), 0); +// if (cache.globalAlign === 'center') { +// this.deltaX = -width / 2; +// } else if (cache.globalAlign === 'right') { +// this.deltaX = -width; +// } +// if (cache.globalBaseline === 'middle') { +// this.deltaY = -height / 2; +// } else if (cache.globalBaseline === 'bottom') { +// this.deltaY = -height; +// } + +// shadowRoot.setAttributes({ shadowRootIdx: -1, x: this.deltaX, y: this.deltaY }); +// if (!this.editLine) { +// const line = createLine({ x: 0, y: 0, lineWidth: 1, stroke: 'black' }); +// // 不使用stage的Ticker,避免影响其他的动画以及受到其他动画影响 +// const animate = line.animate(); +// animate.setTimeline(this.timeline); +// animate.to({ opacity: 1 }, 10, 'linear').wait(700).to({ opacity: 0 }, 10, 'linear').wait(700).loop(Infinity); +// this.editLine = line; +// this.ticker.start(true); + +// const g = createGroup({ x: 0, y: 0, width: 0, height: 0 }); +// this.editBg = g; +// shadowRoot.add(this.editLine); +// shadowRoot.add(this.editBg); +// } + +// const p1 = this.getEventPosition(e); + +// const lineInfo = this.getLineByPoint(cache, p1); + +// if (lineInfo) { +// const columnInfo = this.getColumnByLinePoint(lineInfo, p1); +// if (!columnInfo) { +// return; +// } + +// let y1 = lineInfo.top; +// let y2 = lineInfo.top + lineInfo.height; +// let x = columnInfo.left + columnInfo.width; +// y1 += 2; +// y2 -= 2; +// let cursorIndex = this.getColumnIndex(cache, columnInfo); +// if (p1.x < columnInfo.left + columnInfo.width / 2) { +// x = columnInfo.left; +// cursorIndex -= 1; +// } + +// this.lastPoint = { x, y: (y1 + y2) / 2 }; + +// this.curCursorIdx = cursorIndex; +// this.selectionStartCursorIdx = cursorIndex; +// this.setCursorAndTextArea(x, y1, y2, target); +// } +// } + +// protected getPointByColumnIdx(idx: number, rt: IRichText, orient: 'left' | 'right') { +// const cache = rt.getFrameCache(); +// const column = this.getColumnByIndex(cache, idx); +// const height = rt.attribute.fontSize ?? (rt.attribute.textConfig?.[0] as any)?.fontSize; +// if (!column) { +// return { +// x: 0, +// y1: 0, +// y2: height +// }; +// } +// const { lineInfo, columnInfo } = column; +// let y1 = lineInfo.top; +// let y2 = lineInfo.top + lineInfo.height; +// const x = columnInfo.left + (orient === 'left' ? 0 : columnInfo.width); +// y1 += 2; +// y2 -= 2; + +// return { x, y1, y2 }; +// } + +// protected getColumnIndex(cache: IRichTextFrame, cInfo: IRichTextParagraph | IRichTextIcon) { +// // TODO 认为都是单个字符拆分的 +// let inputIndex = -1; +// for (let i = 0; i < cache.lines.length; i++) { +// const line = cache.lines[i]; +// for (let j = 0; j < line.paragraphs.length; j++) { +// inputIndex++; +// if (cInfo === line.paragraphs[j]) { +// return inputIndex; +// } +// } +// } +// return -1; +// } +// protected getColumnByIndex( +// cache: IRichTextFrame, +// index: number +// ): { +// lineInfo: IRichTextLine; +// columnInfo: IRichTextParagraph | IRichTextIcon; +// } | null { +// // TODO 认为都是单个字符拆分的 +// let inputIndex = -1; +// for (let i = 0; i < cache.lines.length; i++) { +// const lineInfo = cache.lines[i]; +// for (let j = 0; j < lineInfo.paragraphs.length; j++) { +// const columnInfo = lineInfo.paragraphs[j]; +// inputIndex++; +// if (inputIndex === index) { +// return { +// lineInfo, +// columnInfo +// }; +// } +// } +// } +// return null; +// } + +// protected setCursorAndTextArea(x: number, y1: number, y2: number, rt: IRichText) { +// this.editLine.setAttributes({ +// points: [ +// { x, y: y1 }, +// { x, y: y2 } +// ] +// }); +// const out = { x: 0, y: 0 }; +// rt.globalTransMatrix.getInverse().transformPoint({ x, y: y1 }, out); +// // TODO 考虑stage变换 +// const { left, top } = this.pluginService.stage.window.getBoundingClientRect(); +// out.x += left; +// out.y += top; + +// this.editModule.moveTo(out.x, out.y, rt, this.curCursorIdx, this.selectionStartCursorIdx); +// } +// protected setCursor(x: number, y1: number, y2: number) { +// this.editLine.setAttributes({ +// points: [ +// { x, y: y1 }, +// { x, y: y2 } +// ] +// }); +// } + +// applyUpdate() { +// this.pluginService.stage.renderNextFrame(); +// } +// deFocus(e: PointerEvent) { +// const target = this.currRt as IRichText; +// if (!target) { +// return; +// } +// target.detachShadow(); +// this.currRt = null; +// if (this.editLine) { +// this.editLine.parent.removeChild(this.editLine); +// this.editLine.release(); +// this.editLine = null; + +// this.editBg.parent.removeChild(this.editBg); +// this.editBg.release(); +// this.editBg = null; +// } +// } + +// static splitText(text: string) { +// // 😁这种emoji长度算两个,所以得处理一下 +// return Array.from(text); +// } + +// static tryUpdateRichtext(richtext: IRichText) { +// const cache = richtext.getFrameCache(); +// if ( +// !cache.lines.every(line => +// line.paragraphs.every( +// item => !(item.text && isString(item.text) && RichTextEditPlugin.splitText(item.text).length > 1) +// ) +// ) +// ) { +// const tc: IRichTextCharacter[] = []; +// richtext.attribute.textConfig.forEach((item: IRichTextParagraphCharacter) => { +// const textList = RichTextEditPlugin.splitText(item.text.toString()); +// if (isString(item.text) && textList.length > 1) { +// // 拆分 +// for (let i = 0; i < textList.length; i++) { +// const t = textList[i]; +// tc.push({ ...item, text: t }); +// } +// } else { +// tc.push(item); +// } +// }); +// richtext.setAttributes({ textConfig: tc }); +// richtext.doUpdateFrameCache(tc); +// } +// } + +// onSelect() { +// return; +// } + +// deactivate(context: IPluginService): void { +// // context.stage.off('pointerdown', this.handleClick); +// context.stage.off('pointermove', this.handleMove); +// context.stage.off('pointerdown', this.handlePointerDown); +// context.stage.off('pointerup', this.handlePointerUp); +// context.stage.off('pointerleave', this.handlePointerUp); +// } + +// release() { +// this.editModule.release(); +// } +// } diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 14e71c88a..ad0e26fa8 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -1,5 +1,5 @@ import type { IPointLike } from '@visactor/vutils'; -import { isObject, isString, merge } from '@visactor/vutils'; +import { isObject, isString, max, merge } from '@visactor/vutils'; import { Generator } from '../../common/generator'; import { createGroup, createLine, createRect } from '../../graphic'; import type { @@ -18,29 +18,19 @@ import type { ITicker, ITimeline } from '../../interface'; -import { EditModule, findCursorIndexIgnoreLinebreak } from './edit-module'; import { Animate, DefaultTicker, DefaultTimeline } from '../../animate'; +import { EditModule } from './edit-module'; type UpdateType = 'input' | 'change' | 'onfocus' | 'defocus' | 'selection' | 'dispatch'; class Selection { - cacheSelectionStartCursorIdx: number; - cacheCurCursorIdx: number; selectionStartCursorIdx: number; curCursorIdx: number; rt: IRichText; - constructor( - cacheSelectionStartCursorIdx: number, - cacheCurCursorIdx: number, - selectionStartCursorIdx: number, - curCursorIdx: number, - rt: IRichText - ) { + constructor(selectionStartCursorIdx: number, curCursorIdx: number, rt: IRichText) { this.curCursorIdx = curCursorIdx; this.selectionStartCursorIdx = selectionStartCursorIdx; - this.cacheCurCursorIdx = cacheCurCursorIdx; - this.cacheSelectionStartCursorIdx = cacheSelectionStartCursorIdx; this.rt = rt; } @@ -51,43 +41,36 @@ class Selection { hasFormat(key: string): boolean { return this.getFormat(key) != null; } - getFormat(key: string): any { + + /** + * 获取第idx中key的值 + * @param key + * @param cursorIdx + */ + _getFormat(key: string, cursorIdx: number) { if (!this.rt) { return null; } + const idx = Math.round(cursorIdx); const config = this.rt.attribute.textConfig as any; - const val: any = config[this.selectionStartCursorIdx + 1][key]; - if (val == null) { - return null; - } - for (let i = this.selectionStartCursorIdx + 2; i <= this.curCursorIdx; i++) { - const item = config[i]; - if (val === item[key]) { - continue; - } - return null; - } - return val; + return config[Math.min(idx, config.length - 1)][key] ?? (this.rt.attribute as any)[key]; + } + getFormat(key: string): any { + return this.getAllFormat(key)[0]; } getAllFormat(key: string): any { - if (!this.rt) { - return []; - } - const config = this.rt.attribute.textConfig as any; - const defaultV = (this.rt.attribute as any)[key]; - if (this.isEmpty()) { - return [config[this.selectionStartCursorIdx][key] ?? defaultV]; + const valSet = new Set(); + const minCursorIdx = Math.min(this.selectionStartCursorIdx, this.curCursorIdx); + const maxCursorIdx = Math.max(this.selectionStartCursorIdx, this.curCursorIdx); + if (minCursorIdx === maxCursorIdx) { + return [this._getFormat(key, minCursorIdx)]; } - const val: any = config[this.selectionStartCursorIdx + 1][key] ?? defaultV; - const set = new Set(); - set.add(val); - for (let i = this.selectionStartCursorIdx + 2; i <= this.curCursorIdx; i++) { - const item = config[i]; - set.add(item[key] ?? defaultV); + for (let i = minCursorIdx; i < maxCursorIdx; i++) { + const val = this._getFormat(key, i); + val && valSet.add(val); } - const list = Array.from(set.values()); - return list; + return Array.from(valSet.values()); } } @@ -99,37 +82,66 @@ export class RichTextEditPlugin implements IPlugin { pluginService: IPluginService; _uid: number = Generator.GenAutoIncrementId(); key: string = this.name + this._uid; + + // 是否正在编辑 editing: boolean = false; + // 鼠标是否按下,判断是否展示selection + pointerDown: boolean = false; + + // selection组件 editLine: ILine; editBg: IGroup; - pointerDown: boolean = false; - // 用于selection中保存上一次click时候的位置 - lastPoint?: IPointLike; - editModule: EditModule; + ticker: ITicker; + timeline: ITimeline; + currRt: IRichText; // 当前的cursor信息 + // 0.1为第一个字符右侧, -0.1为第一个字符左侧 + // 1.1为第二个字符右侧,0.9为第二个字符左侧 curCursorIdx: number; selectionStartCursorIdx: number; + startCursorPos?: IPointLike; - commandCbs: Map void>>; - updateCbs: Array<(type: UpdateType, p: RichTextEditPlugin) => void>; + editModule: EditModule; - ticker: ITicker; - timeline: ITimeline; + protected commandCbs: Map void>>; + protected updateCbs: Array<(type: UpdateType, p: RichTextEditPlugin) => void>; - // 富文本有align或者baseline的时候,需要对光标做偏移 + // 富文本外部有align或者baseline的时候,需要对光标做偏移 protected declare deltaX: number; protected declare deltaY: number; - constructor() { - this.commandCbs = new Map(); - this.commandCbs.set(FORMAT_TEXT_COMMAND, [this.formatTextCommandCb]); - this.updateCbs = []; - this.timeline = new DefaultTimeline(); - this.ticker = new DefaultTicker([this.timeline]); - this.deltaX = 0; - this.deltaY = 0; + static splitText(text: string) { + // 😁这种emoji长度算两个,所以得处理一下 + return Array.from(text); + } + + static tryUpdateRichtext(richtext: IRichText) { + const cache = richtext.getFrameCache(); + if ( + !cache.lines.every(line => + line.paragraphs.every( + item => !(item.text && isString(item.text) && RichTextEditPlugin.splitText(item.text).length > 1) + ) + ) + ) { + const tc: IRichTextCharacter[] = []; + richtext.attribute.textConfig.forEach((item: IRichTextParagraphCharacter) => { + const textList = RichTextEditPlugin.splitText(item.text.toString()); + if (isString(item.text) && textList.length > 1) { + // 拆分 + for (let i = 0; i < textList.length; i++) { + const t = textList[i]; + tc.push({ ...item, text: t }); + } + } else { + tc.push(item); + } + }); + richtext.setAttributes({ textConfig: tc }); + richtext.doUpdateFrameCache(tc); + } } static CreateSelection(rt: IRichText) { @@ -137,43 +149,19 @@ export class RichTextEditPlugin implements IPlugin { return null; } const { textConfig = [] } = rt.attribute; - return new Selection( - -1, - textConfig.length - 1, - findCursorIndexIgnoreLinebreak(textConfig, -1), - findCursorIndexIgnoreLinebreak(textConfig, textConfig.length - 1), - rt - ); + return new Selection(0, textConfig.length - 1, rt); } - /** - * 获取当前选择的区间范围 - * @param defaultAll 如果force为true,又没有选择,则认为选择了所有然后进行匹配,如果为false,则认为什么都没有选择,返回null - * @returns - */ - getSelection(defaultAll: boolean = false) { - if (!this.currRt) { - return null; - } - if ( - this.selectionStartCursorIdx != null && - this.curCursorIdx != null - // this.selectionStartCursorIdx !== this.curCursorIdx && - ) { - return new Selection( - this.selectionStartCursorIdx, - this.curCursorIdx, - findCursorIndexIgnoreLinebreak(this.currRt.attribute.textConfig, this.selectionStartCursorIdx), - findCursorIndexIgnoreLinebreak(this.currRt.attribute.textConfig, this.curCursorIdx), - this.currRt - ); - } else if (defaultAll) { - return RichTextEditPlugin.CreateSelection(this.currRt); - } - return null; + constructor() { + this.commandCbs = new Map(); + this.commandCbs.set(FORMAT_TEXT_COMMAND, [this.formatTextCommandCb]); + this.updateCbs = []; + this.timeline = new DefaultTimeline(); + this.ticker = new DefaultTicker([this.timeline]); + this.deltaX = 0; + this.deltaY = 0; } - /* command */ formatTextCommandCb(payload: string, p: RichTextEditPlugin) { const rt = p.currRt; if (!rt) { @@ -184,7 +172,9 @@ export class RichTextEditPlugin implements IPlugin { return; } const { selectionStartCursorIdx, curCursorIdx } = selectionData; - const config = rt.attribute.textConfig.slice(selectionStartCursorIdx + 1, curCursorIdx + 1); + const minCursorIdx = Math.min(selectionStartCursorIdx, curCursorIdx); + const maxCursorIdx = Math.max(selectionStartCursorIdx, curCursorIdx); + const config = rt.attribute.textConfig.slice(minCursorIdx + 1, maxCursorIdx + 1); if (payload === 'bold') { config.forEach((item: IRichTextParagraphCharacter) => (item.fontWeight = 'bold')); } else if (payload === 'italic') { @@ -229,22 +219,32 @@ export class RichTextEditPlugin implements IPlugin { } handleInput = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, orient: 'left' | 'right') => { - // 修改cursor的位置,但并不同步,因为这可能是临时的 - const p = this.getPointByColumnIdx(cursorIdx, rt, orient); + // 修改cursor的位置,但并不同步到curIdx,因为这可能是临时的 + // const p = this.getPointByColumnIdx(cursorIdx, rt, orient); + // console.log(this.curCursorIdx, cursorIdx); this.hideSelection(); - this.setCursor(p.x, p.y1, p.y2); + // this.setCursor(p.x, p.y1, p.y2); this.updateCbs.forEach(cb => cb('input', this)); }; + handleChange = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, orient: 'left' | 'right') => { // 修改cursor的位置,并同步到editModule - const p = this.getPointByColumnIdx(cursorIdx, rt, orient); this.curCursorIdx = cursorIdx; this.selectionStartCursorIdx = cursorIdx; + const p = this.computedCursorPosByCursorIdx(cursorIdx, rt); this.setCursorAndTextArea(p.x, p.y1, p.y2, rt); this.hideSelection(); this.updateCbs.forEach(cb => cb('change', this)); }; + deactivate(context: IPluginService): void { + // context.stage.off('pointerdown', this.handleClick); + context.stage.off('pointermove', this.handleMove); + context.stage.off('pointerdown', this.handlePointerDown); + context.stage.off('pointerup', this.handlePointerUp); + context.stage.off('pointerleave', this.handlePointerUp); + } + handleMove = (e: PointerEvent) => { if (!this.isRichtext(e)) { return; @@ -253,113 +253,20 @@ export class RichTextEditPlugin implements IPlugin { this.handleEnter(e); (e.target as any).once('pointerleave', this.handleLeave); - this.showSelection(e); + this.tryShowSelection(e); }; - showSelection(e: PointerEvent) { - const cache = (e.target as IRichText).getFrameCache(); - if (!(cache && this.editBg)) { - return; - } - if (this.pointerDown) { - let p0 = this.lastPoint; - // 计算p1在字符中的位置 - let p1 = this.getEventPosition(e); - let line1Info = this.getLineByPoint(cache, p1); - if (!line1Info) { - return; - } - const column1 = this.getColumnByLinePoint(line1Info, p1); - const y1 = line1Info.top; - const y2 = line1Info.top + line1Info.height; - let x = column1.left + column1.width; - let cursorIndex = this.getColumnIndex(cache, column1); - if (p1.x < column1.left + column1.width / 2) { - x = column1.left; - cursorIndex -= 1; - } - p1.x = x; - p1.y = (y1 + y2) / 2; - let line0Info = this.getLineByPoint(cache, p0); - if (p0.y > p1.y || (p0.y === p1.y && p0.x > p1.x)) { - [p0, p1] = [p1, p0]; - [line1Info, line0Info] = [line0Info, line1Info]; - } - - this.editBg.removeAllChild(); - if (line0Info === line1Info) { - const column0 = this.getColumnByLinePoint(line0Info, p0); - this.editBg.setAttributes({ - x: p0.x, - y: line0Info.top, - width: p1.x - p0.x, - height: column0.height, - fill: '#336df4', - fillOpacity: 0.2 - }); - } else { - this.editBg.setAttributes({ x: 0, y: line0Info.top, width: 0, height: 0 }); - const startIdx = cache.lines.findIndex(item => item === line0Info); - const endIdx = cache.lines.findIndex(item => item === line1Info); - let y = 0; - for (let i = startIdx; i <= endIdx; i++) { - const line = cache.lines[i]; - if (i === startIdx) { - const p = line.paragraphs[line.paragraphs.length - 1]; - this.editBg.add( - createRect({ - x: p0.x, - y, - width: p.left + p.width - p0.x, - height: line.height, - fill: '#336df4', - fillOpacity: 0.2 - }) - ); - } else if (i === endIdx) { - const p = line.paragraphs[0]; - this.editBg.add( - createRect({ - x: p.left, - y, - width: p1.x - p.left, - height: line.height, - fill: '#336df4', - fillOpacity: 0.2 - }) - ); - } else { - const p0 = line.paragraphs[0]; - const p1 = line.paragraphs[line.paragraphs.length - 1]; - this.editBg.add( - createRect({ - x: p0.left, - y, - width: p1.left + p1.width - p0.left, - height: line.height, - fill: '#336df4', - fillOpacity: 0.2 - }) - ); - } - y += line.height; - } - } - - this.curCursorIdx = cursorIndex; - this.setCursorAndTextArea(x, y1 + 2, y2 - 2, e.target as IRichText); - - this.applyUpdate(); - this.updateCbs.forEach(cb => cb('selection', this)); - } - } + // 鼠标进入 + handleEnter = (e: PointerEvent) => { + this.editing = true; + this.pluginService.stage.setCursor('text'); + }; - hideSelection() { - if (this.editBg) { - this.editBg.removeAllChild(); - this.editBg.setAttributes({ fill: 'transparent' }); - } - } + // 鼠标离开 + handleLeave = (e: PointerEvent) => { + this.editing = false; + this.pluginService.stage.setCursor('default'); + }; handlePointerDown = (e: PointerEvent) => { if (this.editing) { @@ -367,7 +274,7 @@ export class RichTextEditPlugin implements IPlugin { } else { this.deFocus(e); } - this.applyUpdate(); + this.triggerRender(); this.pointerDown = true; this.updateCbs.forEach(cb => cb(this.editing ? 'onfocus' : 'defocus', this)); }; @@ -375,66 +282,11 @@ export class RichTextEditPlugin implements IPlugin { this.pointerDown = false; }; - forceFocus(e: PointerEvent) { - this.handleEnter(e); - this.handlePointerDown(e); - this.handlePointerUp(e); - } - - // 鼠标进入 - handleEnter = (e: PointerEvent) => { - this.editing = true; - this.pluginService.stage.setCursor('text'); - }; - - // 鼠标离开 - handleLeave = (e: PointerEvent) => { - this.editing = false; - this.pluginService.stage.setCursor('default'); - }; - - isRichtext(e: PointerEvent) { - return !!(e.target && (e.target as any).type === 'richtext' && (e.target as any).attribute.editable); - } - - protected getEventPosition(e: PointerEvent): IPointLike { - const p = this.pluginService.stage.eventPointTransform(e); - - const p1 = { x: 0, y: 0 }; - (e.target as IRichText).globalTransMatrix.transformPoint(p, p1); - p1.x -= this.deltaX; - p1.y -= this.deltaY; - return p1; - } - - protected getLineByPoint(cache: IRichTextFrame, p1: IPointLike): IRichTextLine { - let lineInfo = cache.lines[0]; - for (let i = 0; i < cache.lines.length; i++) { - if (lineInfo.top <= p1.y && lineInfo.top + lineInfo.height >= p1.y) { - break; - } - lineInfo = cache.lines[i + 1]; - } - - return lineInfo; - } - protected getColumnByLinePoint(lineInfo: IRichTextLine, p1: IPointLike): IRichTextParagraph | IRichTextIcon { - let columnInfo = lineInfo.paragraphs[0]; - for (let i = 0; i < lineInfo.paragraphs.length; i++) { - if (columnInfo.left <= p1.x && columnInfo.left + columnInfo.width >= p1.x) { - break; - } - columnInfo = lineInfo.paragraphs[i]; - } - - return columnInfo; - } - onFocus(e: PointerEvent) { this.deFocus(e); this.currRt = e.target as IRichText; - // 添加shadowGraphic + // 创建shadowGraphic const target = e.target as IRichText; RichTextEditPlugin.tryUpdateRichtext(target); const shadowRoot = target.attachShadow(); @@ -443,21 +295,10 @@ export class RichTextEditPlugin implements IPlugin { return; } - this.deltaX = 0; - this.deltaY = 0; - const height = cache.actualHeight; - const width = cache.lines.reduce((w, item) => Math.max(w, item.actualWidth), 0); - if (cache.globalAlign === 'center') { - this.deltaX = -width / 2; - } else if (cache.globalAlign === 'right') { - this.deltaX = -width; - } - if (cache.globalBaseline === 'middle') { - this.deltaY = -height / 2; - } else if (cache.globalBaseline === 'bottom') { - this.deltaY = -height; - } + // 计算全局偏移 + this.computeGlobalDelta(cache); + // 添加cursor节点 shadowRoot.setAttributes({ shadowRootIdx: -1, x: this.deltaX, y: this.deltaY }); if (!this.editLine) { const line = createLine({ x: 0, y: 0, lineWidth: 1, stroke: 'black' }); @@ -474,49 +315,188 @@ export class RichTextEditPlugin implements IPlugin { shadowRoot.add(this.editBg); } - const p1 = this.getEventPosition(e); + const data = this.computedCursorPosByEvent(e, cache); - const lineInfo = this.getLineByPoint(cache, p1); + if (data) { + const { x, y1, y2, cursorIndex } = data; + this.startCursorPos = { x, y: (y1 + y2) / 2 }; + this.curCursorIdx = cursorIndex; + this.selectionStartCursorIdx = cursorIndex; + this.setCursorAndTextArea(x, y1, y2, target); + } + } - if (lineInfo) { - const columnInfo = this.getColumnByLinePoint(lineInfo, p1); - if (!columnInfo) { - return; - } + protected deFocus(e: PointerEvent) { + const target = this.currRt as IRichText; + if (!target) { + return; + } + target.detachShadow(); + this.currRt = null; + if (this.editLine) { + this.editLine.parent.removeChild(this.editLine); + this.editLine.release(); + this.editLine = null; - let y1 = lineInfo.top; - let y2 = lineInfo.top + lineInfo.height; - let x = columnInfo.left + columnInfo.width; - y1 += 2; - y2 -= 2; - let cursorIndex = this.getColumnIndex(cache, columnInfo); - if (p1.x < columnInfo.left + columnInfo.width / 2) { - x = columnInfo.left; - cursorIndex -= 1; + this.editBg.parent.removeChild(this.editBg); + this.editBg.release(); + this.editBg = null; + } + } + + // 显示selection + tryShowSelection(e: PointerEvent) { + const cache = (e.target as IRichText).getFrameCache(); + if (!(cache && this.editBg && this.pointerDown && this.startCursorPos)) { + return; + } + let startCursorPos = this.startCursorPos; + const currCursorData = this.computedCursorPosByEvent(e, cache); + if (!currCursorData) { + return; + } + this.curCursorIdx = currCursorData.cursorIndex; + let endCursorPos = { + x: currCursorData.x, + y: (currCursorData.y1 + currCursorData.y2) / 2 + }; + let line0Info = this.getLineByPoint(cache, startCursorPos); + let line1Info = this.getLineByPoint(cache, endCursorPos); + + if ( + startCursorPos.y > endCursorPos.y || + (startCursorPos.y === endCursorPos.y && startCursorPos.x > endCursorPos.x) + ) { + [startCursorPos, endCursorPos] = [endCursorPos, startCursorPos]; + [line1Info, line0Info] = [line0Info, line1Info]; + } + + this.hideSelection(); + if (line0Info === line1Info) { + // 同行 + this.editBg.setAttributes({ + x: startCursorPos.x, + y: line0Info.top, + width: endCursorPos.x - startCursorPos.x, + height: line0Info.height, + fill: '#336df4', + fillOpacity: 0.2 + }); + } else { + this.editBg.setAttributes({ x: 0, y: line0Info.top, width: 0, height: 0 }); + const startIdx = cache.lines.findIndex(item => item === line0Info); + const endIdx = cache.lines.findIndex(item => item === line1Info); + let y = 0; + for (let i = startIdx; i <= endIdx; i++) { + const line = cache.lines[i]; + if (i === startIdx) { + const p = line.paragraphs[line.paragraphs.length - 1]; + this.editBg.add( + createRect({ + x: startCursorPos.x, + y, + width: p.left + p.width - startCursorPos.x, + height: line.height, + fill: '#336df4', + fillOpacity: 0.2 + }) + ); + } else if (i === endIdx) { + const p = line.paragraphs[0]; + this.editBg.add( + createRect({ + x: p.left, + y, + width: endCursorPos.x - p.left, + height: line.height, + fill: '#336df4', + fillOpacity: 0.2 + }) + ); + } else { + const p0 = line.paragraphs[0]; + const p1 = line.paragraphs[line.paragraphs.length - 1]; + this.editBg.add( + createRect({ + x: p0.left, + y, + width: p1.left + p1.width - p0.left, + height: line.height, + fill: '#336df4', + fillOpacity: 0.2 + }) + ); + } + y += line.height; } + } - this.lastPoint = { x, y: (y1 + y2) / 2 }; + this.setCursorAndTextArea(currCursorData.x, currCursorData.y1 + 2, currCursorData.y2 - 2, e.target as IRichText); - this.curCursorIdx = cursorIndex; - this.selectionStartCursorIdx = cursorIndex; - this.setCursorAndTextArea(x, y1, y2, target); + this.triggerRender(); + this.updateCbs.forEach(cb => cb('selection', this)); + } + + hideSelection() { + if (this.editBg) { + this.editBg.removeAllChild(); + this.editBg.setAttributes({ fill: 'transparent' }); } } - protected getPointByColumnIdx(idx: number, rt: IRichText, orient: 'left' | 'right') { - const cache = rt.getFrameCache(); - const { lineInfo, columnInfo } = this.getColumnByIndex(cache, idx); - let y1 = lineInfo.top; - let y2 = lineInfo.top + lineInfo.height; - const x = columnInfo.left + (orient === 'left' ? 0 : columnInfo.width); - y1 += 2; - y2 -= 2; + protected getLineByPoint(cache: IRichTextFrame, p1: IPointLike): IRichTextLine { + let lineInfo = cache.lines[0]; + for (let i = 0; i < cache.lines.length; i++) { + if (lineInfo.top <= p1.y && lineInfo.top + lineInfo.height >= p1.y) { + break; + } + lineInfo = cache.lines[i + 1]; + } - return { x, y1, y2 }; + return lineInfo; } + protected getColumnAndIndexByLinePoint( + lineInfo: IRichTextLine, + p1: IPointLike + ): { + columnInfo: IRichTextParagraph | IRichTextIcon; + delta: number; + } { + let columnInfo = lineInfo.paragraphs[0]; + let delta = 0; + if (lineInfo.paragraphs.length) { + const start = lineInfo.paragraphs[0]; + const end = lineInfo.paragraphs[lineInfo.paragraphs.length - 1]; + if (p1.x <= start.left) { + delta = -0.1; + columnInfo = start; + } else if (p1.x >= end.left + end.width) { + delta = 0.1; + columnInfo = end; + } + } + if (!delta) { + for (let i = 0; i < lineInfo.paragraphs.length; i++) { + columnInfo = lineInfo.paragraphs[i]; + if (columnInfo.left <= p1.x && columnInfo.left + columnInfo.width >= p1.x) { + if (p1.x > columnInfo.left + columnInfo.width / 2) { + delta = 0.1; + } else { + delta = -0.1; + } + break; + } + } + } + + return { + columnInfo, + delta + }; + } protected getColumnIndex(cache: IRichTextFrame, cInfo: IRichTextParagraph | IRichTextIcon) { - // TODO 认为都是单个字符拆分的 + // TODO 【注意】认为cache都是单个字符拆分的 let inputIndex = -1; for (let i = 0; i < cache.lines.length; i++) { const line = cache.lines[i]; @@ -529,29 +509,41 @@ export class RichTextEditPlugin implements IPlugin { } return -1; } - protected getColumnByIndex( - cache: IRichTextFrame, - index: number - ): { - lineInfo: IRichTextLine; - columnInfo: IRichTextParagraph | IRichTextIcon; - } | null { - // TODO 认为都是单个字符拆分的 - let inputIndex = -1; - for (let i = 0; i < cache.lines.length; i++) { - const lineInfo = cache.lines[i]; - for (let j = 0; j < lineInfo.paragraphs.length; j++) { - const columnInfo = lineInfo.paragraphs[j]; - inputIndex++; - if (inputIndex === index) { - return { - lineInfo, - columnInfo - }; - } - } + + protected isRichtext(e: PointerEvent) { + return !!(e.target && (e.target as any).type === 'richtext' && (e.target as any).attribute.editable); + } + + // 如果没有开自动渲染,得触发重绘 + protected triggerRender() { + this.pluginService.stage.renderNextFrame(); + } + + protected computeGlobalDelta(cache: IRichTextFrame) { + this.deltaX = 0; + this.deltaY = 0; + const height = cache.actualHeight; + const width = cache.lines.reduce((w, item) => Math.max(w, item.actualWidth), 0); + if (cache.globalAlign === 'center') { + this.deltaX = -width / 2; + } else if (cache.globalAlign === 'right') { + this.deltaX = -width; + } + if (cache.globalBaseline === 'middle') { + this.deltaY = -height / 2; + } else if (cache.globalBaseline === 'bottom') { + this.deltaY = -height; } - return null; + } + + protected getEventPosition(e: PointerEvent): IPointLike { + const p = this.pluginService.stage.eventPointTransform(e); + + const p1 = { x: 0, y: 0 }; + (e.target as IRichText).globalTransMatrix.transformPoint(p, p1); + p1.x -= this.deltaX; + p1.y -= this.deltaY; + return p1; } protected setCursorAndTextArea(x: number, y1: number, y2: number, rt: IRichText) { @@ -570,81 +562,107 @@ export class RichTextEditPlugin implements IPlugin { this.editModule.moveTo(out.x, out.y, rt, this.curCursorIdx, this.selectionStartCursorIdx); } - protected setCursor(x: number, y1: number, y2: number) { - this.editLine.setAttributes({ - points: [ - { x, y: y1 }, - { x, y: y2 } - ] - }); - } - applyUpdate() { - this.pluginService.stage.renderNextFrame(); - } - deFocus(e: PointerEvent) { - const target = this.currRt as IRichText; - if (!target) { + protected computedCursorPosByEvent(e: PointerEvent, cache: IRichTextFrame) { + const p1 = this.getEventPosition(e); + const lineInfo = this.getLineByPoint(cache, p1); + if (!lineInfo) { return; } - target.detachShadow(); - this.currRt = null; - if (this.editLine) { - this.editLine.parent.removeChild(this.editLine); - this.editLine.release(); - this.editLine = null; - this.editBg.parent.removeChild(this.editBg); - this.editBg.release(); - this.editBg = null; + const { columnInfo, delta } = this.getColumnAndIndexByLinePoint(lineInfo, p1); + if (!columnInfo) { + return; } - } - static splitText(text: string) { - // 😁这种emoji长度算两个,所以得处理一下 - return Array.from(text); + let y1 = lineInfo.top; + let y2 = lineInfo.top + lineInfo.height; + y1 += 2; + y2 -= 2; + + let cursorIndex = this.getColumnIndex(cache, columnInfo); + cursorIndex += delta; + const x = columnInfo.left + (delta > 0 ? columnInfo.width : 0); + + return { + x, + y1, + y2, + cursorIndex + }; } - static tryUpdateRichtext(richtext: IRichText) { - const cache = richtext.getFrameCache(); - if ( - !cache.lines.every(line => - line.paragraphs.every( - item => !(item.text && isString(item.text) && RichTextEditPlugin.splitText(item.text).length > 1) - ) - ) - ) { - const tc: IRichTextCharacter[] = []; - richtext.attribute.textConfig.forEach((item: IRichTextParagraphCharacter) => { - const textList = RichTextEditPlugin.splitText(item.text.toString()); - if (isString(item.text) && textList.length > 1) { - // 拆分 - for (let i = 0; i < textList.length; i++) { - const t = textList[i]; - tc.push({ ...item, text: t }); - } - } else { - tc.push(item); - } - }); - richtext.setAttributes({ textConfig: tc }); - richtext.doUpdateFrameCache(tc); + // 根据cursorIdx计算出点的位置 + protected computedCursorPosByCursorIdx(cursorIdx: number, rt: IRichText) { + const idx = Math.round(cursorIdx); + const leftRight = cursorIdx - idx; // >0 向右,<0 向左 + const cache = rt.getFrameCache(); + const column = this.getColumnByIndex(cache, idx); + const height = rt.attribute.fontSize ?? (rt.attribute.textConfig?.[0] as any)?.fontSize; + if (!column) { + return { + x: 0, + y1: 0, + y2: height + }; } - } + const { lineInfo, columnInfo } = column; + let y1 = lineInfo.top; + let y2 = lineInfo.top + lineInfo.height; + const x = columnInfo.left + (leftRight < 0 ? 0 : columnInfo.width); + y1 += 2; + y2 -= 2; - onSelect() { - return; + return { x, y1, y2 }; } - deactivate(context: IPluginService): void { - // context.stage.off('pointerdown', this.handleClick); - context.stage.off('pointermove', this.handleMove); - context.stage.off('pointerdown', this.handlePointerDown); - context.stage.off('pointerup', this.handlePointerUp); - context.stage.off('pointerleave', this.handlePointerUp); + protected getColumnByIndex( + cache: IRichTextFrame, + index: number + ): { + lineInfo: IRichTextLine; + columnInfo: IRichTextParagraph | IRichTextIcon; + } | null { + // TODO 认为都是单个字符拆分的 + for (let i = 0, inputIndex = 0; i < cache.lines.length; i++) { + const lineInfo = cache.lines[i]; + for (let j = 0; j < lineInfo.paragraphs.length; j++) { + const columnInfo = lineInfo.paragraphs[j]; + if (inputIndex === index) { + return { + lineInfo, + columnInfo + }; + } + inputIndex++; + } + } + return null; } release() { + this.deactivate(this.pluginService); this.editModule.release(); } + + /** + * 获取当前选择的区间范围 + * @param defaultAll 如果force为true,又没有选择,则认为选择了所有然后进行匹配,如果为false,则认为什么都没有选择,返回null + * @returns + */ + getSelection(defaultAll: boolean = false) { + if (!this.currRt) { + return null; + } + if ( + this.selectionStartCursorIdx != null && + this.curCursorIdx != null + // this.selectionStartCursorIdx !== this.curCursorIdx && + ) { + return new Selection(this.selectionStartCursorIdx, this.curCursorIdx, this.currRt); + } else if (defaultAll) { + return RichTextEditPlugin.CreateSelection(this.currRt); + } + return null; + } } From 54f7168d58aa61f143ceff02e9c67c78d10db0e8 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 18 Oct 2024 20:00:04 +0800 Subject: [PATCH 31/51] fix: fix issue where verticalDirection is middle or bottom --- .../plugins/builtin-plugin/richtext-edit-plugin.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index ad0e26fa8..4e42c5542 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -294,7 +294,6 @@ export class RichTextEditPlugin implements IPlugin { if (!cache) { return; } - // 计算全局偏移 this.computeGlobalDelta(cache); @@ -522,17 +521,18 @@ export class RichTextEditPlugin implements IPlugin { protected computeGlobalDelta(cache: IRichTextFrame) { this.deltaX = 0; this.deltaY = 0; - const height = cache.actualHeight; + const height = cache.height; + const actualHeight = cache.actualHeight; const width = cache.lines.reduce((w, item) => Math.max(w, item.actualWidth), 0); if (cache.globalAlign === 'center') { this.deltaX = -width / 2; } else if (cache.globalAlign === 'right') { this.deltaX = -width; } - if (cache.globalBaseline === 'middle') { - this.deltaY = -height / 2; - } else if (cache.globalBaseline === 'bottom') { - this.deltaY = -height; + if (cache.verticalDirection === 'middle') { + this.deltaY = height / 2 - actualHeight / 2; + } else if (cache.verticalDirection === 'bottom') { + this.deltaY = height - actualHeight; } } From aae642373858db6776908c45b389aa324fb90cb1 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 18 Oct 2024 21:03:08 +0800 Subject: [PATCH 32/51] fix: fix issue with delete --- .../src/plugins/builtin-plugin/edit-module.ts | 45 +++++++++++-------- .../builtin-plugin/richtext-edit-plugin.ts | 4 +- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 331fc343e..73bd8f5fd 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -18,7 +18,7 @@ function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) { * @param cursorIndex * @returns */ -export function findConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[], cursorIndex: number): number { +export function findConfigIndex(textConfig: IRichTextCharacter[], cursorIndex: number): number { let index = 0; // 小于0是在最前面了 if (cursorIndex < 0) { @@ -50,6 +50,12 @@ export function textConfigIgnoreLinebreakIdxToCursorIdx(textConfig: IRichTextCha index++; } } + // 正常Cursor是放在右边的,但如果回退到换行符了,那就放在左侧 + if ((textConfig[cursorIndex] as any)?.text === '\n') { + index -= 0.1; + } else { + index += 0.1; + } return index; } @@ -61,13 +67,9 @@ export class EditModule { cursorIndex: number; selectionStartCursorIdx: number; // 输入的回调(composing的时候每次也会触发) - onInputCbList: Array< - (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, pos: 'left' | 'right') => void - >; + onInputCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>; // change的回调(composing确认才会触发) - onChangeCbList: Array< - (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, pos: 'left' | 'right') => void - >; + onChangeCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>; constructor(container?: HTMLElement) { this.container = container ?? document.body; @@ -83,11 +85,11 @@ export class EditModule { this.onChangeCbList = []; } - onInput(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, pos: 'left' | 'right') => void) { + onInput(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void) { this.onInputCbList.push(cb); } - onChange(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, pos: 'left' | 'right') => void) { + onChange(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void) { this.onChangeCbList.push(cb); } @@ -115,7 +117,7 @@ export class EditModule { const config = textConfig[0]; textConfig.unshift({ fill: 'black', ...config, text: '' }); } else { - const cursorIndex = findConfigIndexIgnoreLinebreak(textConfig, this.cursorIndex); + const cursorIndex = findConfigIndex(textConfig, this.cursorIndex); const lastConfig = textConfig[cursorIndex]; textConfig.splice(cursorIndex + 1, 0, { ...lastConfig, text: '' }); } @@ -126,7 +128,7 @@ export class EditModule { this.isComposing = false; // 拆分上一次的内容 const { textConfig = [] } = this.currRt.attribute; - const configIdx = findConfigIndexIgnoreLinebreak(textConfig, this.cursorIndex + 1); + const configIdx = findConfigIndex(textConfig, this.cursorIndex + 1); const lastConfig = textConfig[configIdx]; textConfig.splice(configIdx, 1); @@ -142,8 +144,7 @@ export class EditModule { this.isComposing, // TODO 当换行后刚开始输入会有问题,后续看这里具体Cursor变换逻辑 Math.min(this.cursorIndex + textList.length, getMaxConfigIndexIgnoreLinebreak(textConfig) + 0.1), - this.currRt, - 'right' + this.currRt ); }); }; @@ -176,11 +177,17 @@ export class EditModule { // 转换成基于textConfig的 // let delta = 0; - startIdx = findConfigIndexIgnoreLinebreak(textConfig, startIdx); + startIdx = findConfigIndex(textConfig, startIdx); // delta = this.selectionStartCursorIdx - startIdx; - endIdx = findConfigIndexIgnoreLinebreak(textConfig, endIdx); + endIdx = findConfigIndex(textConfig, endIdx); // console.log(startIdx, delta, endIdx); + let idxDelta = 0; + // 如果是换行,得往回一格 + if (str === '\n') { + idxDelta = -0.2; + } + const lastConfigIdx = startIdx + (this.isComposing ? 1 : 0); let lastConfig: any = textConfig[lastConfigIdx]; if (!lastConfig) { @@ -220,14 +227,16 @@ export class EditModule { } this.currRt.setAttributes({ textConfig }); - this.cursorIndex = textConfigIgnoreLinebreakIdxToCursorIdx(textConfig, startIdx) + 0.1; + this.cursorIndex = textConfigIgnoreLinebreakIdxToCursorIdx(textConfig, startIdx); + + this.cursorIndex += idxDelta; if (!this.isComposing) { this.onChangeCbList.forEach(cb => { - cb(str, this.isComposing, this.cursorIndex, this.currRt, str === '\n' ? 'left' : 'right'); + cb(str, this.isComposing, this.cursorIndex, this.currRt); }); } else { this.onInputCbList.forEach(cb => { - cb(str, this.isComposing, this.cursorIndex, this.currRt, str === '\n' ? 'left' : 'right'); + cb(str, this.isComposing, this.cursorIndex, this.currRt); }); } }; diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 4e42c5542..4c13c021a 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -218,7 +218,7 @@ export class RichTextEditPlugin implements IPlugin { this.editModule.onChange(this.handleChange); } - handleInput = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, orient: 'left' | 'right') => { + handleInput = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => { // 修改cursor的位置,但并不同步到curIdx,因为这可能是临时的 // const p = this.getPointByColumnIdx(cursorIdx, rt, orient); // console.log(this.curCursorIdx, cursorIdx); @@ -227,7 +227,7 @@ export class RichTextEditPlugin implements IPlugin { this.updateCbs.forEach(cb => cb('input', this)); }; - handleChange = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText, orient: 'left' | 'right') => { + handleChange = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => { // 修改cursor的位置,并同步到editModule this.curCursorIdx = cursorIdx; this.selectionStartCursorIdx = cursorIdx; From 85ca692e65390d28859a74d430550731e7629898 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 18 Oct 2024 22:51:17 +0800 Subject: [PATCH 33/51] feat: support direct keydown --- .../src/plugins/builtin-plugin/edit-module.ts | 5 +- .../builtin-plugin/richtext-edit-plugin.ts | 82 +++++++++++++++++++ 2 files changed, 85 insertions(+), 2 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 73bd8f5fd..64dec5586 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -1,3 +1,4 @@ +import { application } from '../../application'; import type { IRichText, IRichTextCharacter, IRichTextParagraphCharacter } from '../../interface'; import { IRichTextIcon, IRichTextParagraph } from '../../interface'; @@ -102,7 +103,7 @@ export class EditModule { textAreaDom.addEventListener('input', this.handleInput); textAreaDom.addEventListener('compositionstart', this.handleCompositionStart); textAreaDom.addEventListener('compositionend', this.handleCompositionEnd); - window.addEventListener('keydown', this.handleKeyDown); + application.global.addEventListener('keydown', this.handleKeyDown); } handleKeyDown = (e: KeyboardEvent) => { @@ -258,6 +259,6 @@ export class EditModule { this.textAreaDom.removeEventListener('input', this.handleInput); this.textAreaDom.removeEventListener('compositionstart', this.handleCompositionStart); this.textAreaDom.removeEventListener('compositionend', this.handleCompositionEnd); - window.removeEventListener('keydown', this.handleKeyDown); + application.global.removeEventListener('keydown', this.handleKeyDown); } } diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 4c13c021a..d566a0ea6 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -20,6 +20,7 @@ import type { } from '../../interface'; import { Animate, DefaultTicker, DefaultTimeline } from '../../animate'; import { EditModule } from './edit-module'; +import { application } from '../../application'; type UpdateType = 'input' | 'change' | 'onfocus' | 'defocus' | 'selection' | 'dispatch'; @@ -213,11 +214,90 @@ export class RichTextEditPlugin implements IPlugin { context.stage.on('pointerdown', this.handlePointerDown); context.stage.on('pointerup', this.handlePointerUp); context.stage.on('pointerleave', this.handlePointerUp); + application.global.addEventListener('keydown', this.handleKeyDown); this.editModule.onInput(this.handleInput); this.editModule.onChange(this.handleChange); } + handleKeyDown = (e: KeyboardEvent) => { + if (!(this.currRt && this.editing)) { + return; + } + const cache = this.currRt.getFrameCache(); + if (!cache) { + return; + } + let x = 0; + let y = 0; + if (e.key === 'ArrowUp') { + y = -1; + } else if (e.key === 'ArrowDown') { + y = 1; + } else if (e.key === 'ArrowLeft') { + x = -1; + } else if (e.key === 'ArrowRight') { + x = 1; + } + + // const pos = this.computedCursorPosByCursorIdx(this.curCursorIdx, this.currRt); + const { lineInfo, columnInfo } = this.getColumnByIndex(cache, Math.round(this.curCursorIdx)); + if (x) { + // 快接近首尾需要特殊处理 + if ( + x > 0 && + columnInfo === lineInfo.paragraphs[lineInfo.paragraphs.length - 2] && + this.curCursorIdx < Math.round(this.curCursorIdx) + ) { + this.curCursorIdx = this.curCursorIdx + 0.2; + } else if ( + x > 0 && + columnInfo === lineInfo.paragraphs[lineInfo.paragraphs.length - 1] && + this.curCursorIdx > Math.round(this.curCursorIdx) + ) { + this.curCursorIdx = this.curCursorIdx + 1 - 0.2; + } else if (x < 0 && columnInfo === lineInfo.paragraphs[0] && this.curCursorIdx > Math.round(this.curCursorIdx)) { + this.curCursorIdx = this.curCursorIdx - 0.2; + } else if (x < 0 && columnInfo === lineInfo.paragraphs[0] && this.curCursorIdx < Math.round(this.curCursorIdx)) { + this.curCursorIdx = this.curCursorIdx - 1 + 0.2; + } else { + this.curCursorIdx += x; + } + + const pos = this.computedCursorPosByCursorIdx(this.curCursorIdx, this.currRt); + this.setCursorAndTextArea(pos.x, pos.y1, pos.y2, this.currRt); + this.hideSelection(); + } + + if (y) { + if (y > 0 && lineInfo === cache.lines[cache.lines.length - 1]) { + return; + } + if (y < 0 && lineInfo === cache.lines[0]) { + return; + } + const lineIdx = cache.lines.findIndex(item => item === lineInfo) + y; + if (lineIdx < 0 || lineIdx >= cache.lines.length) { + return; + } + const pos = this.computedCursorPosByCursorIdx(this.curCursorIdx, this.currRt); + const posX = pos.x; + let posY = (pos.y1 + pos.y2) / 2; + posY += y * lineInfo.height; + const nextLineInfo = cache.lines[lineIdx]; + const { columnInfo, delta } = this.getColumnAndIndexByLinePoint(nextLineInfo, { x: posX, y: posY }); + if (!columnInfo) { + return; + } + const cursorIdx = this.getColumnIndex(cache, columnInfo) + delta; + const data = this.computedCursorPosByCursorIdx(cursorIdx, this.currRt); + + this.curCursorIdx = cursorIdx; + this.selectionStartCursorIdx = cursorIdx; + this.setCursorAndTextArea(data.x, data.y1, data.y2, this.currRt); + } + }; + handleInput = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => { // 修改cursor的位置,但并不同步到curIdx,因为这可能是临时的 // const p = this.getPointByColumnIdx(cursorIdx, rt, orient); @@ -243,6 +323,8 @@ export class RichTextEditPlugin implements IPlugin { context.stage.off('pointerdown', this.handlePointerDown); context.stage.off('pointerup', this.handlePointerUp); context.stage.off('pointerleave', this.handlePointerUp); + + application.global.addEventListener('keydown', this.handleKeyDown); } handleMove = (e: PointerEvent) => { From b3b25de0c2df9b5d7be68fb5c443cf43c7f6d269 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Fri, 18 Oct 2024 22:58:50 +0800 Subject: [PATCH 34/51] feat: reset animate status while set cursor --- .../builtin-plugin/richtext-edit-plugin.ts | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index d566a0ea6..569e1d5e3 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -384,9 +384,7 @@ export class RichTextEditPlugin implements IPlugin { if (!this.editLine) { const line = createLine({ x: 0, y: 0, lineWidth: 1, stroke: 'black' }); // 不使用stage的Ticker,避免影响其他的动画以及受到其他动画影响 - const animate = line.animate(); - animate.setTimeline(this.timeline); - animate.to({ opacity: 1 }, 10, 'linear').wait(700).to({ opacity: 0 }, 10, 'linear').wait(700).loop(Infinity); + this.addAnimateToLine(line); this.editLine = line; this.ticker.start(true); @@ -425,6 +423,17 @@ export class RichTextEditPlugin implements IPlugin { } } + protected addAnimateToLine(line: ILine) { + line.animates && + line.animates.forEach(animate => { + animate.stop(); + animate.release(); + }); + const animate = line.animate(); + animate.setTimeline(this.timeline); + animate.to({ opacity: 1 }, 10, 'linear').wait(700).to({ opacity: 0 }, 10, 'linear').wait(700).loop(Infinity); + } + // 显示selection tryShowSelection(e: PointerEvent) { const cache = (e.target as IRichText).getFrameCache(); @@ -635,6 +644,7 @@ export class RichTextEditPlugin implements IPlugin { { x, y: y2 } ] }); + this.addAnimateToLine(this.editLine); const out = { x: 0, y: 0 }; rt.globalTransMatrix.getInverse().transformPoint({ x, y: y1 }, out); // TODO 考虑stage变换 From a2db073b5e2a2c531221caff752684403180cd20 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 16 Dec 2024 17:19:50 +0800 Subject: [PATCH 35/51] feat: support full selection and copy --- .../contributions/env/base-contribution.ts | 7 + packages/vrender-core/src/core/global.ts | 14 ++ packages/vrender-core/src/interface/global.ts | 5 + .../src/plugins/builtin-plugin/edit-module.ts | 8 +- .../builtin-plugin/richtext-edit-plugin.ts | 137 +++++++++++++++++- .../env/contributions/browser-contribution.ts | 23 +++ 6 files changed, 185 insertions(+), 9 deletions(-) diff --git a/packages/vrender-core/src/core/contributions/env/base-contribution.ts b/packages/vrender-core/src/core/contributions/env/base-contribution.ts index 0baed3f40..805ba7ca1 100644 --- a/packages/vrender-core/src/core/contributions/env/base-contribution.ts +++ b/packages/vrender-core/src/core/contributions/env/base-contribution.ts @@ -190,4 +190,11 @@ export abstract class BaseEnvContribution implements IEnvContribution { ): Promise<{ loadState: 'success' | 'fail' }> { return { loadState: 'fail' }; } + + isMacOS() { + return false; + } + copyToClipBoard(text: string) { + return Promise.resolve(null); + } } diff --git a/packages/vrender-core/src/core/global.ts b/packages/vrender-core/src/core/global.ts index 4c1ec7f75..198890436 100644 --- a/packages/vrender-core/src/core/global.ts +++ b/packages/vrender-core/src/core/global.ts @@ -423,4 +423,18 @@ export class DefaultGlobal implements IGlobal { } return this.envContribution.getElementTopLeft(dom, baseWindow); } + + isMacOS(): boolean { + if (!this._env) { + this.setEnv('browser'); + } + return this.envContribution.isMacOS(); + } + + copyToClipBoard(text: string) { + if (!this._env) { + this.setEnv('browser'); + } + return this.envContribution.copyToClipBoard(text); + } } diff --git a/packages/vrender-core/src/interface/global.ts b/packages/vrender-core/src/interface/global.ts index efca682f0..62dce9188 100644 --- a/packages/vrender-core/src/interface/global.ts +++ b/packages/vrender-core/src/interface/global.ts @@ -134,6 +134,9 @@ export interface IEnvContribution ) => Promise<{ loadState: 'success' | 'fail'; }>; + + isMacOS: () => boolean; + copyToClipBoard: (text: string) => Promise; } export type IMiniAppEnvParams = { @@ -213,6 +216,8 @@ export interface IGlobal extends Omit boolean; isSafari: () => boolean; + isMacOS: () => boolean; + copyToClipBoard: (text: string) => Promise; /** * 获取环境中最大静态canvas的数量,纯粹canvas diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 64dec5586..eaad05562 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -1,6 +1,12 @@ import { application } from '../../application'; import type { IRichText, IRichTextCharacter, IRichTextParagraphCharacter } from '../../interface'; -import { IRichTextIcon, IRichTextParagraph } from '../../interface'; + +let isMac = false; +try { + isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; +} catch (err) { + // ignore +} function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) { let idx = 0; diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 569e1d5e3..d1078a260 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -19,7 +19,7 @@ import type { ITimeline } from '../../interface'; import { Animate, DefaultTicker, DefaultTimeline } from '../../animate'; -import { EditModule } from './edit-module'; +import { EditModule, findConfigIndex } from './edit-module'; import { application } from '../../application'; type UpdateType = 'input' | 'change' | 'onfocus' | 'defocus' | 'selection' | 'dispatch'; @@ -39,6 +39,22 @@ class Selection { return this.selectionStartCursorIdx === this.curCursorIdx; } + getSelectionPureText(): string { + const minCursorIdx = Math.min(this.selectionStartCursorIdx, this.curCursorIdx); + const maxCursorIdx = Math.max(this.selectionStartCursorIdx, this.curCursorIdx); + if (minCursorIdx === maxCursorIdx) { + return ''; + } + const config = this.rt.attribute.textConfig as any; + const startIdx = findConfigIndex(config, Math.ceil(minCursorIdx)); + const endIdx = findConfigIndex(config, Math.floor(maxCursorIdx)); + let str = ''; + for (let i = startIdx; i <= endIdx; i++) { + str += config[i].text; + } + return str; + } + hasFormat(key: string): boolean { return this.getFormat(key) != null; } @@ -52,8 +68,16 @@ class Selection { if (!this.rt) { return null; } - const idx = Math.round(cursorIdx); + let idx = Math.round(cursorIdx); const config = this.rt.attribute.textConfig as any; + for (let i = 0; i < config.length; i++) { + if (config[i].text !== '\n') { + idx--; + if (idx < 0) { + return config[i][key]; + } + } + } return config[Math.min(idx, config.length - 1)][key] ?? (this.rt.attribute as any)[key]; } getFormat(key: string): any { @@ -67,7 +91,7 @@ class Selection { if (minCursorIdx === maxCursorIdx) { return [this._getFormat(key, minCursorIdx)]; } - for (let i = minCursorIdx; i < maxCursorIdx; i++) { + for (let i = Math.ceil(minCursorIdx); i <= Math.floor(maxCursorIdx); i++) { const val = this._getFormat(key, i); val && valSet.add(val); } @@ -220,14 +244,77 @@ export class RichTextEditPlugin implements IPlugin { this.editModule.onChange(this.handleChange); } - handleKeyDown = (e: KeyboardEvent) => { - if (!(this.currRt && this.editing)) { + copyToClipboard(e: KeyboardEvent): boolean { + if ( + (application.global.isMacOS() && e.metaKey && e.key === 'c') || + (!application.global.isMacOS() && e.ctrlKey && e.key === 'c') + ) { + const selection = this.getSelection(); + const text = selection.getSelectionPureText(); + application.global.copyToClipBoard(text); + e.preventDefault(); + return true; + } + return false; + } + + /** + * 选中某一个区间,startIdx和endIdx分别是开始结束的光标位置 + * 设置光标为endIdx,设置开始位置为startIdx + * @param startIdx 开始位置 + * @param endIdx 结束位置 + * @returns + */ + selectionRange(startIdx: number, endIdx: number) { + const currRt = this.currRt; + if (!currRt) { return; } - const cache = this.currRt.getFrameCache(); + const cache = currRt.getFrameCache(); if (!cache) { return; } + + this.curCursorIdx = endIdx; + this.selectionStartCursorIdx = startIdx; + const { x, y1, y2 } = this.computedCursorPosByCursorIdx(this.selectionStartCursorIdx, this.currRt); + this.startCursorPos = { x, y: (y1 + y2) / 2 }; + const pos = this.computedCursorPosByCursorIdx(this.curCursorIdx, this.currRt); + this.setCursorAndTextArea(pos.x, pos.y1, pos.y2, this.currRt); + this._tryShowSelection(pos, cache); + } + + fullSelection(e: KeyboardEvent) { + if ( + (application.global.isMacOS() && e.metaKey && e.key === 'a') || + (!application.global.isMacOS() && e.ctrlKey && e.key === 'a') + ) { + const currRt = this.currRt; + if (!currRt) { + return; + } + const cache = currRt.getFrameCache(); + if (!cache) { + return; + } + const { lines } = cache; + const totalCursorCount = lines.reduce((total, line) => total + line.paragraphs.length, 0) - 1; + this.selectionRange(-0.1, totalCursorCount + 0.1); + + e.preventDefault(); + return true; + } + return false; + } + + directKey(e: KeyboardEvent) { + if (!(e.key === 'ArrowUp' || e.key === 'ArrowDown' || e.key === 'ArrowLeft' || e.key === 'ArrowRight')) { + return false; + } + const cache = this.currRt.getFrameCache(); + if (!cache) { + return false; + } let x = 0; let y = 0; if (e.key === 'ArrowUp') { @@ -296,6 +383,29 @@ export class RichTextEditPlugin implements IPlugin { this.selectionStartCursorIdx = cursorIdx; this.setCursorAndTextArea(data.x, data.y1, data.y2, this.currRt); } + + return true; + } + + handleKeyDown = (e: KeyboardEvent) => { + if (!(this.currRt && this.editing)) { + return; + } + // 复制到剪贴板 + // cmd/ctl + C + if (this.copyToClipboard(e)) { + return; + } + // 全选 + // cmd/ctl + A + if (this.fullSelection(e)) { + return; + } + // 方向键 + // 上、下、左、右 + if (this.directKey(e)) { + return; + } }; handleInput = (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => { @@ -440,12 +550,23 @@ export class RichTextEditPlugin implements IPlugin { if (!(cache && this.editBg && this.pointerDown && this.startCursorPos)) { return; } - let startCursorPos = this.startCursorPos; + const currCursorData = this.computedCursorPosByEvent(e, cache); if (!currCursorData) { return; } this.curCursorIdx = currCursorData.cursorIndex; + } + + _tryShowSelection( + currCursorData: { + x: any; + y1: number; + y2: number; + }, + cache: IRichTextFrame + ) { + let startCursorPos = this.startCursorPos; let endCursorPos = { x: currCursorData.x, y: (currCursorData.y1 + currCursorData.y2) / 2 @@ -521,7 +642,7 @@ export class RichTextEditPlugin implements IPlugin { } } - this.setCursorAndTextArea(currCursorData.x, currCursorData.y1 + 2, currCursorData.y2 - 2, e.target as IRichText); + this.setCursorAndTextArea(currCursorData.x, currCursorData.y1 + 2, currCursorData.y2 - 2, this.currRt as IRichText); this.triggerRender(); this.updateCbs.forEach(cb => cb('selection', this)); diff --git a/packages/vrender-kits/src/env/contributions/browser-contribution.ts b/packages/vrender-kits/src/env/contributions/browser-contribution.ts index 82fd1f493..65e73d100 100644 --- a/packages/vrender-kits/src/env/contributions/browser-contribution.ts +++ b/packages/vrender-kits/src/env/contributions/browser-contribution.ts @@ -62,6 +62,7 @@ export function createImageElement(src: string, isSvg: boolean = false): Promise export class BrowserEnvContribution extends BaseEnvContribution implements IEnvContribution { type: EnvType = 'browser'; supportEvent: boolean = true; + _isMacOS?: boolean; constructor() { super(); @@ -372,4 +373,26 @@ export class BrowserEnvContribution extends BaseEnvContribution implements IEnvC return { loadState: 'fail' } as { loadState: 'success' | 'fail' }; }); } + + isMacOS(): boolean { + if (this._isMacOS === void 0) { + try { + this._isMacOS = navigator.platform.toUpperCase().indexOf('MAC') >= 0; + } catch (err) { + this._isMacOS = false; + } + } + return this._isMacOS; + } + + copyToClipBoard(text: string): Promise { + return navigator.clipboard + .writeText(text) + .then(() => { + return; + }) + .catch(err => { + return; + }); + } } From a5cb20d3caa7f9055cbfdad291552ca3e0616534 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 16 Dec 2024 21:01:25 +0800 Subject: [PATCH 36/51] feat: support dblclick --- .../src/graphic/richtext/utils.ts | 4 +- .../builtin-plugin/richtext-edit-plugin.ts | 78 ++++++++++++++++--- .../browser/src/pages/richtext-editor.ts | 6 ++ 3 files changed, 76 insertions(+), 12 deletions(-) diff --git a/packages/vrender-core/src/graphic/richtext/utils.ts b/packages/vrender-core/src/graphic/richtext/utils.ts index 44bf509bf..ee1ae9889 100644 --- a/packages/vrender-core/src/graphic/richtext/utils.ts +++ b/packages/vrender-core/src/graphic/richtext/utils.ts @@ -240,7 +240,7 @@ export function testLetter2(string: string, index: number) { let i = index; // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行 while ( - (regLetter.test(string[i - 1]) && regLetter.test(string[i])) || + (regLetter.test(string[i + 1]) && regLetter.test(string[i])) || // 行首标点符号处理 regPunctuation.test(string[i]) ) { @@ -250,7 +250,7 @@ export function testLetter2(string: string, index: number) { return i; } } - return i; + return i + 1; } // 测量文字详细信息 diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index d1078a260..a1f58f32d 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -21,6 +21,7 @@ import type { import { Animate, DefaultTicker, DefaultTimeline } from '../../animate'; import { EditModule, findConfigIndex } from './edit-module'; import { application } from '../../application'; +import { testLetter, testLetter2 } from '../../graphic/richtext/utils'; type UpdateType = 'input' | 'change' | 'onfocus' | 'defocus' | 'selection' | 'dispatch'; @@ -238,6 +239,7 @@ export class RichTextEditPlugin implements IPlugin { context.stage.on('pointerdown', this.handlePointerDown); context.stage.on('pointerup', this.handlePointerUp); context.stage.on('pointerleave', this.handlePointerUp); + context.stage.on('dblclick', this.handleDBLClick); application.global.addEventListener('keydown', this.handleKeyDown); this.editModule.onInput(this.handleInput); @@ -274,7 +276,6 @@ export class RichTextEditPlugin implements IPlugin { if (!cache) { return; } - this.curCursorIdx = endIdx; this.selectionStartCursorIdx = startIdx; const { x, y1, y2 } = this.computedCursorPosByCursorIdx(this.selectionStartCursorIdx, this.currRt); @@ -433,6 +434,7 @@ export class RichTextEditPlugin implements IPlugin { context.stage.off('pointerdown', this.handlePointerDown); context.stage.off('pointerup', this.handlePointerUp); context.stage.off('pointerleave', this.handlePointerUp); + context.stage.off('dblclick', this.handleDBLClick); application.global.addEventListener('keydown', this.handleKeyDown); } @@ -445,7 +447,7 @@ export class RichTextEditPlugin implements IPlugin { this.handleEnter(e); (e.target as any).once('pointerleave', this.handleLeave); - this.tryShowSelection(e); + this.tryShowSelection(e, false); }; // 鼠标进入 @@ -473,6 +475,13 @@ export class RichTextEditPlugin implements IPlugin { handlePointerUp = (e: PointerEvent) => { this.pointerDown = false; }; + handleDBLClick = (e: PointerEvent) => { + if (!this.editing) { + return; + } + + this.tryShowSelection(e, true); + }; onFocus(e: PointerEvent) { this.deFocus(e); @@ -545,17 +554,40 @@ export class RichTextEditPlugin implements IPlugin { } // 显示selection - tryShowSelection(e: PointerEvent) { + tryShowSelection(e: PointerEvent, dblclick: boolean) { const cache = (e.target as IRichText).getFrameCache(); - if (!(cache && this.editBg && this.pointerDown && this.startCursorPos)) { + if (!(cache && this.editBg && this.startCursorPos)) { return; } - const currCursorData = this.computedCursorPosByEvent(e, cache); - if (!currCursorData) { - return; + if (!dblclick) { + if (this.pointerDown) { + const currCursorData = this.computedCursorPosByEvent(e, cache); + if (!currCursorData) { + return; + } + this.curCursorIdx = currCursorData.cursorIndex; + this._tryShowSelection(currCursorData, cache); + } + } else { + const currCursorData = this.computedCursorPosByEvent(e, cache); + if (!currCursorData) { + return; + } + const curCursorIdx = currCursorData.cursorIndex; + const lineInfo = currCursorData.lineInfo; + const columnIndex = lineInfo.paragraphs.findIndex(item => item === currCursorData.columnInfo); + if (columnIndex < 0) { + return; + } + const str = lineInfo.paragraphs.reduce((str, item) => { + return str + item.text; + }, ''); + const startIdx = testLetter(str, columnIndex); + const endIndex = testLetter2(str, columnIndex); + + this.selectionRange(curCursorIdx - (columnIndex - startIdx) - 0.9, curCursorIdx + (endIndex - columnIndex) - 0.9); } - this.curCursorIdx = currCursorData.cursorIndex; } _tryShowSelection( @@ -706,6 +738,13 @@ export class RichTextEditPlugin implements IPlugin { delta }; } + /* 工具函数 */ + /** + * 根据给定的ParagraphInfo得到对应的index + * @param cache 富文本缓存 + * @param cInfo ParagraphInfo + * @returns + */ protected getColumnIndex(cache: IRichTextFrame, cInfo: IRichTextParagraph | IRichTextIcon) { // TODO 【注意】认为cache都是单个字符拆分的 let inputIndex = -1; @@ -776,6 +815,12 @@ export class RichTextEditPlugin implements IPlugin { this.editModule.moveTo(out.x, out.y, rt, this.curCursorIdx, this.selectionStartCursorIdx); } + /** + * 根据Event算出光标位置等信息 + * @param e Event + * @param cache 富文本缓存 + * @returns + */ protected computedCursorPosByEvent(e: PointerEvent, cache: IRichTextFrame) { const p1 = this.getEventPosition(e); const lineInfo = this.getLineByPoint(cache, p1); @@ -801,11 +846,18 @@ export class RichTextEditPlugin implements IPlugin { x, y1, y2, - cursorIndex + cursorIndex, + lineInfo, + columnInfo }; } - // 根据cursorIdx计算出点的位置 + /** + * 根据cursorIdx计算出点的位置 + * @param cursorIdx index + * @param rt 富文本 + * @returns + */ protected computedCursorPosByCursorIdx(cursorIdx: number, rt: IRichText) { const idx = Math.round(cursorIdx); const leftRight = cursorIdx - idx; // >0 向右,<0 向左 @@ -829,6 +881,12 @@ export class RichTextEditPlugin implements IPlugin { return { x, y1, y2 }; } + /** + * 根据index获取columnInfo + * @param cache 缓存 + * @param index index + * @returns + */ protected getColumnByIndex( cache: IRichTextFrame, index: number diff --git a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts index 37485310b..f818fb714 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts @@ -246,6 +246,12 @@ export const page = () => { fontSize: 26, textAlign: 'center', fill: '#0f51b5' + }, + { + text: 'and this is our world, \nthat we call life', + fontSize: 26, + textAlign: 'center', + fill: '#0f51b5' } ] }) From 095e354bf45bf4225247871086c4151251ab8048 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 16 Dec 2024 21:58:05 +0800 Subject: [PATCH 37/51] feat: support richtext background, fix issue with selection --- .../src/graphic/richtext/paragraph.ts | 14 ++++++++++++++ .../src/interface/graphic/richText.ts | 4 ++++ .../builtin-plugin/richtext-edit-plugin.ts | 15 ++++++++++++--- .../browser/src/pages/richtext-editor.ts | 3 +++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/packages/vrender-core/src/graphic/richtext/paragraph.ts b/packages/vrender-core/src/graphic/richtext/paragraph.ts index 0751bff05..004f80396 100644 --- a/packages/vrender-core/src/graphic/richtext/paragraph.ts +++ b/packages/vrender-core/src/graphic/richtext/paragraph.ts @@ -209,6 +209,20 @@ export default class Paragraph { baseline = 0; } + if (this.character.fill) { + if (this.character.background && (!this.character.backgroundOpacity || this.character.backgroundOpacity > 0)) { + const fillStyle = ctx.fillStyle; + const globalAlpha = ctx.globalAlpha; + ctx.fillStyle = this.character.background; + if (this.character.backgroundOpacity !== void 0) { + ctx.globalAlpha = this.character.backgroundOpacity; + } + ctx.fillRect(left, baseline - this.ascent, this.widthOrigin || this.width, this.ascent + this.descent); + ctx.fillStyle = fillStyle; + ctx.globalAlpha = globalAlpha; + } + } + const { lineWidth = 1 } = this.character; if (this.character.stroke && lineWidth) { ctx.strokeText(text, left, baseline); diff --git a/packages/vrender-core/src/interface/graphic/richText.ts b/packages/vrender-core/src/interface/graphic/richText.ts index 01d788a52..2b30f468a 100644 --- a/packages/vrender-core/src/interface/graphic/richText.ts +++ b/packages/vrender-core/src/interface/graphic/richText.ts @@ -60,6 +60,10 @@ export type IRichTextParagraphCharacter = IRichTextBasicCharacter & { opacity?: number; fillOpacity?: number; strokeOpacity?: number; + // 仅支持纯色背景 + background?: string; + // 背景透明度 + backgroundOpacity?: number; // direction?: RichTextLayoutDirectionType; }; diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index a1f58f32d..80a54d2c5 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -574,7 +574,7 @@ export class RichTextEditPlugin implements IPlugin { if (!currCursorData) { return; } - const curCursorIdx = currCursorData.cursorIndex; + // const curCursorIdx = currCursorData.cursorIndex; const lineInfo = currCursorData.lineInfo; const columnIndex = lineInfo.paragraphs.findIndex(item => item === currCursorData.columnInfo); if (columnIndex < 0) { @@ -583,10 +583,19 @@ export class RichTextEditPlugin implements IPlugin { const str = lineInfo.paragraphs.reduce((str, item) => { return str + item.text; }, ''); + + let idx = 0; + for (let i = 0; i < cache.lines.length; i++) { + const line = cache.lines[i]; + if (line === lineInfo) { + break; + } + idx += line.paragraphs.length; + } + const startIdx = testLetter(str, columnIndex); const endIndex = testLetter2(str, columnIndex); - - this.selectionRange(curCursorIdx - (columnIndex - startIdx) - 0.9, curCursorIdx + (endIndex - columnIndex) - 0.9); + this.selectionRange(idx + startIdx - 0.1, idx + endIndex - 0.1); } } diff --git a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts index f818fb714..dcc11db5c 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts @@ -41,18 +41,21 @@ export const page = () => { text: '我', fontSize: 26, textAlign: 'center', + background: 'orange', fill: '#0f51b5' }, { text: '们', fontSize: 26, textAlign: 'center', + background: 'orange', fill: '#0f51b5' }, { text: '是', fontSize: 26, textAlign: 'center', + background: 'orange', fill: '#0f51b5' }, { From 2accbc23eebd879152a724fbfd9dcaef7c0b7521 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 11:57:03 +0800 Subject: [PATCH 38/51] feat: support pre-split with editable richtext --- packages/vrender-core/src/graphic/richtext.ts | 55 +++++++++++++++++-- .../src/graphic/richtext/utils.ts | 4 +- .../builtin-plugin/richtext-edit-plugin.ts | 44 +++++++-------- .../browser/src/pages/richtext-editor.ts | 9 +++ 4 files changed, 81 insertions(+), 31 deletions(-) diff --git a/packages/vrender-core/src/graphic/richtext.ts b/packages/vrender-core/src/graphic/richtext.ts index 19f06243b..b4b5c0526 100644 --- a/packages/vrender-core/src/graphic/richtext.ts +++ b/packages/vrender-core/src/graphic/richtext.ts @@ -1,5 +1,5 @@ import type { IAABBBounds } from '@visactor/vutils'; -import { isNumber } from '@visactor/vutils'; +import { isNumber, isString } from '@visactor/vutils'; import type { IRichText, IRichTextCharacter, @@ -13,7 +13,9 @@ import type { IStage, ILayer, IRichTextIcon, - EventPoint + EventPoint, + IRichTextFrame, + ISetAttributeContext } from '../interface'; import { Graphic, GRAPHIC_UPDATE_TAG_KEY, NOWORK_ANIMATE_ATTR } from './graphic'; import { DefaultRichTextAttribute } from './config'; @@ -187,6 +189,42 @@ export class RichText extends Graphic implements IRic return getTheme(this).richtext; } + static AllSingleCharacter(cache: IRichTextFrame | IRichTextGraphicAttribute['textConfig']) { + if ((cache as IRichTextFrame).lines) { + const frame = cache as IRichTextFrame; + return frame.lines.every(line => + line.paragraphs.every(item => !(item.text && isString(item.text) && RichText.splitText(item.text).length > 1)) + ); + } + const tc = cache as IRichTextGraphicAttribute['textConfig']; + return tc.every( + item => !((item as any).text && isString((item as any).text) && RichText.splitText((item as any).text).length > 1) + ); + } + + static splitText(text: string) { + // 😁这种emoji长度算两个,所以得处理一下 + return Array.from(text); + } + + static TransformTextConfig2SingleCharacter(textConfig: IRichTextGraphicAttribute['textConfig']) { + const tc: IRichTextGraphicAttribute['textConfig'] = []; + textConfig.forEach((item: IRichTextParagraphCharacter) => { + const textList = RichText.splitText(item.text.toString()); + if (isString(item.text) && textList.length > 1) { + // 拆分 + for (let i = 0; i < textList.length; i++) { + const t = textList[i]; + tc.push({ ...item, text: t }); + } + } else { + tc.push(item); + } + }); + + return tc; + } + protected updateAABBBounds( attribute: IRichTextGraphicAttribute, richtextTheme: Required, @@ -321,7 +359,6 @@ export class RichText extends Graphic implements IRic doUpdateFrameCache(tc?: IRichTextCharacter[]) { // 1. 测量,生成paragraph const { - textConfig: _tc = [], maxWidth, maxHeight, width, @@ -333,8 +370,18 @@ export class RichText extends Graphic implements IRic textBaseline, layoutDirection, singleLine, - disableAutoWrapLine + disableAutoWrapLine, + editable } = this.attribute; + + let { textConfig: _tc = [] } = this.attribute; + + // 预处理editable,将textConfig中的text转换为单个字符 + if (editable && _tc.length > 0 && !RichText.AllSingleCharacter(_tc)) { + _tc = RichText.TransformTextConfig2SingleCharacter(_tc); + this.attribute.textConfig = _tc; + } + const paragraphs: (Paragraph | RichTextIcon)[] = []; const textConfig = tc ?? _tc; diff --git a/packages/vrender-core/src/graphic/richtext/utils.ts b/packages/vrender-core/src/graphic/richtext/utils.ts index ee1ae9889..ef75755e1 100644 --- a/packages/vrender-core/src/graphic/richtext/utils.ts +++ b/packages/vrender-core/src/graphic/richtext/utils.ts @@ -325,8 +325,8 @@ export function measureTextCanvas( result.descent = 0; } else { result.width = Math.floor(measurement.width); - result.height = Math.floor(measurement.actualBoundingBoxAscent + measurement.actualBoundingBoxDescent); - result.ascent = Math.floor(measurement.actualBoundingBoxAscent); + result.height = Math.floor(measurement.fontBoundingBoxAscent + measurement.fontBoundingBoxDescent); + result.ascent = Math.floor(measurement.fontBoundingBoxAscent); result.descent = result.height - result.ascent; } return result; diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 80a54d2c5..afceb3214 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -1,7 +1,7 @@ import type { IPointLike } from '@visactor/vutils'; import { isObject, isString, max, merge } from '@visactor/vutils'; import { Generator } from '../../common/generator'; -import { createGroup, createLine, createRect } from '../../graphic'; +import { createGroup, createLine, createRect, RichText } from '../../graphic'; import type { IGroup, ILine, @@ -138,33 +138,27 @@ export class RichTextEditPlugin implements IPlugin { protected declare deltaX: number; protected declare deltaY: number; - static splitText(text: string) { - // 😁这种emoji长度算两个,所以得处理一下 - return Array.from(text); - } + // static splitText(text: string) { + // // 😁这种emoji长度算两个,所以得处理一下 + // return Array.from(text); + // } static tryUpdateRichtext(richtext: IRichText) { const cache = richtext.getFrameCache(); - if ( - !cache.lines.every(line => - line.paragraphs.every( - item => !(item.text && isString(item.text) && RichTextEditPlugin.splitText(item.text).length > 1) - ) - ) - ) { - const tc: IRichTextCharacter[] = []; - richtext.attribute.textConfig.forEach((item: IRichTextParagraphCharacter) => { - const textList = RichTextEditPlugin.splitText(item.text.toString()); - if (isString(item.text) && textList.length > 1) { - // 拆分 - for (let i = 0; i < textList.length; i++) { - const t = textList[i]; - tc.push({ ...item, text: t }); - } - } else { - tc.push(item); - } - }); + if (!RichText.AllSingleCharacter(cache)) { + const tc = RichText.TransformTextConfig2SingleCharacter(richtext.attribute.textConfig); + // richtext.attribute.textConfig.forEach((item: IRichTextParagraphCharacter) => { + // const textList = RichTextEditPlugin.splitText(item.text.toString()); + // if (isString(item.text) && textList.length > 1) { + // // 拆分 + // for (let i = 0; i < textList.length; i++) { + // const t = textList[i]; + // tc.push({ ...item, text: t }); + // } + // } else { + // tc.push(item); + // } + // }); richtext.setAttributes({ textConfig: tc }); richtext.doUpdateFrameCache(tc); } diff --git a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts index dcc11db5c..a42215746 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts @@ -244,6 +244,13 @@ export const page = () => { textAlign: 'center', fill: '#0f51b5' }, + { + text: '[4]', + script: 'super', + fontSize: 26, + textAlign: 'center', + fill: '#0f51b5' + }, { text: '风\n', fontSize: 26, @@ -260,6 +267,8 @@ export const page = () => { }) ); + console.log(shapes[0]); + const stage = createStage({ canvas: 'main', width: 1200, From 65a055e027259b9de07652ded99143ecf5798e4e Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 12:09:42 +0800 Subject: [PATCH 39/51] feat: disable historyUndo --- .../src/plugins/builtin-plugin/edit-module.ts | 3 + .../browser/src/pages/richtext-editor.ts | 114 ++++++++++++------ 2 files changed, 79 insertions(+), 38 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index eaad05562..f2fb7ab9d 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -160,6 +160,9 @@ export class EditModule { if (!this.currRt) { return; } + if (ev.inputType === 'historyUndo') { + return; + } // 如果是回车,那就不往后+1 const { textConfig = [], ...rest } = this.currRt.attribute; diff --git a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts index a42215746..b26753724 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts @@ -28,9 +28,10 @@ export const page = () => { shapes.push( createRichText({ visible: true, - fontSize: 26, + fontSize: 16, _debug_bounds: true, width: 0, + height: 0, x: 100, y: 100, editable: true, @@ -39,227 +40,264 @@ export const page = () => { textConfig: [ { text: '我', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', background: 'orange', fill: '#0f51b5' }, { text: '们', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', background: 'orange', fill: '#0f51b5' }, { text: '是', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', background: 'orange', fill: '#0f51b5' }, { text: '无', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '缘', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: 'a', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '无', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '故', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '的', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '尘😁', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '埃\n', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '无', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '缘', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '无', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '故', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '的', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '游', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '走\n', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '黑', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '暗', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '只', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '需', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '要', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '张', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '开', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '一', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '张', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '缝', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '隙\n', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '就', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '能', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '挂', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '起', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '飓', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '[4]', script: 'super', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: '风\n', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' }, { text: 'and this is our world, \nthat we call life', - fontSize: 26, + fontSize: 16, + lineHeight: 26, textAlign: 'center', fill: '#0f51b5' } From f0d3f3715133e0c1f6906c50d1d6497dc1f1e06d Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 12:12:42 +0800 Subject: [PATCH 40/51] feat: set shadowRoot on the top --- .../src/plugins/builtin-plugin/richtext-edit-plugin.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index afceb3214..784ee535d 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -492,8 +492,8 @@ export class RichTextEditPlugin implements IPlugin { // 计算全局偏移 this.computeGlobalDelta(cache); - // 添加cursor节点 - shadowRoot.setAttributes({ shadowRootIdx: -1, x: this.deltaX, y: this.deltaY }); + // 添加cursor节点,shadowRoot在上面 + shadowRoot.setAttributes({ shadowRootIdx: 1, pickable: false, x: this.deltaX, y: this.deltaY }); if (!this.editLine) { const line = createLine({ x: 0, y: 0, lineWidth: 1, stroke: 'black' }); // 不使用stage的Ticker,避免影响其他的动画以及受到其他动画影响 From f1ad49c36c5ec121cb4019f52cdac07698845c7a Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 15:24:15 +0800 Subject: [PATCH 41/51] fix: fix issue with composing input --- packages/vrender-core/src/graphic/richtext.ts | 5 ++++- .../vrender-core/src/plugins/builtin-plugin/edit-module.ts | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/vrender-core/src/graphic/richtext.ts b/packages/vrender-core/src/graphic/richtext.ts index b4b5c0526..21b68213c 100644 --- a/packages/vrender-core/src/graphic/richtext.ts +++ b/packages/vrender-core/src/graphic/richtext.ts @@ -196,9 +196,12 @@ export class RichText extends Graphic implements IRic line.paragraphs.every(item => !(item.text && isString(item.text) && RichText.splitText(item.text).length > 1)) ); } + // isComposing的不算 const tc = cache as IRichTextGraphicAttribute['textConfig']; return tc.every( - item => !((item as any).text && isString((item as any).text) && RichText.splitText((item as any).text).length > 1) + item => + (item as any).isComposing || + !((item as any).text && isString((item as any).text) && RichText.splitText((item as any).text).length > 1) ); } diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index f2fb7ab9d..8ff772330 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -142,7 +142,7 @@ export class EditModule { const text = (lastConfig as any).text; const textList: string[] = text ? Array.from(text.toString()) : []; for (let i = 0; i < textList.length; i++) { - textConfig.splice(i + configIdx, 0, { ...lastConfig, text: textList[i] }); + textConfig.splice(i + configIdx, 0, { ...lastConfig, isComposing: false, text: textList[i] } as any); } this.currRt.setAttributes({ textConfig }); this.onChangeCbList.forEach(cb => { @@ -231,6 +231,7 @@ export class EditModule { textConfig.splice(startIdx, 0, currConfig); } (currConfig as any).text = str; + currConfig.isComposing = this.isComposing; if (!textConfig.length) { textConfig.push(currConfig); } From a35c68881620b0f3cdf075fc154eb95a5cca4d44 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 15:57:33 +0800 Subject: [PATCH 42/51] fix: fix issue with selection range --- .../src/graphic/richtext/utils.ts | 36 +++ .../builtin-plugin/richtext-edit-plugin.ts | 18 +- .../browser/src/pages/richtext-editor.ts | 256 ------------------ 3 files changed, 50 insertions(+), 260 deletions(-) diff --git a/packages/vrender-core/src/graphic/richtext/utils.ts b/packages/vrender-core/src/graphic/richtext/utils.ts index ef75755e1..af7668617 100644 --- a/packages/vrender-core/src/graphic/richtext/utils.ts +++ b/packages/vrender-core/src/graphic/richtext/utils.ts @@ -206,6 +206,42 @@ export function getStrByWithCanvas( return index; } +export function getWordStartEndIdx(string: string, index: number) { + let startIdx = index; + // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行 + while ( + (regLetter.test(string[startIdx - 1]) && regLetter.test(string[startIdx])) || + // 行首标点符号处理 + regPunctuation.test(string[startIdx]) + ) { + startIdx--; + // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环 + if (startIdx <= 0) { + break; + } + } + + let endIdx = index; + // 切分前后都是英文字母数字下划线,向前找到非英文字母处换行 + while ( + (regLetter.test(string[endIdx + 1]) && regLetter.test(string[endIdx])) || + // 行首标点符号处理 + regPunctuation.test(string[endIdx]) + ) { + endIdx++; + // 无法满足所有条件,放弃匹配,直接截断,避免陷入死循环 + if (endIdx >= string.length) { + break; + } + } + endIdx = Math.min(endIdx + 1, string.length); + + return { + startIdx, + endIdx + }; +} + /** * 向前找到单词结尾处换行 * @param string diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 784ee535d..cb56d80b4 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -21,7 +21,8 @@ import type { import { Animate, DefaultTicker, DefaultTimeline } from '../../animate'; import { EditModule, findConfigIndex } from './edit-module'; import { application } from '../../application'; -import { testLetter, testLetter2 } from '../../graphic/richtext/utils'; +import { getWordStartEndIdx } from '../../graphic/richtext/utils'; +// import { testLetter, testLetter2 } from '../../graphic/richtext/utils'; type UpdateType = 'input' | 'change' | 'onfocus' | 'defocus' | 'selection' | 'dispatch'; @@ -270,6 +271,15 @@ export class RichTextEditPlugin implements IPlugin { if (!cache) { return; } + // 对startIdx和endIdx约束 + const { lines } = cache; + const totalCursorCount = lines.reduce((total, line) => total + line.paragraphs.length, 0) - 1; + if (startIdx > endIdx) { + [startIdx, endIdx] = [endIdx, startIdx]; + } + startIdx = Math.min(Math.max(startIdx, -0.1), totalCursorCount + 0.1); + endIdx = Math.min(Math.max(endIdx, -0.1), totalCursorCount + 0.1); + this.curCursorIdx = endIdx; this.selectionStartCursorIdx = startIdx; const { x, y1, y2 } = this.computedCursorPosByCursorIdx(this.selectionStartCursorIdx, this.currRt); @@ -587,9 +597,9 @@ export class RichTextEditPlugin implements IPlugin { idx += line.paragraphs.length; } - const startIdx = testLetter(str, columnIndex); - const endIndex = testLetter2(str, columnIndex); - this.selectionRange(idx + startIdx - 0.1, idx + endIndex - 0.1); + const { startIdx, endIdx } = getWordStartEndIdx(str, columnIndex); + + this.selectionRange(idx + startIdx - 0.1, idx + endIdx - 0.1); } } diff --git a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts index b26753724..05e23ac77 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts @@ -38,262 +38,6 @@ export const page = () => { // background: 'green', // "textAlign": "center", textConfig: [ - { - text: '我', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - background: 'orange', - fill: '#0f51b5' - }, - { - text: '们', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - background: 'orange', - fill: '#0f51b5' - }, - { - text: '是', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - background: 'orange', - fill: '#0f51b5' - }, - { - text: '无', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '缘', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: 'a', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '无', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '故', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '的', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '尘😁', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '埃\n', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '无', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '缘', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '无', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '故', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '的', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '游', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '走\n', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '黑', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '暗', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '只', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '需', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '要', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '张', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '开', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '一', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '张', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '缝', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '隙\n', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '就', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '能', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '挂', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '起', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '飓', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '[4]', - script: 'super', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, - { - text: '风\n', - fontSize: 16, - lineHeight: 26, - textAlign: 'center', - fill: '#0f51b5' - }, { text: 'and this is our world, \nthat we call life', fontSize: 16, From 466ffa1c82d14dc2d0d75156e69a71490ac8e661 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 20:07:54 +0800 Subject: [PATCH 43/51] feat: support multi break-line --- packages/vrender-core/src/graphic/richtext.ts | 23 +++++++-- .../src/plugins/builtin-plugin/edit-module.ts | 49 ++++++++++++------- .../builtin-plugin/richtext-edit-plugin.ts | 6 +-- .../browser/src/pages/richtext-editor.ts | 2 +- 4 files changed, 53 insertions(+), 27 deletions(-) diff --git a/packages/vrender-core/src/graphic/richtext.ts b/packages/vrender-core/src/graphic/richtext.ts index 21b68213c..750ba4cbf 100644 --- a/packages/vrender-core/src/graphic/richtext.ts +++ b/packages/vrender-core/src/graphic/richtext.ts @@ -478,6 +478,9 @@ export class RichText extends Graphic implements IRic this._frameCache?.icons ); const wrapper = new Wrapper(frame); + // @since 0.22.0 + // 如果可编辑的话,则支持多换行符 + wrapper.newLine = editable; if (disableAutoWrapLine) { let lineCount = 0; let skip = false; @@ -508,11 +511,11 @@ export class RichText extends Graphic implements IRic } } else { for (let i = 0; i < paragraphs.length; i++) { - if (i === paragraphs.length - 1) { - wrapper.newLine = true; - } + // if (i === paragraphs.length - 1) { + // wrapper.newLine = true; + // } wrapper.deal(paragraphs[i]); - wrapper.newLine = false; + // wrapper.newLine = false; } } @@ -540,6 +543,18 @@ export class RichText extends Graphic implements IRic }); } + // 处理空行 + if (editable) { + frame.lines.forEach(item => { + const lastParagraphs = item.paragraphs; + item.paragraphs = item.paragraphs.filter(p => (p as any).text !== ''); + if (item.paragraphs.length === 0 && lastParagraphs.length) { + (lastParagraphs[0] as any).text = '\n'; + item.paragraphs.push(lastParagraphs[0]); + } + }); + } + this._frameCache = frame; // this.bindIconEvent(); diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 8ff772330..95dfd2f7c 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -1,13 +1,6 @@ import { application } from '../../application'; import type { IRichText, IRichTextCharacter, IRichTextParagraphCharacter } from '../../interface'; -let isMac = false; -try { - isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0; -} catch (err) { - // ignore -} - function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) { let idx = 0; for (let i = 0; i < textConfig.length; i++) { @@ -20,22 +13,27 @@ function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) { } /** - * 找到cursorIndex所在的textConfig的位置,忽略换行符 + * 找到cursorIndex所在的textConfig的位置,忽略单个换行符,连续换行符的时候只忽略第一个 * @param textConfig * @param cursorIndex * @returns */ -export function findConfigIndex(textConfig: IRichTextCharacter[], cursorIndex: number): number { +export function findConfigIndexByCursorIdx(textConfig: IRichTextCharacter[], cursorIndex: number): number { let index = 0; // 小于0是在最前面了 if (cursorIndex < 0) { return -1; } let idx = Math.round(cursorIndex); + let lastLineBreak = true; for (index = 0; index < textConfig.length; index++) { const c = textConfig[index] as IRichTextParagraphCharacter; - if (c.text !== '\n') { + if (c.text === '\n') { + idx -= Number(lastLineBreak); + lastLineBreak = true; + } else { idx--; + lastLineBreak = false; } if (idx < 0) { break; @@ -49,16 +47,29 @@ export function findConfigIndex(textConfig: IRichTextCharacter[], cursorIndex: n return Math.min(index, textConfig.length - 1); } -export function textConfigIgnoreLinebreakIdxToCursorIdx(textConfig: IRichTextCharacter[], cursorIndex: number): number { +export function findCursorIdxByConfigIndex(textConfig: IRichTextCharacter[], configIndex: number): number { let index = 0; - for (let i = 0; i < cursorIndex; i++) { + // 仅有一个\n,那不算 + // 如果有连续的\n,那就少算一个 + let lastLineBreak = true; + let delta = 0; + for (let i = 0; i <= configIndex + delta; i++) { const c = textConfig[i] as IRichTextParagraphCharacter; - if (c.text !== '\n') { + if (c.text === '\n') { + index += Number(lastLineBreak); + // 第一个换行符当做不存在 + delta += 1 - Number(lastLineBreak); + lastLineBreak = true; + } else { index++; + lastLineBreak = false; + // 回归 + delta = 0; } } + index = Math.max(index - 1, 0); // 正常Cursor是放在右边的,但如果回退到换行符了,那就放在左侧 - if ((textConfig[cursorIndex] as any)?.text === '\n') { + if ((textConfig[configIndex] as any)?.text === '\n') { index -= 0.1; } else { index += 0.1; @@ -124,7 +135,7 @@ export class EditModule { const config = textConfig[0]; textConfig.unshift({ fill: 'black', ...config, text: '' }); } else { - const cursorIndex = findConfigIndex(textConfig, this.cursorIndex); + const cursorIndex = findConfigIndexByCursorIdx(textConfig, this.cursorIndex); const lastConfig = textConfig[cursorIndex]; textConfig.splice(cursorIndex + 1, 0, { ...lastConfig, text: '' }); } @@ -135,7 +146,7 @@ export class EditModule { this.isComposing = false; // 拆分上一次的内容 const { textConfig = [] } = this.currRt.attribute; - const configIdx = findConfigIndex(textConfig, this.cursorIndex + 1); + const configIdx = findConfigIndexByCursorIdx(textConfig, this.cursorIndex + 1); const lastConfig = textConfig[configIdx]; textConfig.splice(configIdx, 1); @@ -187,9 +198,9 @@ export class EditModule { // 转换成基于textConfig的 // let delta = 0; - startIdx = findConfigIndex(textConfig, startIdx); + startIdx = findConfigIndexByCursorIdx(textConfig, startIdx); // delta = this.selectionStartCursorIdx - startIdx; - endIdx = findConfigIndex(textConfig, endIdx); + endIdx = findConfigIndexByCursorIdx(textConfig, endIdx); // console.log(startIdx, delta, endIdx); let idxDelta = 0; @@ -238,7 +249,7 @@ export class EditModule { } this.currRt.setAttributes({ textConfig }); - this.cursorIndex = textConfigIgnoreLinebreakIdxToCursorIdx(textConfig, startIdx); + this.cursorIndex = findCursorIdxByConfigIndex(textConfig, startIdx); this.cursorIndex += idxDelta; if (!this.isComposing) { diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index cb56d80b4..681e630f5 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -19,7 +19,7 @@ import type { ITimeline } from '../../interface'; import { Animate, DefaultTicker, DefaultTimeline } from '../../animate'; -import { EditModule, findConfigIndex } from './edit-module'; +import { EditModule, findConfigIndexByCursorIdx } from './edit-module'; import { application } from '../../application'; import { getWordStartEndIdx } from '../../graphic/richtext/utils'; // import { testLetter, testLetter2 } from '../../graphic/richtext/utils'; @@ -48,8 +48,8 @@ class Selection { return ''; } const config = this.rt.attribute.textConfig as any; - const startIdx = findConfigIndex(config, Math.ceil(minCursorIdx)); - const endIdx = findConfigIndex(config, Math.floor(maxCursorIdx)); + const startIdx = findConfigIndexByCursorIdx(config, Math.ceil(minCursorIdx)); + const endIdx = findConfigIndexByCursorIdx(config, Math.floor(maxCursorIdx)); let str = ''; for (let i = startIdx; i <= endIdx; i++) { str += config[i].text; diff --git a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts index 05e23ac77..39abbfe4a 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts @@ -39,7 +39,7 @@ export const page = () => { // "textAlign": "center", textConfig: [ { - text: 'and this is our world, \nthat we call life', + text: 'and', fontSize: 16, lineHeight: 26, textAlign: 'center', From dea9e13b155db36cd6b68fccb9d660262ee978f9 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 20:48:12 +0800 Subject: [PATCH 44/51] feat: support focus listener --- .../src/plugins/builtin-plugin/edit-module.ts | 30 ++ .../builtin-plugin/richtext-edit-plugin.ts | 34 ++- .../browser/src/pages/richtext-editor.ts | 258 +++++++++++++++++- 3 files changed, 317 insertions(+), 5 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 95dfd2f7c..a00b73fa5 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -88,6 +88,9 @@ export class EditModule { onInputCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>; // change的回调(composing确认才会触发) onChangeCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>; + onFocusInList: Array<() => void>; + onFocusOutList: Array<() => void>; + focusOutTimer: number; constructor(container?: HTMLElement) { this.container = container ?? document.body; @@ -101,6 +104,8 @@ export class EditModule { this.isComposing = false; this.onInputCbList = []; this.onChangeCbList = []; + this.onFocusInList = []; + this.onFocusOutList = []; } onInput(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void) { @@ -111,6 +116,14 @@ export class EditModule { this.onChangeCbList.push(cb); } + onFocusIn(cb: () => void) { + this.onFocusInList.push(cb); + } + + onFocusOut(cb: () => void) { + this.onFocusOutList.push(cb); + } + applyStyle(textAreaDom: HTMLTextAreaElement) { textAreaDom.setAttribute( 'style', @@ -120,9 +133,24 @@ export class EditModule { textAreaDom.addEventListener('input', this.handleInput); textAreaDom.addEventListener('compositionstart', this.handleCompositionStart); textAreaDom.addEventListener('compositionend', this.handleCompositionEnd); + // 监听焦点 + textAreaDom.addEventListener('focusin', this.handleFocusIn); + textAreaDom.addEventListener('focusout', this.handleFocusOut); application.global.addEventListener('keydown', this.handleKeyDown); } + handleFocusIn = () => { + this.focusOutTimer && clearTimeout(this.focusOutTimer); + this.focusOutTimer = 0; + this.onFocusInList && this.onFocusInList.forEach(cb => cb()); + }; + handleFocusOut = () => { + // 延时触发,避免误关闭 + this.focusOutTimer = setTimeout(() => { + this.onFocusOutList && this.onFocusOutList.forEach(cb => cb()); + }, 100); + }; + handleKeyDown = (e: KeyboardEvent) => { if (e.key === 'Delete' || e.key === 'Backspace') { this.handleInput({ data: null, type: 'Backspace' }); @@ -280,6 +308,8 @@ export class EditModule { this.textAreaDom.removeEventListener('input', this.handleInput); this.textAreaDom.removeEventListener('compositionstart', this.handleCompositionStart); this.textAreaDom.removeEventListener('compositionend', this.handleCompositionEnd); + this.textAreaDom.addEventListener('focusin', this.handleFocusOut); + this.textAreaDom.addEventListener('focusout', this.handleFocusOut); application.global.removeEventListener('keydown', this.handleKeyDown); } } diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 681e630f5..59970fda8 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -239,6 +239,7 @@ export class RichTextEditPlugin implements IPlugin { this.editModule.onInput(this.handleInput); this.editModule.onChange(this.handleChange); + this.editModule.onFocusOut(this.handleFocusOut); } copyToClipboard(e: KeyboardEvent): boolean { @@ -334,6 +335,8 @@ export class RichTextEditPlugin implements IPlugin { // const pos = this.computedCursorPosByCursorIdx(this.curCursorIdx, this.currRt); const { lineInfo, columnInfo } = this.getColumnByIndex(cache, Math.round(this.curCursorIdx)); + const { lines } = cache; + const totalCursorCount = lines.reduce((total, line) => total + line.paragraphs.length, 0) - 1; if (x) { // 快接近首尾需要特殊处理 if ( @@ -355,6 +358,11 @@ export class RichTextEditPlugin implements IPlugin { } else { this.curCursorIdx += x; } + if (this.curCursorIdx < -0.1) { + this.curCursorIdx = -0.1; + } else if (this.curCursorIdx > totalCursorCount + 0.1) { + this.curCursorIdx = totalCursorCount + 0.1; + } const pos = this.computedCursorPosByCursorIdx(this.curCursorIdx, this.currRt); this.setCursorAndTextArea(pos.x, pos.y1, pos.y2, this.currRt); @@ -381,9 +389,15 @@ export class RichTextEditPlugin implements IPlugin { if (!columnInfo) { return; } - const cursorIdx = this.getColumnIndex(cache, columnInfo) + delta; + let cursorIdx = this.getColumnIndex(cache, columnInfo) + delta; const data = this.computedCursorPosByCursorIdx(cursorIdx, this.currRt); + if (cursorIdx < -0.1) { + cursorIdx = -0.1; + } else if (cursorIdx > totalCursorCount + 0.1) { + cursorIdx = totalCursorCount + 0.1; + } + this.curCursorIdx = cursorIdx; this.selectionStartCursorIdx = cursorIdx; this.setCursorAndTextArea(data.x, data.y1, data.y2, this.currRt); @@ -432,6 +446,18 @@ export class RichTextEditPlugin implements IPlugin { this.updateCbs.forEach(cb => cb('change', this)); }; + handleFocusIn = () => { + // this.updateCbs.forEach(cb => cb(this.editing ? 'onfocus' : 'defocus', this)); + }; + + handleFocusOut = () => { + this.editing = false; + this.deFocus(); + this.pointerDown = false; + this.triggerRender(); + this.updateCbs.forEach(cb => cb('defocus', this)); + }; + deactivate(context: IPluginService): void { // context.stage.off('pointerdown', this.handleClick); context.stage.off('pointermove', this.handleMove); @@ -470,7 +496,7 @@ export class RichTextEditPlugin implements IPlugin { if (this.editing) { this.onFocus(e); } else { - this.deFocus(e); + this.deFocus(); } this.triggerRender(); this.pointerDown = true; @@ -488,7 +514,7 @@ export class RichTextEditPlugin implements IPlugin { }; onFocus(e: PointerEvent) { - this.deFocus(e); + this.deFocus(); this.currRt = e.target as IRichText; // 创建shadowGraphic @@ -528,7 +554,7 @@ export class RichTextEditPlugin implements IPlugin { } } - protected deFocus(e: PointerEvent) { + protected deFocus() { const target = this.currRt as IRichText; if (!target) { return; diff --git a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts index 39abbfe4a..b26753724 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts @@ -39,7 +39,263 @@ export const page = () => { // "textAlign": "center", textConfig: [ { - text: 'and', + text: '我', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + }, + { + text: '们', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + }, + { + text: '是', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + }, + { + text: '无', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '缘', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: 'a', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '无', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '故', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '的', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '尘😁', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '埃\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '无', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '缘', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '无', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '故', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '的', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '游', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '走\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '黑', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '暗', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '只', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '需', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '要', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '张', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '开', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '一', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '张', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '缝', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '隙\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '就', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '能', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '挂', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '起', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '飓', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '[4]', + script: 'super', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: '风\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + fill: '#0f51b5' + }, + { + text: 'and this is our world, \nthat we call life', fontSize: 16, lineHeight: 26, textAlign: 'center', From 1f08402a229fd838335cd38ec7a6bee4092cbf4e Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 20:53:04 +0800 Subject: [PATCH 45/51] fix: fix issue with lose style when clear all character --- packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index a00b73fa5..5ef12731d 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -265,7 +265,7 @@ export class EditModule { } if (!this.isComposing) { - currConfig = { ...lastConfig, text: '' }; + currConfig = { fill: 'black', ...lastConfig, text: '' }; startIdx += 1; textConfig.splice(startIdx, 0, currConfig); } From 4b00c1d151e92738190a34d039c123ec0122f220 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 21:05:35 +0800 Subject: [PATCH 46/51] fix: fix issue when apply style --- .../src/plugins/builtin-plugin/edit-module.ts | 15 ++++++++------- .../builtin-plugin/richtext-edit-plugin.ts | 4 +++- .../browser/src/pages/richtext-editor.ts | 2 +- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 5ef12731d..92291f8e7 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -140,15 +140,16 @@ export class EditModule { } handleFocusIn = () => { - this.focusOutTimer && clearTimeout(this.focusOutTimer); - this.focusOutTimer = 0; - this.onFocusInList && this.onFocusInList.forEach(cb => cb()); + // this.focusOutTimer && clearTimeout(this.focusOutTimer); + // this.focusOutTimer = 0; + // this.onFocusInList && this.onFocusInList.forEach(cb => cb()); }; handleFocusOut = () => { - // 延时触发,避免误关闭 - this.focusOutTimer = setTimeout(() => { - this.onFocusOutList && this.onFocusOutList.forEach(cb => cb()); - }, 100); + // 暂时注释,会导致非期待情况下的误关闭 + // // 延时触发,避免误关闭 + // this.focusOutTimer = setTimeout(() => { + // this.onFocusOutList && this.onFocusOutList.forEach(cb => cb()); + // }, 100); }; handleKeyDown = (e: KeyboardEvent) => { diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 59970fda8..66518a260 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -195,7 +195,9 @@ export class RichTextEditPlugin implements IPlugin { const { selectionStartCursorIdx, curCursorIdx } = selectionData; const minCursorIdx = Math.min(selectionStartCursorIdx, curCursorIdx); const maxCursorIdx = Math.max(selectionStartCursorIdx, curCursorIdx); - const config = rt.attribute.textConfig.slice(minCursorIdx + 1, maxCursorIdx + 1); + const minConfigIdx = findConfigIndexByCursorIdx(rt.attribute.textConfig, minCursorIdx); + const maxConfigIdx = findConfigIndexByCursorIdx(rt.attribute.textConfig, maxCursorIdx); + const config = rt.attribute.textConfig.slice(minConfigIdx + 1, maxConfigIdx + 1); if (payload === 'bold') { config.forEach((item: IRichTextParagraphCharacter) => (item.fontWeight = 'bold')); } else if (payload === 'italic') { diff --git a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts index b26753724..99c1d1cb4 100644 --- a/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts +++ b/packages/vrender/__tests__/browser/src/pages/richtext-editor.ts @@ -338,7 +338,7 @@ export const page = () => { } }); - ['bold', 'italic', 'underline', 'lineThrough', { fill: 'red' }].forEach(item => { + ['bold', 'italic', 'underline', 'lineThrough', { fill: 'red' }, { background: 'pink' }].forEach(item => { const btn = document.createElement('button'); btn.innerHTML = typeof item === 'string' ? item : JSON.stringify(item); btn.addEventListener('click', () => { From 80325dc5ddf3441983afafafbdd640211ad3410b Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Tue, 17 Dec 2024 21:21:15 +0800 Subject: [PATCH 47/51] fix: fix issue when input in richtext --- .../vrender-core/src/plugins/builtin-plugin/edit-module.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 92291f8e7..ef5ae6118 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -39,7 +39,8 @@ export function findConfigIndexByCursorIdx(textConfig: IRichTextCharacter[], cur break; } } - if (cursorIndex - Math.round(cursorIndex) < 0) { + // 换行符永远往前走一格 + if (cursorIndex - Math.round(cursorIndex) < 0 || (textConfig[index] as IRichTextParagraphCharacter).text === '\n') { index--; } index = Math.max(index, 0); From 6f6dbbb40ffdd52a20f45f28453b6c3e8f0896e0 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 19 Dec 2024 17:14:05 +0800 Subject: [PATCH 48/51] fix: fix issue with richtext edit multiline --- .../richtext_editor/richtext_editor.test.ts | 279 ++++++++++++++++ packages/vrender-core/src/index.ts | 1 + .../src/plugins/builtin-plugin/edit-module.ts | 300 +++++++++++------- .../builtin-plugin/richtext-edit-plugin.ts | 2 +- 4 files changed, 462 insertions(+), 120 deletions(-) create mode 100644 packages/vrender-core/__tests__/richtext_editor/richtext_editor.test.ts diff --git a/packages/vrender-core/__tests__/richtext_editor/richtext_editor.test.ts b/packages/vrender-core/__tests__/richtext_editor/richtext_editor.test.ts new file mode 100644 index 000000000..6be13593b --- /dev/null +++ b/packages/vrender-core/__tests__/richtext_editor/richtext_editor.test.ts @@ -0,0 +1,279 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +// @ts-nocheck +import { findCursorIdxByConfigIndex, findConfigIndexByCursorIdx } from '../../src/plugins/builtin-plugin/edit-module'; + +const textConfig1 = [ + { + text: '我', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + }, + { + text: '们', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + }, + { + text: '是', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + } +]; +const textConfig2 = [ + { + text: '我', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + }, + { + fill: '#0f51b5', + text: '\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + isComposing: false + }, + { + fill: '#0f51b5', + text: '\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + isComposing: false + }, + { + fill: '#0f51b5', + text: '\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + isComposing: false + }, + { + fill: '#0f51b5', + text: '\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + isComposing: false + }, + { + text: '们', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + }, + { + text: '是', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + } +]; +const textConfig3 = [ + { + text: '我', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + }, + { + fill: '#0f51b5', + text: '\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + isComposing: false + }, + { + fill: '#0f51b5', + text: '\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + isComposing: false + }, + { + fill: '#0f51b5', + text: 'a', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + isComposing: false + }, + { + fill: '#0f51b5', + text: '\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + isComposing: false + }, + { + fill: '#0f51b5', + text: '\n', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + isComposing: false + }, + { + text: '们', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + }, + { + text: '是', + fontSize: 16, + lineHeight: 26, + textAlign: 'center', + background: 'orange', + fill: '#0f51b5' + } +]; + +describe('richtext_editor', () => { + it('richtext_editor findConfigIndexByCursorIdx config 1', () => { + // expect(findConfigIndexByCursorIdx(textConfig1, -0.1)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig1, 0.1)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig1, 0.9)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig1, 1.1)).toEqual(1); + // expect(findConfigIndexByCursorIdx(textConfig1, 1.9)).toEqual(1); + // expect(findConfigIndexByCursorIdx(textConfig1, 2.1)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig1, -0.1, 1)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig1, 0.1, 1)).toEqual(1); + // expect(findConfigIndexByCursorIdx(textConfig1, 0.9, 1)).toEqual(1); + // expect(findConfigIndexByCursorIdx(textConfig1, 1.1, 1)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig1, 1.9, 1)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig1, 2.1, 1)).toEqual(2); + }); + + it('richtext_editor findConfigIndexByCursorIdx config 2', () => { + // expect(findConfigIndexByCursorIdx(textConfig2, -0.1)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig2, 0.1)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig2, 0.9)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig2, 1.1)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig2, 1.9)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig2, 2.1)).toEqual(3); + // expect(findConfigIndexByCursorIdx(textConfig2, 2.9)).toEqual(3); + // expect(findConfigIndexByCursorIdx(textConfig2, 3.1)).toEqual(4); + // expect(findConfigIndexByCursorIdx(textConfig2, 3.9)).toEqual(4); + // expect(findConfigIndexByCursorIdx(textConfig2, 4.1)).toEqual(5); + // expect(findConfigIndexByCursorIdx(textConfig2, 4.9)).toEqual(5); + // expect(findConfigIndexByCursorIdx(textConfig2, 5.1)).toEqual(6); + // expect(findConfigIndexByCursorIdx(textConfig2, -0.1, 1)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig2, 0.1, 1)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig2, 0.9, 1)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig2, 1.1, 1)).toEqual(3); + // expect(findConfigIndexByCursorIdx(textConfig2, 1.9, 1)).toEqual(3); + // expect(findConfigIndexByCursorIdx(textConfig2, 2.1, 1)).toEqual(4); + // expect(findConfigIndexByCursorIdx(textConfig2, 2.9, 1)).toEqual(4); + // expect(findConfigIndexByCursorIdx(textConfig2, 3.1, 1)).toEqual(5); + // expect(findConfigIndexByCursorIdx(textConfig2, 3.9, 1)).toEqual(5); + // expect(findConfigIndexByCursorIdx(textConfig2, 4.1, 1)).toEqual(6); + // expect(findConfigIndexByCursorIdx(textConfig2, 4.9, 1)).toEqual(6); + // expect(findConfigIndexByCursorIdx(textConfig2, 5.1, 1)).toEqual(6); + }); + + it('richtext_editor findConfigIndexByCursorIdx config 3', () => { + // expect(findConfigIndexByCursorIdx(textConfig3, -0.1)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig3, 0.1)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig3, 0.9)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig3, 1.1)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig3, 1.9)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig3, 2.1)).toEqual(3); + // expect(findConfigIndexByCursorIdx(textConfig3, 2.9)).toEqual(3); + // expect(findConfigIndexByCursorIdx(textConfig3, 3.1)).toEqual(5); + // expect(findConfigIndexByCursorIdx(textConfig3, 3.9)).toEqual(5); + // expect(findConfigIndexByCursorIdx(textConfig3, 4.1)).toEqual(6); + // expect(findConfigIndexByCursorIdx(textConfig3, 4.9)).toEqual(6); + // expect(findConfigIndexByCursorIdx(textConfig3, 5.1)).toEqual(7); + // expect(findConfigIndexByCursorIdx(textConfig3, 5.9)).toEqual(7); + // expect(findConfigIndexByCursorIdx(textConfig3, -0.1, 1)).toEqual(0); + // expect(findConfigIndexByCursorIdx(textConfig3, 0.1, 1)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig3, 0.9, 1)).toEqual(2); + // expect(findConfigIndexByCursorIdx(textConfig3, 1.1, 1)).toEqual(3); + // expect(findConfigIndexByCursorIdx(textConfig3, 1.9, 1)).toEqual(3); + // expect(findConfigIndexByCursorIdx(textConfig3, 2.1, 1)).toEqual(5); + // expect(findConfigIndexByCursorIdx(textConfig3, 2.9, 1)).toEqual(5); + // expect(findConfigIndexByCursorIdx(textConfig3, 3.1, 1)).toEqual(6); + // expect(findConfigIndexByCursorIdx(textConfig3, 3.9, 1)).toEqual(6); + // expect(findConfigIndexByCursorIdx(textConfig3, 4.1, 1)).toEqual(7); + // expect(findConfigIndexByCursorIdx(textConfig3, 4.9, 1)).toEqual(7); + // expect(findConfigIndexByCursorIdx(textConfig3, 5.1, 1)).toEqual(7); + // expect(findConfigIndexByCursorIdx(textConfig3, 5.9, 1)).toEqual(7); + }); + + it('richtext_editor findCursorIdxByConfigIndex config 1', () => { + // expect(findCursorIdxByConfigIndex(textConfig1, 0)).toEqual(0.1); + // expect(findCursorIdxByConfigIndex(textConfig1, 1)).toEqual(1.1); + // expect(findCursorIdxByConfigIndex(textConfig1, 2)).toEqual(2.1); + // expect(findCursorIdxByConfigIndex(textConfig1, 0, -0.1)).toEqual(-0.1); + // expect(findCursorIdxByConfigIndex(textConfig1, 1, -0.1)).toEqual(0.9); + // expect(findCursorIdxByConfigIndex(textConfig1, 2, -0.1)).toEqual(1.9); + }); + it('richtext_editor findCursorIdxByConfigIndex config 2', () => { + // expect(findCursorIdxByConfigIndex(textConfig2, 0)).toEqual(0.1); + // expect(findCursorIdxByConfigIndex(textConfig2, 1)).toEqual(0.9); + // expect(findCursorIdxByConfigIndex(textConfig2, 2)).toEqual(0.9); + // expect(findCursorIdxByConfigIndex(textConfig2, 3)).toEqual(1.9); + // expect(findCursorIdxByConfigIndex(textConfig2, 4)).toEqual(2.9); + // expect(findCursorIdxByConfigIndex(textConfig2, 5)).toEqual(4.1); + // expect(findCursorIdxByConfigIndex(textConfig2, 6)).toEqual(5.1); + // expect(findCursorIdxByConfigIndex(textConfig2, 0, -0.1)).toEqual(-0.1); + // expect(findCursorIdxByConfigIndex(textConfig2, 1, -0.1)).toEqual(0.9); + // expect(findCursorIdxByConfigIndex(textConfig2, 2, -0.1)).toEqual(0.9); + // expect(findCursorIdxByConfigIndex(textConfig2, 3, -0.1)).toEqual(1.9); + // expect(findCursorIdxByConfigIndex(textConfig2, 4, -0.1)).toEqual(2.9); + // expect(findCursorIdxByConfigIndex(textConfig2, 5, -0.1)).toEqual(3.9); + // expect(findCursorIdxByConfigIndex(textConfig2, 6, -0.1)).toEqual(4.9); + }); + it('richtext_editor findCursorIdxByConfigIndex config 3', () => { + // expect(findCursorIdxByConfigIndex(textConfig3, 0)).toEqual(0.1); + // expect(findCursorIdxByConfigIndex(textConfig3, 1)).toEqual(0.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 2)).toEqual(0.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 3)).toEqual(2.1); + // expect(findCursorIdxByConfigIndex(textConfig3, 4)).toEqual(2.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 5)).toEqual(2.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 6)).toEqual(4.1); + // expect(findCursorIdxByConfigIndex(textConfig3, 7)).toEqual(5.1); + // expect(findCursorIdxByConfigIndex(textConfig3, 0, -0.1)).toEqual(-0.1); + // expect(findCursorIdxByConfigIndex(textConfig3, 1, -0.1)).toEqual(0.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 2, -0.1)).toEqual(0.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 3, -0.1)).toEqual(1.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 4, -0.1)).toEqual(2.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 5, -0.1)).toEqual(2.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 6, -0.1)).toEqual(3.9); + // expect(findCursorIdxByConfigIndex(textConfig3, 7, -0.1)).toEqual(4.9); + }); +}); diff --git a/packages/vrender-core/src/index.ts b/packages/vrender-core/src/index.ts index 4a5aa7f28..f262e644c 100644 --- a/packages/vrender-core/src/index.ts +++ b/packages/vrender-core/src/index.ts @@ -99,3 +99,4 @@ export * from './plugins/builtin-plugin/html-attribute-plugin'; export * from './plugins/builtin-plugin/react-attribute-plugin'; export * from './plugins/builtin-plugin/3dview-transform-plugin'; export * from './plugins/builtin-plugin/flex-layout-plugin'; +export * from './plugins/builtin-plugin/edit-module'; diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index ef5ae6118..57762236b 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -1,81 +1,108 @@ import { application } from '../../application'; import type { IRichText, IRichTextCharacter, IRichTextParagraphCharacter } from '../../interface'; -function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) { - let idx = 0; - for (let i = 0; i < textConfig.length; i++) { - const c = textConfig[i] as IRichTextParagraphCharacter; - if (c.text !== '\n') { - idx++; - } - } - return Math.max(idx - 1, 0); -} +// function getMaxConfigIndexIgnoreLinebreak(textConfig: IRichTextCharacter[]) { +// let idx = 0; +// for (let i = 0; i < textConfig.length; i++) { +// const c = textConfig[i] as IRichTextParagraphCharacter; +// if (c.text !== '\n') { +// idx++; +// } +// } +// return Math.max(idx - 1, 0); +// } /** - * 找到cursorIndex所在的textConfig的位置,忽略单个换行符,连续换行符的时候只忽略第一个 + * 找到cursorIndex所在的textConfig的位置,给出的index就是要插入的准确位置 * @param textConfig * @param cursorIndex * @returns */ export function findConfigIndexByCursorIdx(textConfig: IRichTextCharacter[], cursorIndex: number): number { - let index = 0; - // 小于0是在最前面了 if (cursorIndex < 0) { - return -1; + return 0; } - let idx = Math.round(cursorIndex); - let lastLineBreak = true; - for (index = 0; index < textConfig.length; index++) { - const c = textConfig[index] as IRichTextParagraphCharacter; + + // 排序找到对应的元素 + const intCursorIndex = Math.round(cursorIndex); + let tempCursorIndex = intCursorIndex; + // 跳过连续换行符中的第一个换行符 + let lineBreak = false; + let configIdx = 0; + for (configIdx = 0; configIdx < textConfig.length && tempCursorIndex >= 0; configIdx++) { + const c = textConfig[configIdx] as IRichTextParagraphCharacter; if (c.text === '\n') { - idx -= Number(lastLineBreak); - lastLineBreak = true; + tempCursorIndex -= Number(lineBreak); + lineBreak = true; } else { - idx--; - lastLineBreak = false; - } - if (idx < 0) { - break; + tempCursorIndex--; + lineBreak = false; } } - // 换行符永远往前走一格 - if (cursorIndex - Math.round(cursorIndex) < 0 || (textConfig[index] as IRichTextParagraphCharacter).text === '\n') { - index--; + // 说明过限了 + if (tempCursorIndex >= 0) { + return textConfig.length; } - index = Math.max(index, 0); - // 避免超过限度,最后一个字符可能是换行符,算一个字符 - return Math.min(index, textConfig.length - 1); + configIdx -= 1; + + // 如果有换行,一定在换行符左边写 + if (cursorIndex > intCursorIndex && !lineBreak) { + configIdx += 1; + } + return configIdx; } +/** + * 根据configIndex找到cursorIndex的位置,忽略单个换行符,连续换行符的时候只忽略第一个 + * @param textConfig + * @param configIndex + * @returns + */ export function findCursorIdxByConfigIndex(textConfig: IRichTextCharacter[], configIndex: number): number { - let index = 0; + let cursorIndex = 0; + if (configIndex < 0) { + return -0.1; + } // 仅有一个\n,那不算 // 如果有连续的\n,那就少算一个 - let lastLineBreak = true; - let delta = 0; - for (let i = 0; i <= configIndex + delta; i++) { + let lastLineBreak = false; + + for (let i = 0; i <= configIndex && i < textConfig.length; i++) { const c = textConfig[i] as IRichTextParagraphCharacter; if (c.text === '\n') { - index += Number(lastLineBreak); - // 第一个换行符当做不存在 - delta += 1 - Number(lastLineBreak); + cursorIndex += Number(lastLineBreak); lastLineBreak = true; } else { - index++; + cursorIndex++; lastLineBreak = false; - // 回归 - delta = 0; } } - index = Math.max(index - 1, 0); - // 正常Cursor是放在右边的,但如果回退到换行符了,那就放在左侧 - if ((textConfig[configIndex] as any)?.text === '\n') { - index -= 0.1; - } else { - index += 0.1; + cursorIndex = Math.max(cursorIndex - 1, 0); + + // 超出区间了直接设置到尾部,configIndex超过区间,cursorIndex不会超过 + if (configIndex > textConfig.length - 1) { + // 如果最后一行是一个换行符,那么就得是xx.9否则就是xx.1 + if ((textConfig[textConfig.length - 1] as any)?.text === '\n') { + return cursorIndex + 0.9; + } + return cursorIndex + 0.1; + } + + // 如果是这个configIdx对应到的是单个换行的话,那么算到下一个字符上 + const lineBreak = (textConfig[configIndex] as any)?.text === '\n'; + if (configIndex >= textConfig.length - 1 && lineBreak) { + return cursorIndex + 1 - 0.1; } - return index; + const singleLineBreak = lineBreak && (textConfig[configIndex - 1] as any)?.text !== '\n'; + + // 光标往左放 + cursorIndex -= 0.1; + + // 如果是单行,那么这一个换行符没有算字符,光标要往右放 + if (singleLineBreak) { + cursorIndex += 0.2; + } + return cursorIndex; } export class EditModule { @@ -83,6 +110,7 @@ export class EditModule { textAreaDom: HTMLTextAreaElement; currRt: IRichText; isComposing: boolean; + composingConfigIdx: number; cursorIndex: number; selectionStartCursorIdx: number; // 输入的回调(composing的时候每次也会触发) @@ -103,6 +131,7 @@ export class EditModule { this.container.append(textAreaDom); this.textAreaDom = textAreaDom; this.isComposing = false; + this.composingConfigIdx = -1; this.onInputCbList = []; this.onChangeCbList = []; this.onFocusInList = []; @@ -160,43 +189,71 @@ export class EditModule { }; handleCompositionStart = () => { + this.isComposing = true; const { textConfig = [] } = this.currRt.attribute; + this.composingConfigIdx = this.cursorIndex < 0 ? 0 : findConfigIndexByCursorIdx(textConfig, this.cursorIndex); if (this.cursorIndex < 0) { const config = textConfig[0]; textConfig.unshift({ fill: 'black', ...config, text: '' }); } else { - const cursorIndex = findConfigIndexByCursorIdx(textConfig, this.cursorIndex); - const lastConfig = textConfig[cursorIndex]; - textConfig.splice(cursorIndex + 1, 0, { ...lastConfig, text: '' }); + const configIdx = this.composingConfigIdx; + const lastConfig = textConfig[configIdx] || textConfig[configIdx - 1]; + textConfig.splice(configIdx, 0, { ...lastConfig, text: '' }); } - - this.isComposing = true; }; handleCompositionEnd = () => { this.isComposing = false; + + const text = this.parseCompositionStr(this.composingConfigIdx); // 拆分上一次的内容 - const { textConfig = [] } = this.currRt.attribute; - const configIdx = findConfigIndexByCursorIdx(textConfig, this.cursorIndex + 1); + // const { textConfig = [] } = this.currRt.attribute; + // const configIdx = this.composingConfigIdx; + + // const lastConfig = textConfig[configIdx]; + // textConfig.splice(configIdx, 1); + // const text = (lastConfig as any).text; + // const textList: string[] = text ? Array.from(text.toString()) : []; + // for (let i = 0; i < textList.length; i++) { + // textConfig.splice(i + configIdx, 0, { ...lastConfig, isComposing: false, text: textList[i] } as any); + // } + // this.currRt.setAttributes({ textConfig }); + // const nextConfigIdx = configIdx + textList.length; + // this.cursorIndex = findCursorIdxByConfigIndex(textConfig, nextConfigIdx); + this.composingConfigIdx = -1; - const lastConfig = textConfig[configIdx]; - textConfig.splice(configIdx, 1); - const text = (lastConfig as any).text; - const textList: string[] = text ? Array.from(text.toString()) : []; - for (let i = 0; i < textList.length; i++) { - textConfig.splice(i + configIdx, 0, { ...lastConfig, isComposing: false, text: textList[i] } as any); - } - this.currRt.setAttributes({ textConfig }); this.onChangeCbList.forEach(cb => { cb( text, this.isComposing, // TODO 当换行后刚开始输入会有问题,后续看这里具体Cursor变换逻辑 - Math.min(this.cursorIndex + textList.length, getMaxConfigIndexIgnoreLinebreak(textConfig) + 0.1), + this.cursorIndex, this.currRt ); }); }; + /** + * 复合输入以及粘贴,都会复制出一大段内容,这时候需要重新处理textConfig和cursorIndex + * 1. 拆分text到textConfig + * 2. 计算新的cursorIndex + * @param configIdx + */ + parseCompositionStr(configIdx: number) { + const { textConfig = [] } = this.currRt.attribute; + + const lastConfig = textConfig[configIdx]; + textConfig.splice(configIdx, 1); + const text = (lastConfig as any).text; + const textList: string[] = text ? Array.from(text.toString()) : []; + for (let i = 0; i < textList.length; i++) { + textConfig.splice(i + configIdx, 0, { ...lastConfig, isComposing: false, text: textList[i] } as any); + } + this.currRt.setAttributes({ textConfig }); + const nextConfigIdx = configIdx + textList.length; + this.cursorIndex = findCursorIdxByConfigIndex(textConfig, nextConfigIdx); + return text; + } + handleInput = (ev: any) => { if (!this.currRt) { return; @@ -204,8 +261,6 @@ export class EditModule { if (ev.inputType === 'historyUndo') { return; } - - // 如果是回车,那就不往后+1 const { textConfig = [], ...rest } = this.currRt.attribute; // 删完了,直接返回 if (ev.type === 'Backspace' && !textConfig.length) { @@ -217,78 +272,85 @@ export class EditModule { str = '\n'; } - // 如果有选中多个文字,那就先删除 - let startIdx = this.selectionStartCursorIdx; - let endIdx = this.cursorIndex; - if (startIdx > endIdx) { - [startIdx, endIdx] = [endIdx, startIdx]; - } - // 无论是否composition都立刻恢复到没有选中的idx状态 - this.selectionStartCursorIdx = startIdx; - - // 转换成基于textConfig的 - // let delta = 0; - startIdx = findConfigIndexByCursorIdx(textConfig, startIdx); - // delta = this.selectionStartCursorIdx - startIdx; - endIdx = findConfigIndexByCursorIdx(textConfig, endIdx); - // console.log(startIdx, delta, endIdx); - - let idxDelta = 0; - // 如果是换行,得往回一格 - if (str === '\n') { - idxDelta = -0.2; + // 处理正反选 + if (this.selectionStartCursorIdx > this.cursorIndex) { + [this.cursorIndex, this.selectionStartCursorIdx] = [this.selectionStartCursorIdx, this.cursorIndex]; } - const lastConfigIdx = startIdx + (this.isComposing ? 1 : 0); + const startIdx = findConfigIndexByCursorIdx(textConfig, this.selectionStartCursorIdx); + const endIdx = findConfigIndexByCursorIdx(textConfig, this.cursorIndex); + + // composing的话会插入一个字符,所以往右加一个 + const lastConfigIdx = this.isComposing ? this.composingConfigIdx : Math.max(startIdx - 1, 0); + // 算一个默认属性 let lastConfig: any = textConfig[lastConfigIdx]; if (!lastConfig) { - if (textConfig.length === 0) { - lastConfig = { - fill: rest.fill ?? 'black', - stroke: rest.stroke ?? false, - fontSize: rest.fontSize ?? 12, - fontWeight: rest.fontWeight ?? 'normal' - }; - } else { - lastConfig = textConfig[lastConfigIdx - 1] || textConfig[lastConfigIdx + 1]; + lastConfig = { + fill: rest.fill ?? 'black', + stroke: rest.stroke ?? false, + fontSize: rest.fontSize ?? 12, + fontWeight: rest.fontWeight ?? 'normal' + }; + } + let nextConfig = lastConfig; + + if (startIdx !== endIdx) { + textConfig.splice(startIdx, endIdx - startIdx); + if (this.isComposing) { + this.composingConfigIdx = startIdx; } } - let currConfig = lastConfig; - if (ev.type === 'Backspace' && !this.isComposing) { - if (startIdx !== endIdx) { - textConfig.splice(startIdx + 1, endIdx - startIdx); - } else { - textConfig.splice(startIdx, 1); - startIdx -= 1; + + let nextConfigIdx = startIdx; + + // 删除键 + if (ev.type === 'Backspace' && !this.isComposing && startIdx === endIdx) { + if (startIdx <= 0) { + return; } + // 删除 + textConfig.splice(startIdx - 1, 1); + nextConfigIdx = Math.max(startIdx - 1, 0); } else { - if (startIdx !== endIdx) { - textConfig.splice(startIdx + 1, endIdx - startIdx); - } - + // 插入 if (!this.isComposing) { - currConfig = { fill: 'black', ...lastConfig, text: '' }; - startIdx += 1; - textConfig.splice(startIdx, 0, currConfig); - } - (currConfig as any).text = str; - currConfig.isComposing = this.isComposing; - if (!textConfig.length) { - textConfig.push(currConfig); + nextConfig = { fill: 'black', ...lastConfig, text: '' }; + textConfig.splice(startIdx, 0, nextConfig); + nextConfigIdx++; } + // 插入 + nextConfig.text = str; + // 标记isComposing,用来判定是否应该拆分成单个字符 + nextConfig.isComposing = this.isComposing; } this.currRt.setAttributes({ textConfig }); - this.cursorIndex = findCursorIdxByConfigIndex(textConfig, startIdx); + // 重新计算cursorIdx + // nextConfigIdx = Math.min(nextConfigIdx, textConfig.length - 1); + + let cursorIndex = this.cursorIndex; + if (str.length > 1 && !this.isComposing) { + // 如果字符长度大于1且不是composing,那说明是粘贴 + // 拆分 + this.parseCompositionStr(nextConfigIdx - 1); + cursorIndex = this.cursorIndex; + } else { + // composing的时候不偏移,只有完整输入后才偏移 + cursorIndex = findCursorIdxByConfigIndex(textConfig, nextConfigIdx); + if (!this.isComposing) { + this.cursorIndex = cursorIndex; + } else { + this.cursorIndex = this.selectionStartCursorIdx; + } + } - this.cursorIndex += idxDelta; if (!this.isComposing) { this.onChangeCbList.forEach(cb => { - cb(str, this.isComposing, this.cursorIndex, this.currRt); + cb(str, this.isComposing, cursorIndex, this.currRt); }); } else { this.onInputCbList.forEach(cb => { - cb(str, this.isComposing, this.cursorIndex, this.currRt); + cb(str, this.isComposing, cursorIndex, this.currRt); }); } }; diff --git a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts index 66518a260..4f9b7ab35 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/richtext-edit-plugin.ts @@ -197,7 +197,7 @@ export class RichTextEditPlugin implements IPlugin { const maxCursorIdx = Math.max(selectionStartCursorIdx, curCursorIdx); const minConfigIdx = findConfigIndexByCursorIdx(rt.attribute.textConfig, minCursorIdx); const maxConfigIdx = findConfigIndexByCursorIdx(rt.attribute.textConfig, maxCursorIdx); - const config = rt.attribute.textConfig.slice(minConfigIdx + 1, maxConfigIdx + 1); + const config = rt.attribute.textConfig.slice(minConfigIdx, maxConfigIdx); if (payload === 'bold') { config.forEach((item: IRichTextParagraphCharacter) => (item.fontWeight = 'bold')); } else if (payload === 'italic') { From c60fb7dacbc233f0b8495181bd14104dac25551b Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Thu, 19 Dec 2024 17:38:28 +0800 Subject: [PATCH 49/51] fix: fix issue with remove character --- .../src/plugins/builtin-plugin/edit-module.ts | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts index 57762236b..c57f9761e 100644 --- a/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts +++ b/packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts @@ -246,7 +246,12 @@ export class EditModule { const text = (lastConfig as any).text; const textList: string[] = text ? Array.from(text.toString()) : []; for (let i = 0; i < textList.length; i++) { - textConfig.splice(i + configIdx, 0, { ...lastConfig, isComposing: false, text: textList[i] } as any); + textConfig.splice(i + configIdx, 0, { + fill: 'black', + ...lastConfig, + isComposing: false, + text: textList[i] + } as any); } this.currRt.setAttributes({ textConfig }); const nextConfigIdx = configIdx + textList.length; @@ -304,13 +309,17 @@ export class EditModule { let nextConfigIdx = startIdx; // 删除键 - if (ev.type === 'Backspace' && !this.isComposing && startIdx === endIdx) { - if (startIdx <= 0) { - return; + if (ev.type === 'Backspace' && !this.isComposing) { + if (startIdx === endIdx) { + if (startIdx <= 0) { + return; + } + // 删除 + textConfig.splice(startIdx - 1, 1); + nextConfigIdx = Math.max(startIdx - 1, 0); + } else { + // 不插入内容 } - // 删除 - textConfig.splice(startIdx - 1, 1); - nextConfigIdx = Math.max(startIdx - 1, 0); } else { // 插入 if (!this.isComposing) { @@ -329,7 +338,7 @@ export class EditModule { // nextConfigIdx = Math.min(nextConfigIdx, textConfig.length - 1); let cursorIndex = this.cursorIndex; - if (str.length > 1 && !this.isComposing) { + if (str && str.length > 1 && !this.isComposing) { // 如果字符长度大于1且不是composing,那说明是粘贴 // 拆分 this.parseCompositionStr(nextConfigIdx - 1); From fd22ee598b24a0ba58fd6a9886d2183440a29edd Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 30 Dec 2024 12:08:36 +0800 Subject: [PATCH 50/51] feat: richtext reuse actualBoundingBox --- packages/vrender-core/src/graphic/richtext.ts | 4 ---- packages/vrender-core/src/graphic/richtext/line.ts | 2 +- packages/vrender-core/src/graphic/richtext/paragraph.ts | 5 +++-- packages/vrender-core/src/graphic/richtext/utils.ts | 4 ++-- 4 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/vrender-core/src/graphic/richtext.ts b/packages/vrender-core/src/graphic/richtext.ts index 750ba4cbf..a25a0699b 100644 --- a/packages/vrender-core/src/graphic/richtext.ts +++ b/packages/vrender-core/src/graphic/richtext.ts @@ -511,11 +511,7 @@ export class RichText extends Graphic implements IRic } } else { for (let i = 0; i < paragraphs.length; i++) { - // if (i === paragraphs.length - 1) { - // wrapper.newLine = true; - // } wrapper.deal(paragraphs[i]); - // wrapper.newLine = false; } } diff --git a/packages/vrender-core/src/graphic/richtext/line.ts b/packages/vrender-core/src/graphic/richtext/line.ts index 60a9b8b4f..ee1c1cd0f 100644 --- a/packages/vrender-core/src/graphic/richtext/line.ts +++ b/packages/vrender-core/src/graphic/richtext/line.ts @@ -223,7 +223,7 @@ export default class Line { applyStrokeStyle(ctx, paragraph.character); // 下面绘制underline和line-through时需要设置FillStyle applyFillStyle(ctx, paragraph.character, b); - paragraph.draw(ctx, y + this.ascent, x, index === 0, this.textAlign); + paragraph.draw(ctx, y, this.ascent, x, index === 0, this.textAlign); }); } diff --git a/packages/vrender-core/src/graphic/richtext/paragraph.ts b/packages/vrender-core/src/graphic/richtext/paragraph.ts index 004f80396..f73eb5f0f 100644 --- a/packages/vrender-core/src/graphic/richtext/paragraph.ts +++ b/packages/vrender-core/src/graphic/richtext/paragraph.ts @@ -142,7 +142,8 @@ export default class Paragraph { } } - draw(ctx: IContext2d, baseline: number, deltaLeft: number, isLineFirst: boolean, textAlign: string) { + draw(ctx: IContext2d, top: number, ascent: number, deltaLeft: number, isLineFirst: boolean, textAlign: string) { + let baseline = top + ascent; let text = this.text; let left = this.left + deltaLeft; baseline += this.top; @@ -217,7 +218,7 @@ export default class Paragraph { if (this.character.backgroundOpacity !== void 0) { ctx.globalAlpha = this.character.backgroundOpacity; } - ctx.fillRect(left, baseline - this.ascent, this.widthOrigin || this.width, this.ascent + this.descent); + ctx.fillRect(left, top, this.widthOrigin || this.width, this.lineHeight); ctx.fillStyle = fillStyle; ctx.globalAlpha = globalAlpha; } diff --git a/packages/vrender-core/src/graphic/richtext/utils.ts b/packages/vrender-core/src/graphic/richtext/utils.ts index af7668617..03e3def31 100644 --- a/packages/vrender-core/src/graphic/richtext/utils.ts +++ b/packages/vrender-core/src/graphic/richtext/utils.ts @@ -361,8 +361,8 @@ export function measureTextCanvas( result.descent = 0; } else { result.width = Math.floor(measurement.width); - result.height = Math.floor(measurement.fontBoundingBoxAscent + measurement.fontBoundingBoxDescent); - result.ascent = Math.floor(measurement.fontBoundingBoxAscent); + result.height = Math.floor(measurement.actualBoundingBoxAscent + measurement.actualBoundingBoxDescent); + result.ascent = Math.floor(measurement.actualBoundingBoxAscent); result.descent = result.height - result.ascent; } return result; From d89fdff73b9eb10fc314e8943ca04f9b33168067 Mon Sep 17 00:00:00 2001 From: zhouxinyu Date: Mon, 30 Dec 2024 13:40:45 +0800 Subject: [PATCH 51/51] fix: fix issue with build --- packages/vrender-core/src/graphic/richtext.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/vrender-core/src/graphic/richtext.ts b/packages/vrender-core/src/graphic/richtext.ts index a25a0699b..8685fd089 100644 --- a/packages/vrender-core/src/graphic/richtext.ts +++ b/packages/vrender-core/src/graphic/richtext.ts @@ -304,12 +304,12 @@ export class RichText extends Graphic implements IRic protected needUpdateTag(key: string): boolean { return super.needUpdateTag(key, RICHTEXT_UPDATE_TAG_KEY); } - getFrameCache(): Frame { + getFrameCache(): IRichTextFrame { if (this.shouldUpdateShape()) { this.doUpdateFrameCache(); this.clearUpdateShapeTag(); } - return this._frameCache; + return this._frameCache as IRichTextFrame; } get cliped() {