refactor(editor): move worker renderer to affine shared (#10081)
This commit is contained in:
@@ -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": [
|
||||||
|
|||||||
2
blocksuite/affine/shared/src/viewport-renderer/index.ts
Normal file
2
blocksuite/affine/shared/src/viewport-renderer/index.ts
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export * from './types.js';
|
||||||
|
export * from './viewport-renderer.js';
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { TextRect } from './types';
|
import type { TextRect } from './types.js';
|
||||||
|
|
||||||
interface WordSegment {
|
interface WordSegment {
|
||||||
text: string;
|
text: string;
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -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') });
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user