Skip to content

Commit

Permalink
fix(edgeless): wrong transparent shape overlay (#5990)
Browse files Browse the repository at this point in the history
  • Loading branch information
donteatfriedrice authored Jan 15, 2024
1 parent f7c4cfc commit 8a0633a
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 69 deletions.
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
Expand Up @@ -145,7 +145,7 @@ test('change shape stroke color', async ({ page }) => {
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 @@ test('change shape style', async ({ page }) => {
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);
});

2 comments on commit 8a0633a

@vercel
Copy link

@vercel vercel bot commented on 8a0633a Jan 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

blocksuite – ./packages/playground

blocksuite-git-master-toeverything.vercel.app
try-blocksuite.vercel.app
blocksuite-toeverything.vercel.app

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Size Report

Bundles

Entry Size Gzip Brotli
examples/basic 13 MB (+10.1 kB) 2.7 MB (+3.59 kB) 1.69 MB (+2.16 kB)

Packages

Name Size Gzip Brotli
blocks 2.27 MB (+482 B) 513 kB (+312 B) 381 kB (+191 B)
editor 84 B 89 B 63 B
store 62.1 kB (+161 B) 17.8 kB (+65 B) 15.9 kB (+61 B)
inline 32.5 kB 8.94 kB 8.01 kB

Please sign in to comment.