Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .trae/specs/add-interactInvertType-background/checklist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
- [x] SmartInvertAttrs.interactInvertType 已包含 'background'
- [x] 相交且 'background' 时设置 label.stroke=false
- [x] 相交且 'background' 时设置 label.background=baseMark.fill(有填充时)
- [x] 其他类型(none/stroked/inside)行为无回归
- [x] 注释更新为“四种处理方式”并包含 background 描述
- [x] 示例验证通过(IText 与 IRichText 场景)
38 changes: 38 additions & 0 deletions .trae/specs/add-interactInvertType-background/spec.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 标签相交背景模式 Spec

## Why
当前标签与 mark 相交时仅支持 none/stroked/inside 三种处理方式,无法满足关闭描边并以底层 mark 的填充色作为文字背景的视觉需求,导致相交场景下对比度与观感不可控。

## What Changes
- 在 SmartInvertAttrs.interactInvertType 中新增 'background' 选项
- 在相交场景下(label 与 mark 相交且不完全在内部),当 interactInvertType 为 'background':
- 将标签描边 stroke 设置为 false(禁用描边)
- 将标签背景 background 设置为关联 mark 的填充色
- 更新 SmartInvert 相关注释文档,将“三种处理方式”修改为“四种”,并补充 background 描述
- 默认行为不变(未配置时保持现状),无破坏性变更

## Impact
- Affected specs: 标签智能反色/相交处理能力
- Affected code:
- packages/vrender-components/src/label/type.ts(类型与注释)
- packages/vrender-components/src/label/base.ts(_smartInvert 相交分支逻辑)

## ADDED Requirements
### Requirement: 新增 interactInvertType 'background'
系统应在标签与 mark 相交且配置 interactInvertType 为 'background' 时:
- 将标签的 stroke 设为 false,关闭描边;
- 将标签的 background 颜色设置为关联 mark 的填充色(优先取 mark.attribute.fill;若缺省则不改动 background)。
- 保持标签 fill 不做变更。

#### Scenario: Success case
- WHEN 标签与 mark 相交,且 smartInvert.interactInvertType === 'background'
- THEN label.stroke === false,且 label.background === baseMark.fill(存在时)

## MODIFIED Requirements
### Requirement: 更新交互反色类型文档
将注释由“支持三种处理方式:none/stroked/inside”更新为“四种处理方式:none/stroked/inside/background”,其中:
- background:关闭描边,并以 mark 的填充色作为文本背景参与渲染。

## REMOVED Requirements

9 changes: 9 additions & 0 deletions .trae/specs/add-interactInvertType-background/tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Tasks
- [x] 更新类型定义与注释:为 SmartInvertAttrs.interactInvertType 添加 'background',并改注释为“四种处理方式”
- [x] 修改 _smartInvert 相交分支:实现 'background' 行为(stroke=false;background=baseMark.fill;保持 fill 不变;跳过描边缺省早退)
- [x] 添加验证用例:构造 label 与 mark 相交示例,确认背景色与填充色一致且描边关闭(覆盖 IText 与 IRichText)
- [x] 自检与清理:校验边界(mark 无 fill、stroke 初始为数组/布尔的情况)、类型约束与代码风格

# Task Dependencies
- [修改 _smartInvert 相交分支] 依赖于 [更新类型定义与注释]
- [添加验证用例] 依赖于 [修改 _smartInvert 相交分支]
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import '@visactor/vrender';
import { createRect } from '@visactor/vrender';
import { createRenderer } from '../../util/render';
import { RectLabel } from '../../../src';

export const run = () => {
const stage = createRenderer('main');

const rect = createRect({
x: 180,
y: 180,
width: 160,
height: 100,
fill: '#2E62F1'
});
stage.defaultLayer.add(rect);

const label = new RectLabel({
data: [{ text: 'Intersect Background' }],
// 放置在图形边缘附近以制造相交(根据文本尺寸可能略有不同)
position: 'top',
offset: -10,
textStyle: {
fill: '#000',
stroke: '#fff',
lineWidth: 1
},
smartInvert: {
interactInvertType: 'background'
}
});

// 关联 label 到 rect
// @ts-ignore
label.setRelatedGraphic(rect);
stage.defaultLayer.add(label);

stage.render();

// 输出验证信息
// eslint-disable-next-line no-console
console.log('label.stroke:', label.attribute?.stroke);
// eslint-disable-next-line no-console
console.log('label.background:', label.attribute?.background);
};
4 changes: 4 additions & 0 deletions packages/vrender-components/__tests__/browser/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,10 @@ const specs = [
path: 'label-smart-inverse',
name: '标签智能反色'
},
{
path: 'label-smart-inverse-background',
name: '标签相交背景模式'
},
{
path: 'scrollbar',
name: '滚动条'
Expand Down
20 changes: 17 additions & 3 deletions packages/vrender-components/src/label/base.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,7 @@ export class LabelBase<T extends BaseLabelAttrs> extends AnimateComponent<T> {
* null(不执行智能反色,保持fill设置的颜色)
* */
let backgroundColor = baseMark.getAttributes(true).fill as IColor;
const backgroundOpacity = baseMark.getAttributes(true).fillOpacity as number;
let foregroundColor = label.attribute.fill as IColor;

if (isObject(backgroundColor) && backgroundColor.gradient) {
Expand Down Expand Up @@ -1089,11 +1090,21 @@ export class LabelBase<T extends BaseLabelAttrs> extends AnimateComponent<T> {
if (label.attribute.lineWidth === 0 || label.attribute.strokeOpacity === 0) {
continue;
}

const stroke = smartInvertStrategy(strokeStrategy, backgroundColor, invertColor, similarColor);
stroke && label.setAttributes({ stroke });
if (interactInvertType === 'background') {
label.setAttributes({ stroke: false });
} else {
const stroke = smartInvertStrategy(strokeStrategy, backgroundColor, invertColor, similarColor);
stroke && label.setAttributes({ stroke });
}
} else if (isIntersect && interactInvertType !== 'none') {
// 存在相交的情况
if (interactInvertType === 'background') {
// 按照标签展示在柱子内部的情况,执行反色逻辑
const fill = smartInvertStrategy(fillStrategy, backgroundColor, invertColor, similarColor);
fill && label.setAttributes({ fill });
label.setAttributes({ stroke: false, background: backgroundColor as string, backgroundOpacity });
continue;
}
/** 当label无法设置stroke时,不进行反色计算(容易反色为白色与白色背景混合不可见) */
if (label.attribute.lineWidth === 0 || label.attribute.strokeOpacity === 0) {
continue;
Expand All @@ -1120,6 +1131,9 @@ export class LabelBase<T extends BaseLabelAttrs> extends AnimateComponent<T> {
const stroke = smartInvertStrategy(strokeStrategy, backgroundColor, invertColor, similarColor);
stroke && label.setAttributes({ stroke });
}
if (isInside === false && interactInvertType === 'background') {
label.setAttributes({ background: null });
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions packages/vrender-components/src/label/type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -307,13 +307,14 @@ export interface SmartInvertAttrs {
*/
outsideEnable?: boolean;
/**
* 当标签和mark相交,但是没有完全在mark内部的时候,支持三种处理方式
* 当标签和mark相交,但是没有完全在mark内部的时候,支持四种处理方式
*
* * none:不做任何处理
* * stroked:标签存在描边的时候,根据描边进行处理
* * inside: 和标签完全在mark内部一样处理
* * background:关闭标签描边,并将标签背景色设置为 mark 的填充色
*/
interactInvertType?: 'none' | 'stroked' | 'inside';
interactInvertType?: 'none' | 'stroked' | 'inside' | 'background';
}

export type ShiftYStrategy = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ export class DefaultTextBackgroundRenderContribution
context.highPerformanceRestore();
context.setTransformForCurrent();
} else {
const { backgroundCornerRadius } = graphic.attribute;
const { backgroundCornerRadius, backgroundOpacity = 1 } = graphic.attribute;
context.highPerformanceSave();
context.setCommonStyle(graphic, graphic.attribute, x, y, graphicAttribute);
context.globalAlpha = backgroundOpacity;
context.fillStyle = background as string;
if (backgroundCornerRadius) {
// 测试后,cache对于重绘性能提升不大,但是在首屏有一定性能损耗,因此rect不再使用cache
Expand Down
Loading