That is adopted demo from the PixiJS framework .
You will notice that Konva
version is much slower than PixiJS
version.
So first of all I am not hiding that other frameworks may work better in some situations. PixiJS is very optimized for such types of graphics and animations (it uses WebGL for rendering).
There is a work in progress for optimizing some Konva
internals to make it work faster for that demo too.
But remember that the demo doesn’t represent the performance of typical application made with Konva
. If you are doing a lot of animations like in the demo with tons of objects you may need to use other solutions like Native Canvas Access or even a different framework.
So choose wisely the tool for your applications.
Konva 20000 Nodes Demo view raw <!DOCTYPE html > <html > <head > <script src ="https://unpkg.com/[email protected] /konva.min.js" > </script > <meta charset ="utf-8" /> <title > Konva Jumping Bunnies Demo</title > <style > body { margin: 0; padding: 0; overflow: hidden; background-color : #f0f0f0 ; } #counter { position: absolute; top: 50px; background-color: white; font-size: 12px; } </style > </head > <body > <div id ="container" > </div > <div id ="counter" > </div > <script src ="https://mrdoob.github.io/stats.js/build/stats.min.js" > </script > <script defer ="defer" > var lastTime = 0 ; var width = window .innerWidth; var height = window .innerHeight; var bunnys = []; var GRAVITY = 0.75 ; var maxX = width; var minX = 0 ; var maxY = height; var minY = 0 ; var startBunnyCount = 10 ; var isAdding = false ; var count = 0 ; var amount = 10 ; var stage = new Konva.Stage({ container: 'container' , width: width, height: height }); var layer = new Konva.FastLayer(); stage.add(layer); var wabbitTexture = new Image(); wabbitTexture.onload = function () { _handleTextureLoaded(); }; wabbitTexture.src = '/assets/bunny.png' ; var stats = new Stats(); document .body.appendChild(stats.domElement); stats.domElement.style.position = 'absolute' ; stats.domElement.style.top = '0px' ; window .requestAnimationFrame(update); var counter = document .getElementById('counter' ); count = startBunnyCount; counter.innerHTML = startBunnyCount + ' BUNNIES' ; stage.on('mousedown' , function () { isAdding = true ; }); stage.on('mouseup' , function () { isAdding = false ; }); document .addEventListener('touchstart' , onTouchStart, true ); document .addEventListener('touchend' , onTouchEnd, true ); function _handleTextureLoaded (event ) { for (var i = 0 ; i < startBunnyCount; i++) { var bunny = new Konva.Image({ image: wabbitTexture, transformsEnabled: 'position' , x: 10, y: 10 }); bunny.speedX = Math .random() * 10 ; bunny.speedY = Math .random() * 10 - 5 ; bunnys.push(bunny); layer.add(bunny); } layer.batchDraw(); } function onTouchStart (event) { isAdding = true ; } function onTouchEnd (event) { isAdding = false ; } function update () { stats.begin(); if (isAdding) { for (var i = 0 ; i < amount; i++) { var bunny = new Konva.Image({ image: wabbitTexture, transformsEnabled: 'position' , x: 0, y: 0 }); bunny.speedX = Math .random() * 10 ; bunny.speedY = Math .random() * 10 - 5 ; bunnys.push(bunny); layer.add(bunny); count++; } counter.innerHTML = count + ' BUNNIES' ; } for (var i = 0 ; i < bunnys.length; i++) { var bunny = bunnys[i]; bunny.setX(bunny.getX() + bunny.speedX); bunny.setY(bunny.getY() + bunny.speedY); bunny.speedY += GRAVITY; if (bunny.getX() > maxX - wabbitTexture.width) { bunny.speedX *= -1; bunny.setX(maxX - wabbitTexture.width); } else if (bunny.getX() < minX) { bunny.speedX *= -1; bunny.setX(minX); } if (bunny.getY() > maxY - wabbitTexture.height) { bunny.speedY *= -0.85; bunny.setY(maxY - wabbitTexture.height); if (Math .random() > 0.5 ) { bunny.speedY -= Math .random() * 6 ; } } else if (bunny.getY() < minY) { bunny.speedY = 0; bunny.setY(minY); } } layer.draw(); requestAnimationFrame(update); stats.end(); } </script > </body > </html >