mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-19 02:51:47 +08:00
feat(editor): support brush dom renderer
This commit is contained in:
@@ -0,0 +1,11 @@
|
|||||||
|
import { DomElementRendererExtension } from '@blocksuite/affine-block-surface';
|
||||||
|
|
||||||
|
import { brushDomRenderer } from './brush-dom/index.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extension to register the DOM-based renderer for 'brush' elements.
|
||||||
|
*/
|
||||||
|
export const BrushDomRendererExtension = DomElementRendererExtension(
|
||||||
|
'brush',
|
||||||
|
brushDomRenderer
|
||||||
|
);
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
import type { DomRenderer } from '@blocksuite/affine-block-surface';
|
||||||
|
import type { BrushElementModel } from '@blocksuite/affine-model';
|
||||||
|
import { DefaultTheme } from '@blocksuite/affine-model';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders a BrushElementModel to a given HTMLElement using DOM properties.
|
||||||
|
* This function is intended to be registered via the DomElementRendererExtension.
|
||||||
|
*
|
||||||
|
* @param model - The brush element model containing rendering properties.
|
||||||
|
* @param element - The HTMLElement to apply the brush's styles to.
|
||||||
|
* @param renderer - The main DOMRenderer instance, providing access to viewport and color utilities.
|
||||||
|
*/
|
||||||
|
export const brushDomRenderer = (
|
||||||
|
model: BrushElementModel,
|
||||||
|
element: HTMLElement,
|
||||||
|
renderer: DomRenderer
|
||||||
|
): void => {
|
||||||
|
const { zoom } = renderer.viewport;
|
||||||
|
const unscaledWidth = model.w;
|
||||||
|
const unscaledHeight = model.h;
|
||||||
|
|
||||||
|
const color = renderer.getColorValue(model.color, DefaultTheme.black, true);
|
||||||
|
|
||||||
|
element.style.width = `${unscaledWidth * zoom}px`;
|
||||||
|
element.style.height = `${unscaledHeight * zoom}px`;
|
||||||
|
element.style.boxSizing = 'border-box';
|
||||||
|
element.style.overflow = 'hidden';
|
||||||
|
|
||||||
|
// Clear any existing content
|
||||||
|
element.replaceChildren();
|
||||||
|
|
||||||
|
// Create SVG element to render the brush stroke
|
||||||
|
const SVG_NS = 'http://www.w3.org/2000/svg';
|
||||||
|
const svg = document.createElementNS(SVG_NS, 'svg');
|
||||||
|
svg.setAttribute('width', '100%');
|
||||||
|
svg.setAttribute('height', '100%');
|
||||||
|
svg.setAttribute('viewBox', `0 0 ${unscaledWidth} ${unscaledHeight}`);
|
||||||
|
svg.setAttribute('preserveAspectRatio', 'none');
|
||||||
|
|
||||||
|
// Create path element for the brush stroke
|
||||||
|
const path = document.createElementNS(SVG_NS, 'path');
|
||||||
|
path.setAttribute('d', model.commands);
|
||||||
|
path.setAttribute('fill', color);
|
||||||
|
path.setAttribute('stroke', 'none');
|
||||||
|
|
||||||
|
svg.append(path);
|
||||||
|
element.append(svg);
|
||||||
|
|
||||||
|
// Apply rotation if needed
|
||||||
|
if (model.rotate) {
|
||||||
|
element.style.transform = `rotate(${model.rotate}deg)`;
|
||||||
|
element.style.transformOrigin = 'center';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply opacity
|
||||||
|
element.style.opacity = `${model.opacity ?? 1}`;
|
||||||
|
|
||||||
|
// Set z-index
|
||||||
|
element.style.zIndex = renderer.layerManager.getZIndex(model).toString();
|
||||||
|
|
||||||
|
// Add brush-specific class for styling
|
||||||
|
element.classList.add('brush-element');
|
||||||
|
};
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
export * from './adapter';
|
export * from './adapter';
|
||||||
export * from './brush-tool';
|
export * from './brush-tool';
|
||||||
export * from './element-renderer';
|
export * from './element-renderer';
|
||||||
|
export * from './element-renderer/brush-dom';
|
||||||
export * from './eraser-tool';
|
export * from './eraser-tool';
|
||||||
export * from './highlighter-tool';
|
export * from './highlighter-tool';
|
||||||
export * from './toolbar/configs';
|
export * from './toolbar/configs';
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
import { BrushTool } from './brush-tool';
|
import { BrushTool } from './brush-tool';
|
||||||
import { effects } from './effects';
|
import { effects } from './effects';
|
||||||
import { BrushElementRendererExtension } from './element-renderer';
|
import { BrushElementRendererExtension } from './element-renderer';
|
||||||
|
import { BrushDomRendererExtension } from './element-renderer/brush-dom';
|
||||||
import { EraserTool } from './eraser-tool';
|
import { EraserTool } from './eraser-tool';
|
||||||
import { HighlighterTool } from './highlighter-tool';
|
import { HighlighterTool } from './highlighter-tool';
|
||||||
import {
|
import {
|
||||||
@@ -30,6 +31,7 @@ export class BrushViewExtension extends ViewExtensionProvider {
|
|||||||
context.register(HighlighterTool);
|
context.register(HighlighterTool);
|
||||||
|
|
||||||
context.register(BrushElementRendererExtension);
|
context.register(BrushElementRendererExtension);
|
||||||
|
context.register(BrushDomRendererExtension);
|
||||||
|
|
||||||
context.register(brushToolbarExtension);
|
context.register(brushToolbarExtension);
|
||||||
context.register(highlighterToolbarExtension);
|
context.register(highlighterToolbarExtension);
|
||||||
|
|||||||
Reference in New Issue
Block a user