refactor(editor): move worker renderer to affine shared (#10081)

This commit is contained in:
Yifeng Wang
2025-02-11 14:16:17 +08:00
committed by GitHub
parent d89d4a71dd
commit 53e5726d36
7 changed files with 37 additions and 32 deletions

View File

@@ -61,6 +61,7 @@
"./theme": "./src/theme/index.ts", "./theme": "./src/theme/index.ts",
"./styles": "./src/styles/index.ts", "./styles": "./src/styles/index.ts",
"./services": "./src/services/index.ts", "./services": "./src/services/index.ts",
"./viewport-renderer": "./src/viewport-renderer/index.ts",
"./adapters": "./src/adapters/index.ts" "./adapters": "./src/adapters/index.ts"
}, },
"files": [ "files": [

View File

@@ -0,0 +1,2 @@
export * from './types.js';
export * from './viewport-renderer.js';

View File

@@ -1,4 +1,4 @@
import type { TextRect } from './types'; import type { TextRect } from './types.js';
interface WordSegment { interface WordSegment {
text: string; text: string;

View File

@@ -23,12 +23,12 @@ export interface ParagraphLayout {
zoom: number; zoom: number;
} }
export interface TextRect {
rect: Rect;
text: string;
}
export interface SectionLayout { export interface SectionLayout {
paragraphs: ParagraphLayout[]; paragraphs: ParagraphLayout[];
rect: Rect; rect: Rect;
} }
export interface TextRect {
rect: Rect;
text: string;
}

View File

@@ -1,24 +1,19 @@
import type { EditorHost } from '@blocksuite/block-std';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import type { AffineEditorContainer } from '@blocksuite/presets';
import { getSentenceRects, segmentSentences } from './text-utils.js'; import { getSentenceRects, segmentSentences } from './text-utils.js';
import { type ParagraphLayout, type SectionLayout } from './types.js'; import { type ParagraphLayout, type SectionLayout } from './types.js';
export class CanvasRenderer { export class ViewportTurboRenderer {
private readonly worker: Worker;
private readonly editorContainer: AffineEditorContainer;
private readonly targetContainer: HTMLElement;
public readonly canvas: HTMLCanvasElement = document.createElement('canvas'); public readonly canvas: HTMLCanvasElement = document.createElement('canvas');
private readonly worker: Worker;
private readonly targetContainer: HTMLElement;
private host!: EditorHost;
private lastZoom: number | null = null; private lastZoom: number | null = null;
private lastSection: SectionLayout | null = null; private lastSection: SectionLayout | null = null;
private lastBitmap: ImageBitmap | null = null; private lastBitmap: ImageBitmap | null = null;
private lastMode: 'page' | 'edgeless' = 'edgeless';
constructor( constructor(targetContainer: HTMLElement) {
editorContainer: AffineEditorContainer,
targetContainer: HTMLElement
) {
this.editorContainer = editorContainer;
this.targetContainer = targetContainer; this.targetContainer = targetContainer;
this.worker = new Worker(new URL('./painter.worker.ts', import.meta.url), { this.worker = new Worker(new URL('./painter.worker.ts', import.meta.url), {
@@ -30,16 +25,20 @@ export class CanvasRenderer {
} }
} }
setHost(host: EditorHost) {
this.host = host;
}
get viewport() { get viewport() {
return this.editorContainer.std.get(GfxControllerIdentifier).viewport; return this.host.std.get(GfxControllerIdentifier).viewport;
} }
getHostRect() { getHostRect() {
return this.editorContainer.host!.getBoundingClientRect(); return this.host.getBoundingClientRect();
} }
getHostLayout() { getHostLayout() {
const paragraphBlocks = this.editorContainer.host!.querySelectorAll( const paragraphBlocks = this.host.querySelectorAll(
'.affine-paragraph-rich-text-wrapper [data-v-text="true"]' '.affine-paragraph-rich-text-wrapper [data-v-text="true"]'
); );
@@ -161,7 +160,6 @@ export class CanvasRenderer {
private updateCacheState(section: SectionLayout, bitmapCopy: ImageBitmap) { private updateCacheState(section: SectionLayout, bitmapCopy: ImageBitmap) {
this.lastZoom = this.viewport.zoom; this.lastZoom = this.viewport.zoom;
this.lastSection = section; this.lastSection = section;
this.lastMode = this.editorContainer.mode;
if (this.lastBitmap) { if (this.lastBitmap) {
this.lastBitmap.close(); this.lastBitmap.close();
} }
@@ -170,10 +168,7 @@ export class CanvasRenderer {
private canUseCache(currentZoom: number): boolean { private canUseCache(currentZoom: number): boolean {
return ( return (
this.lastZoom === currentZoom && this.lastZoom === currentZoom && !!this.lastSection && !!this.lastBitmap
!!this.lastSection &&
!!this.lastBitmap &&
this.lastMode === this.editorContainer.mode
); );
} }

View File

@@ -1,16 +1,18 @@
import { ViewportTurboRenderer } from '@blocksuite/affine-shared/viewport-renderer';
import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx'; import { GfxControllerIdentifier } from '@blocksuite/block-std/gfx';
import { nextTick } from '@blocksuite/global/utils';
import { Text } from '@blocksuite/store'; import { Text } from '@blocksuite/store';
import { Pane } from 'tweakpane'; import { Pane } from 'tweakpane';
import { CanvasRenderer } from './canvas-renderer.js';
import { doc, editor } from './editor.js'; import { doc, editor } from './editor.js';
type DocMode = 'page' | 'edgeless'; type DocMode = 'page' | 'edgeless';
const container = document.querySelector('#right-column') as HTMLElement; const rightColumn = document.querySelector('#right-column') as HTMLElement;
const renderer = new CanvasRenderer(editor, container); const renderer = new ViewportTurboRenderer(rightColumn);
async function handleToCanvasClick() { async function handleToCanvasClick() {
renderer.setHost(editor.host!);
await renderer.render(); await renderer.render();
const viewport = editor.std.get(GfxControllerIdentifier).viewport; const viewport = editor.std.get(GfxControllerIdentifier).viewport;
viewport.viewportUpdated.on(async () => { viewport.viewportUpdated.on(async () => {
@@ -18,6 +20,13 @@ async function handleToCanvasClick() {
}); });
} }
async function handleModeChange(mode: DocMode) {
editor.mode = mode;
await nextTick();
renderer.setHost(editor.host!);
await renderer.render();
}
function initUI() { function initUI() {
const pane = new Pane({ const pane = new Pane({
container: document.querySelector('#tweakpane-container') as HTMLElement, container: document.querySelector('#tweakpane-container') as HTMLElement,
@@ -34,7 +43,6 @@ function initUI() {
.on('click', () => { .on('click', () => {
handleToCanvasClick().catch(console.error); handleToCanvasClick().catch(console.error);
}); });
pane pane
.addBinding(params, 'mode', { .addBinding(params, 'mode', {
label: 'Editor Mode', label: 'Editor Mode',
@@ -44,10 +52,8 @@ function initUI() {
}, },
}) })
.on('change', ({ value }) => { .on('change', ({ value }) => {
editor.mode = value as DocMode; handleModeChange(value as DocMode).catch(console.error);
}); });
document.querySelector('#left-column')?.append(editor);
} }
function addParagraph(content: string) { function addParagraph(content: string) {
@@ -61,6 +67,7 @@ function addParagraph(content: string) {
function main() { function main() {
initUI(); initUI();
document.querySelector('#left-column')?.append(editor);
const firstParagraph = doc.getBlockByFlavour('affine:paragraph')[0]; const firstParagraph = doc.getBlockByFlavour('affine:paragraph')[0];
doc.updateBlock(firstParagraph, { text: new Text('Renderer') }); doc.updateBlock(firstParagraph, { text: new Text('Renderer') });