Skip to content

Commit

Permalink
perf: optimize large image rendering performance
Browse files Browse the repository at this point in the history
  • Loading branch information
wang1212 committed Oct 23, 2024
1 parent 56abfb8 commit 174b5a5
Show file tree
Hide file tree
Showing 19 changed files with 870 additions and 87 deletions.
9 changes: 9 additions & 0 deletions .changeset/nine-mangos-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
'@antv/g-plugin-canvaskit-renderer': patch
'@antv/g-plugin-canvas-renderer': patch
'@antv/g-plugin-device-renderer': patch
'@antv/g-plugin-image-loader': patch
'@antv/g-lite': patch
---

perf: optimize large image rendering performance
59 changes: 59 additions & 0 deletions __tests__/demos/perf/image.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { Canvas, Image as GImage } from '@antv/g';

export async function image(context: { canvas: Canvas }) {
const { canvas } = context;
await canvas.ready;
console.log(canvas);

const $dom = canvas.getContextService().getDomElement() as HTMLCanvasElement;
$dom.style.border = '1px solid gray';

// ---
$dom.addEventListener('wheel', (event) => {
event.preventDefault();

const { deltaX, deltaY } = event;
const d = -(deltaX ?? deltaY);

const ratio = 1 + (Math.min(Math.max(d, -50), 50) * 1) / 100;
const zoom = canvas.getCamera().getZoom();

canvas
.getCamera()
.setZoomByViewportPoint(zoom * ratio, [event.offsetX, event.offsetY]);
});

let isDragging = false;
let lastX, lastY;
$dom.addEventListener('mousedown', (e) => {
isDragging = true;
lastX = e.clientX;
lastY = e.clientY;
});
$dom.addEventListener('mousemove', (e) => {
if (isDragging) {
const dx = e.clientX - lastX;
const dy = e.clientY - lastY;
canvas.getCamera().pan(-dx, -dy);
lastX = e.clientX;
lastY = e.clientY;
}
});
$dom.addEventListener('mouseup', () => {
isDragging = false;
});

// ---

let image = new GImage({
style: {
x: 0,
y: 0,
// width: 100,
// height: 400,
// src: 'https://gw.alipayobjects.com/mdn/rms_6ae20b/afts/img/A*N4ZMS7gHsUIAAAAAAAAAAABkARQnAQ',
src: 'http://mmtcdp.stable.alipay.net/cto_designhubcore/afts/img/g1a5QYkvbcMAAAAAAAAAAAAADgLVAQBr/original',
},
});
canvas.appendChild(image);
}
1 change: 1 addition & 0 deletions __tests__/demos/perf/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { circles } from './circles';
export { rects } from './rect';
export { image } from './image';
1 change: 1 addition & 0 deletions __tests__/main.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import * as lil from 'lil-gui';
import '@antv/g-camera-api';
import { Canvas, CanvasEvent, runtime } from '@antv/g';
import { Renderer as CanvasRenderer } from '@antv/g-canvas';
import { Renderer as CanvaskitRenderer } from '@antv/g-canvaskit';
Expand Down
2 changes: 2 additions & 0 deletions packages/g-lite/src/Canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export class Canvas extends EventTarget implements ICanvas {
requestAnimationFrame,
cancelAnimationFrame,
createImage,
enableLargeImageOptimization,
supportsPointerEvents,
supportsTouchEvents,
supportsCSSTransform,
Expand Down Expand Up @@ -244,6 +245,7 @@ export class Canvas extends EventTarget implements ICanvas {
cursor: cursor || ('default' as Cursor),
background: background || 'transparent',
createImage,
enableLargeImageOptimization,
document,
supportsCSSTransform,
useNativeClickEvent,
Expand Down
19 changes: 19 additions & 0 deletions packages/g-lite/src/services/OffscreenCanvasCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@ export class OffscreenCanvasCreator {
private canvas: CanvasLike;
private context: CanvasRenderingContext2D | OffscreenCanvasRenderingContext2D;

/**
* @returns new canvas instance
*/
static createCanvas(): HTMLCanvasElement | OffscreenCanvas | null {
try {
return new window.OffscreenCanvas(0, 0);
} catch {
//
}

try {
return document.createElement('canvas');
} catch {
//
}

return null;
}

getOrCreateCanvas(
offscreenCanvas: CanvasLike,
contextAttributes?: CanvasRenderingContext2DSettings,
Expand Down
20 changes: 20 additions & 0 deletions packages/g-lite/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,26 @@ export interface CanvasConfig {
* replace `new window.Image()`
*/
createImage?: (src: string) => HTMLImageElement;
/**
* Optimize rendering performance for high-resolution large images
*/
enableLargeImageOptimization?:
| boolean
| {
/**
* Downsampling rate threshold, [0.01, 0.5], represents the ratio of reducing the image.
* For example, 0.3 means reducing the original image to 0.3 times of the original.
*
* default 0.5
*/
downSamplingRateThreshold?: number;
/**
* The maximum size of the downsampled image, with equal width and height.
*
* default 2048
*/
maxDownSampledImageSize?: number;
};

/**
* limits query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ export function getPattern(
}

const canvasPattern = imagePool.getOrCreatePatternSync(
object,
pattern,
context,
$offscreenCanvas,
Expand Down
Loading

0 comments on commit 174b5a5

Please sign in to comment.