Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(edgeless): wrong transparent shape overlay #5990

26 changes: 5 additions & 21 deletions packages/blocks/src/_common/icons/edgeless.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1912,13 +1912,7 @@ export const rectSvg = html` <svg
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
>
<rect
stroke="rgba(0, 0, 0, 0.1)"
width="100"
y="20"
height="80"
fill="currentColor"
/>
<rect stroke="inherit" width="100" y="20" height="80" fill="currentColor" />
</svg>`;

export const ellipseSvg = html` <svg
Expand All @@ -1927,13 +1921,7 @@ export const ellipseSvg = html` <svg
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
>
<circle
stroke="rgba(0, 0, 0, 0.1)"
cx="50"
cy="50"
r="50"
fill="currentColor"
/>
<circle stroke="inherit" cx="50" cy="50" r="50" fill="currentColor" />
</svg>`;

export const triangleSvg = html` <svg
Expand All @@ -1942,11 +1930,7 @@ export const triangleSvg = html` <svg
viewBox="0 0 100 100"
xmlns="http://www.w3.org/2000/svg"
>
<polygon
stroke="rgba(0, 0, 0, 0.1)"
points="50,0 100,100 0,100"
fill="currentColor"
/>
<polygon stroke="inherit" points="50,0 100,100 0,100" fill="currentColor" />
</svg>`;

export const diamondSvg = html` <svg
Expand All @@ -1956,7 +1940,7 @@ export const diamondSvg = html` <svg
xmlns="http://www.w3.org/2000/svg"
>
<polygon
stroke="rgba(0, 0, 0, 0.1)"
stroke="inherit"
points="50,0 100,50 50,100 0,50"
fill="currentColor"
/>
Expand All @@ -1969,7 +1953,7 @@ export const roundedSvg = html` <svg
xmlns="http://www.w3.org/2000/svg"
>
<rect
stroke="rgba(0, 0, 0, 0.1)"
stroke="inherit"
width="100"
y="20"
height="80"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@ import {
ScribbledStyleIcon,
} from '../../../../../_common/icons/index.js';
import type { CssVariableName } from '../../../../../_common/theme/css-variables.js';
import { DEFAULT_SHAPE_FILL_COLOR } from '../../../../../surface-block/elements/shape/consts.js';
import { ShapeStyle } from '../../../../../surface-block/index.js';
import type { EdgelessPageBlockComponent } from '../../../edgeless-page-block.js';
import type { ColorEvent } from '../../panel/color-panel.js';
import { type ColorEvent, isTransparent } from '../../panel/color-panel.js';
import {
LINE_COLOR_PREFIX,
SHAPE_COLOR_PREFIX,
Expand Down Expand Up @@ -76,32 +75,22 @@ export class EdgelessShapeMenu extends WithDisposable(LitElement) {
private _setStrokeColor = (strokeColor: CssVariableName) => {
if (this.edgeless.edgelessTool.type !== 'shape') return;

const { shapeStyle } = this;

const props: Record<string, unknown> = { strokeColor };
if (shapeStyle === ShapeStyle.General) {
props.fillColor = strokeColor.replace(
LINE_COLOR_PREFIX,
SHAPE_COLOR_PREFIX
);
}
const fillColor = strokeColor.replace(
LINE_COLOR_PREFIX,
SHAPE_COLOR_PREFIX
);
const filled = !isTransparent(fillColor);
props.fillColor = fillColor;
props.filled = filled;
this.onChange(props);
};

private _setShapeStyle = (shapeStyle: ShapeStyle) => {
if (this.edgeless.edgelessTool.type !== 'shape') return;

const { strokeColor } = this;

let fillColor;
if (shapeStyle === ShapeStyle.General) {
fillColor = strokeColor.replace(LINE_COLOR_PREFIX, SHAPE_COLOR_PREFIX);
} else {
fillColor = DEFAULT_SHAPE_FILL_COLOR;
}
this.onChange({
shapeStyle,
fillColor,
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
} from '../../../../../surface-block/elements/shape/consts.js';
import { ShapeStyle } from '../../../../../surface-block/index.js';
import { ShapeToolController } from '../../../controllers/tools/shape-tool.js';
import { isTransparent } from '../../panel/color-panel.js';
import { getTooltipWithShortcut } from '../../utils.js';
import { createPopper } from '../common/create-popper.js';
import { EdgelessToolButton } from '../edgeless-toolbar-button.js';
Expand Down Expand Up @@ -221,7 +222,14 @@ export class EdgelessShapeToolButton extends EdgelessToolButton<
<div class="container-clip">
<div
class="shapes"
style=${styleMap({ color: `var(${this.fillColor})` })}
style=${styleMap({
color: `${
!isTransparent(this.fillColor)
? `var(${this.fillColor})`
: 'var(--affine-white-60)'
}`,
stroke: 'var(--affine-black-10)',
})}
>
${repeat(shapes, (shape, index) => {
return html`<edgeless-shape-tool-element
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import type {
} from '../../../../_common/utils/index.js';
import { hasClassNameInList } from '../../../../_common/utils/index.js';
import type { ShapeElement } from '../../../../surface-block/index.js';
import { Bound, CanvasElementType } from '../../../../surface-block/index.js';
import {
Bound,
CanvasElementType,
StrokeStyle,
} from '../../../../surface-block/index.js';
import type { SelectionArea } from '../../services/tools-manager.js';
import {
EXCLUDING_MOUSE_OUT_CLASS_LIST,
Expand Down Expand Up @@ -252,19 +256,29 @@ export class ShapeToolController extends EdgelessToolController<ShapeTool> {
createOverlay() {
this.clearOverlay();
const options = SHAPE_OVERLAY_OPTIONS;
const computedStyle = getComputedStyle(this._edgeless);
const attributes =
this._edgeless.surface.service.editSession.getLastProps('shape');
options.stroke = computedStyle.getPropertyValue(attributes.strokeColor);
options.fill = computedStyle.getPropertyValue(attributes.fillColor);
options.stroke = attributes.strokeColor;
options.fill = attributes.fillColor;
switch (attributes.strokeStyle) {
case StrokeStyle.Dashed:
options.strokeLineDash = [12, 12];
break;
case StrokeStyle.None:
options.strokeLineDash = [];
options.stroke = 'transparent';
break;
default:
options.strokeLineDash = [];
}
let shapeType: string = attributes.shapeType;
if (attributes.radius > 0 && shapeType === 'rect') {
shapeType = 'roundedRect';
}
this._shapeOverlay = new ShapeOverlay(this._edgeless, shapeType, options, {
shapeStyle: attributes.shapeStyle,
fillColor: attributes.fillColor,
strokeColor: attributes.strokeColor,
fillColor: options.fill,
strokeColor: options.stroke,
});
this._edgeless.surface.viewport.addOverlay(this._shapeOverlay);
}
Expand Down
11 changes: 8 additions & 3 deletions packages/blocks/src/page-block/edgeless/utils/consts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { DEFAULT_ROUGHNESS } from '../../../surface-block/consts.js';
import { LineWidth } from '../../../_common/types.js';
import {
DEFAULT_ROUGHNESS,
StrokeStyle,
} from '../../../surface-block/consts.js';

export const NOTE_MIN_WIDTH = 364;
export const NOTE_MIN_HEIGHT = 78;
Expand All @@ -25,9 +29,10 @@ export const SHAPE_OVERLAY_OFFSET_Y = 6;
export const SHAPE_OVERLAY_OPTIONS = {
seed: 666,
roughness: DEFAULT_ROUGHNESS,
strokeLineDash: [0, 0],
strokeStyle: StrokeStyle.Solid,
strokeLineDash: [] as number[],
stroke: 'black',
strokeWidth: 4,
strokeWidth: LineWidth.LINE_WIDTH_TWO,
fill: 'transparent',
};

Expand Down
49 changes: 36 additions & 13 deletions packages/blocks/src/page-block/edgeless/utils/tool-overlay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,10 @@ const drawGeneralShape = (
xywh: XYWH,
options: Options
) => {
ctx.strokeStyle = options.stroke ?? '';
ctx.setLineDash(options.strokeLineDash ?? []);
ctx.strokeStyle = options.stroke ?? 'transparent';
ctx.lineWidth = options.strokeWidth ?? 2;
ctx.fillStyle = options.fill ?? '#FFFFFF00';
ctx.fillStyle = options.fill ?? 'transparent';

ctx.beginPath();

Expand Down Expand Up @@ -239,6 +240,10 @@ class ToolOverlay extends Overlay {
protected edgeless: EdgelessPageBlockComponent;
protected disposables!: DisposableGroup;

public isTransparent(color: string): boolean {
return color.includes('transparent');
}

constructor(edgeless: EdgelessPageBlockComponent) {
super();
this.x = 0;
Expand Down Expand Up @@ -271,6 +276,30 @@ class ToolOverlay extends Overlay {
export class ShapeOverlay extends ToolOverlay {
public shape: Shape;

get computedStyle() {
return getComputedStyle(this.edgeless);
}

private _isTransparent(color: string) {
return color.includes('transparent');
}

private _getRealStrokeColor(color: string) {
const realStrokeColor = this.computedStyle.getPropertyValue(
color as string
);
if (!this._isTransparent(color)) return realStrokeColor;

return 'transparent';
}

private _getRealFillColor(color: string) {
const realFillColor = this.computedStyle.getPropertyValue(color as string);
if (!this._isTransparent(color)) return realFillColor;

return 'transparent';
}

constructor(
edgeless: EdgelessPageBlockComponent,
type: string,
Expand All @@ -288,24 +317,18 @@ export class ShapeOverlay extends ToolOverlay {
SHAPE_OVERLAY_WIDTH,
SHAPE_OVERLAY_HEIGHT,
] as XYWH;
const { shapeStyle } = style;
const { shapeStyle, fillColor, strokeColor } = style;
options.fill = this._getRealFillColor(fillColor);
options.stroke = this._getRealStrokeColor(strokeColor);
this.shape = ShapeFactory.createShape(xywh, type, options, shapeStyle);
this.disposables.add(
this.edgeless.slots.edgelessToolUpdated.on(edgelessTool => {
if (edgelessTool.type !== 'shape') return;
const shapeType = edgelessTool.shapeType;

const computedStyle = getComputedStyle(edgeless);
const strokeColor = computedStyle.getPropertyValue(
style.strokeColor as string
);
const fillColor = computedStyle.getPropertyValue(
style.fillColor as string
);
const newOptions = {
...options,
stroke: strokeColor,
fill: fillColor,
stroke: this._getRealStrokeColor(strokeColor),
fill: this._getRealFillColor(fillColor),
};

let { x, y } = this;
Expand Down
10 changes: 6 additions & 4 deletions packages/blocks/src/surface-block/managers/edit-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {
import type { SurfaceService } from '../surface-service.js';

const ConnectorEndpointSchema = z.nativeEnum(ConnectorEndpointStyle);
const StorkeStyleSchema = z.nativeEnum(StrokeStyle);
const StrokeStyleSchema = z.nativeEnum(StrokeStyle);
const LineWidthSchema = z.nativeEnum(LineWidth);
const ShapeStyleSchema = z.nativeEnum(ShapeStyle);
const ShapeTextFontSizeSchema = z.nativeEnum(SHAPE_TEXT_FONT_SIZE);
Expand All @@ -54,7 +54,7 @@ const LastPropsSchema = z.object({
connector: z.object({
frontEndpointStyle: ConnectorEndpointSchema,
rearEndpointStyle: ConnectorEndpointSchema,
strokeStyle: StorkeStyleSchema,
strokeStyle: StrokeStyleSchema,
stroke: LineColorsSchema,
strokeWidth: LineWidthSchema,
rough: z.boolean(),
Expand All @@ -72,7 +72,7 @@ const LastPropsSchema = z.object({
filled: z.boolean(),
radius: z.number(),
strokeWidth: z.number().optional(),
strokeStyle: StorkeStyleSchema.optional(),
strokeStyle: StrokeStyleSchema.optional(),
color: z.string().optional(),
fontSize: ShapeTextFontSizeSchema.optional(),
fontFamily: CanvasTextFontFamilySchema.optional(),
Expand All @@ -98,7 +98,7 @@ const LastPropsSchema = z.object({
style: z.object({
borderRadius: z.number(),
borderSize: z.number(),
borderStyle: StorkeStyleSchema,
borderStyle: StrokeStyleSchema,
shadowType: NoteShadowsSchema,
}),
}),
Expand Down Expand Up @@ -155,6 +155,8 @@ export class EditSessionStorage {
shapeType: ShapeType.Rect,
fillColor: DEFAULT_SHAPE_FILL_COLOR,
strokeColor: DEFAULT_SHAPE_STROKE_COLOR,
strokeStyle: StrokeStyle.Solid,
strokeWidth: LineWidth.LINE_WIDTH_TWO,
shapeStyle: ShapeStyle.General,
filled: true,
radius: 0,
Expand Down
4 changes: 2 additions & 2 deletions tests/edgeless/shape.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { expect } from '@playwright/test';

Check failure on line 1 in tests/edgeless/shape.spec.ts

View workflow job for this annotation

GitHub Actions / Playground E2E test (6)

edgeless/shape.spec.ts:92:1 › delete shape by component-toolbar

1) edgeless/shape.spec.ts:92:1 › delete shape by component-toolbar ─────────────────────────────── Test timeout of 30000ms exceeded.

import {
assertEdgelessTool,
Expand Down Expand Up @@ -145,7 +145,7 @@
await changeShapeStrokeColor(page, color);
await page.waitForTimeout(50);
const [picked] = await pickColorAtPoints(page, [
[rect.start.x + 2, rect.start.y + 2],
[rect.start.x + 1, rect.start.y + 1],
]);

await assertEdgelessColorSameWithHexColor(page, color, picked);
Expand Down Expand Up @@ -478,7 +478,7 @@
const color = '--affine-palette-line-navy';
await changeShapeStrokeColor(page, color);
await page.waitForTimeout(50);
const [picked] = await pickColorAtPoints(page, [[start.x + 2, start.y + 2]]);
const [picked] = await pickColorAtPoints(page, [[start.x + 1, start.y + 1]]);

await assertEdgelessColorSameWithHexColor(page, color, picked);
});
Loading