mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-16 09:36:17 +08:00
feat(editor): support border radius for shape dom renderer (#12326)
Comparison:  <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Border radius and border thickness of shapes now scale dynamically with zoom level for improved visual consistency. - **Tests** - Added a test to ensure percentage-based border radius values are correctly rendered in the DOM. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -6,10 +6,16 @@ import { manageClassNames, setStyles } from './utils';
|
||||
|
||||
function applyShapeSpecificStyles(
|
||||
model: ShapeElementModel,
|
||||
element: HTMLElement
|
||||
element: HTMLElement,
|
||||
zoom: number
|
||||
) {
|
||||
if (model.shapeType === 'rect') {
|
||||
element.style.borderRadius = `${model.radius ?? 0}px`;
|
||||
const w = model.w * zoom;
|
||||
const h = model.h * zoom;
|
||||
const r = model.radius ?? 0;
|
||||
const borderRadius =
|
||||
r < 1 ? `${Math.min(w * r, h * r)}px` : `${r * zoom}px`;
|
||||
element.style.borderRadius = borderRadius;
|
||||
} else if (model.shapeType === 'ellipse') {
|
||||
element.style.borderRadius = '50%';
|
||||
} else {
|
||||
@@ -20,11 +26,12 @@ function applyShapeSpecificStyles(
|
||||
function applyBorderStyles(
|
||||
model: ShapeElementModel,
|
||||
element: HTMLElement,
|
||||
strokeColor: string
|
||||
strokeColor: string,
|
||||
zoom: number
|
||||
) {
|
||||
element.style.border =
|
||||
model.strokeStyle !== 'none'
|
||||
? `${model.strokeWidth}px ${model.strokeStyle === 'dash' ? 'dashed' : 'solid'} ${strokeColor}`
|
||||
? `${model.strokeWidth * zoom}px ${model.strokeStyle === 'dash' ? 'dashed' : 'solid'} ${strokeColor}`
|
||||
: 'none';
|
||||
}
|
||||
|
||||
@@ -85,11 +92,11 @@ export const shapeDomRenderer = (
|
||||
element.style.width = `${model.w * zoom}px`;
|
||||
element.style.height = `${model.h * zoom}px`;
|
||||
|
||||
applyShapeSpecificStyles(model, element);
|
||||
applyShapeSpecificStyles(model, element, zoom);
|
||||
|
||||
element.style.backgroundColor = model.filled ? fillColor : 'transparent';
|
||||
|
||||
applyBorderStyles(model, element, strokeColor);
|
||||
applyBorderStyles(model, element, strokeColor, zoom);
|
||||
applyTransformStyles(model, element);
|
||||
|
||||
element.style.boxSizing = 'border-box';
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { DomRenderer } from '@blocksuite/affine-block-surface';
|
||||
import { beforeEach, describe, expect, test } from 'vitest';
|
||||
|
||||
import { wait } from '../utils/common.js';
|
||||
import { getSurface } from '../utils/edgeless.js';
|
||||
import { setupEditor } from '../utils/setup.js';
|
||||
|
||||
@@ -40,6 +41,27 @@ describe('Shape rendering with DOM renderer', () => {
|
||||
expect(shapeElement).toBeInstanceOf(HTMLElement);
|
||||
});
|
||||
|
||||
test('should correctly apply percentage-based border radius', async () => {
|
||||
const surfaceView = getSurface(window.doc, window.editor);
|
||||
const surfaceModel = surfaceView.model;
|
||||
const shapeProps = {
|
||||
type: 'shape',
|
||||
subType: 'rectangle',
|
||||
xywh: '[150, 150, 80, 60]', // width: 80, height: 60
|
||||
radius: 0.1, // 10% of min(width, height) = 10% of 60 = 6
|
||||
fill: '#ff0000',
|
||||
stroke: '#000000',
|
||||
};
|
||||
const shapeId = surfaceModel.addElement(shapeProps);
|
||||
await wait(100);
|
||||
const shapeElement = surfaceView?.renderRoot.querySelector<HTMLElement>(
|
||||
`[data-element-id="${shapeId}"]`
|
||||
);
|
||||
|
||||
expect(shapeElement).not.toBeNull();
|
||||
expect(shapeElement?.style.borderRadius).toBe('6px');
|
||||
});
|
||||
|
||||
test('should remove shape DOM node when element is deleted', async () => {
|
||||
const surfaceView = getSurface(window.doc, window.editor);
|
||||
const surfaceModel = surfaceView.model;
|
||||
|
||||
Reference in New Issue
Block a user