mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 20:38:52 +00:00
perf(editor): fallback to placeholder for canvas text (#12033)
### TL;DR For canvas elements, this PR adds placeholders during zooming operations to improve performance.  ### What changed? - Implemented placeholder rendering during zooming operations in the canvas renderer, but not only DOM. - Added a `forceFullRender` property to the `GfxCompatibleInterface` to allow elements to opt out of placeholder rendering - Set `forceFullRender = true` for connectors to ensure they always render properly, even during zooming - Connected the turbo renderer to the viewport's zooming state to automatically switch between full and placeholder rendering ### Why make this change? Rendering complex elements during zooming operations can cause performance issues and make the UI feel sluggish. Rendering connector label also leads to high cost DOM `set font` delays.  The turbo renderer improves performance by displaying simple placeholders for elements during zooming, while still rendering critical elements like connectors fully. This creates a smoother user experience while maintaining essential visual information. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced a feature-flag-controlled "turbo" rendering mode that displays placeholder graphics during zooming for improved performance. - Added the ability to override placeholder rendering for specific elements, ensuring full rendering when required. - **Bug Fixes** - Enhanced rendering logic to ensure connectors always render fully, even during zoom operations. - **Documentation** - Updated API documentation to reflect new properties related to rendering behavior. - **Tests** - Improved tests to verify correct rendering behavior for connectors. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type { SurfaceBlockModel } from '@blocksuite/affine/blocks/surface';
|
||||
import type {
|
||||
BrushElementModel,
|
||||
ConnectorElementModel,
|
||||
GroupElementModel,
|
||||
} from '@blocksuite/affine/model';
|
||||
import { beforeEach, describe, expect, test } from 'vitest';
|
||||
@@ -160,6 +161,7 @@ describe('connector', () => {
|
||||
|
||||
expect(model.getConnectors(id).map(el => el.id)).toEqual([connector.id]);
|
||||
expect(model.getConnectors(id2).map(el => el.id)).toEqual([connector.id]);
|
||||
expect((connector as ConnectorElementModel).forceFullRender).toBe(true);
|
||||
});
|
||||
|
||||
test('multiple connectors are supported', () => {
|
||||
@@ -194,6 +196,8 @@ describe('connector', () => {
|
||||
|
||||
expect(model.getConnectors(id).map(c => c.id)).toEqual(connectors);
|
||||
expect(model.getConnectors(id2).map(c => c.id)).toEqual(connectors);
|
||||
expect((connector as ConnectorElementModel).forceFullRender).toBe(true);
|
||||
expect((connector2 as ConnectorElementModel).forceFullRender).toBe(true);
|
||||
});
|
||||
|
||||
test('should return null if connector are updated', () => {
|
||||
@@ -213,6 +217,11 @@ describe('connector', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const connectorBeforeUpdate = model.getElementById(connectorId)!;
|
||||
expect(
|
||||
(connectorBeforeUpdate as ConnectorElementModel).forceFullRender
|
||||
).toBe(true);
|
||||
|
||||
model.updateElement(connectorId, {
|
||||
source: {
|
||||
position: [0, 0],
|
||||
@@ -243,6 +252,11 @@ describe('connector', () => {
|
||||
},
|
||||
});
|
||||
|
||||
const connectorBeforeDelete = model.getElementById(connectorId)!;
|
||||
expect(
|
||||
(connectorBeforeDelete as ConnectorElementModel).forceFullRender
|
||||
).toBe(true);
|
||||
|
||||
model.deleteElement(connectorId);
|
||||
|
||||
await wait();
|
||||
|
||||
Reference in New Issue
Block a user