Optimizing Konva Performance with Viewport Culling
Introduction
In the previous article, I guided you on how to use Konva to create a simple WhiteBoard application; now we will continue to dive deeper into the performance issue when having to show too many elements on the UI to see how to solve it.
Here you need to understand that to draw a single element on the browser, including colors, shadows, animations, and enabling event triggers, etc., all consume a corresponding amount of CPU/GPU; if you only show a small number of elements it is negligible, but if this number is large enough and your machine's configuration is not sufficient to meet the demand, it will cause lagging or make the app unusable.
In this article, I will guide you on optimizing performance for a product to show 1000 elements on the UI while still operating smoothly using mathematical knowledge of Coordinate Transformation, also known as the Viewport Culling mechanism.
Prerequisites
If you don't know about Konva yet, please see the previous article to grasp some basic information about this package before continuing.
Detail
First, create the file type.ts to define the necessary types.
Create the file utility.ts
The code above is used to establish configuration constants for the application (screen size, object quantity) and the generateData function to create mock data for 1000 objects with random attributes of position, shape, and color within a virtual space with a size of 5000px.
Create the file ShapeItem.tsx
This is a sub-component wrapped in memo to avoid unnecessary re-renders. It is responsible for drawing specific shapes (rectangles, circles, polygons, images) based on the type attribute of the input data. At the same time, it optimizes performance by turning off costly drawing features like perfectDrawEnabled and shadowForStrokeEnabled.
Create the file OptimizedCanvas.tsx
This is the main component implementing the Viewport Culling mechanism. It calculates the space area currently displayed on the screen (viewport) through the updateViewport function whenever the user drags or zooms. Then, it uses useMemo to filter the data list, keeping and rendering only those objects within the visible range, significantly reducing the load on the GPU when only having to draw a small portion instead of all 1000 objects.
The result of use will be as follows when you zoom to show all elements.
When you zoom in smaller, it will only show those elements within the viewport and still be able to click on the elements for interaction.
Happy coding!
Comments
Post a Comment