


Eine kurze Diskussion über die Verwendung des Caches zur Optimierung der Leistung von HTML5 Canvas. Programm_HTML5-Tutorial-Fähigkeiten
Wenn Sie zu viel mit der Leinwand herumspielen, werden Sie automatisch über Leistungsprobleme nachdenken. Wie optimiert man die Leinwandanimation?
【Cache verwenden】
Cache verwenden bedeutet, für das Vorrendern eine Off-Screen-Leinwand zu verwenden. Das Prinzip ist sehr einfach: Zeichnen Sie zuerst in eine Off-Screen-Leinwand und zeichnen Sie dann die Off-Screen-Leinwand über drawImage in die Haupt-Leinwand. Viele Leute verstehen das vielleicht falsch. Ist das nicht ein doppelter Puffermechanismus, der in Spielen häufig verwendet wird?
Tatsächlich wird der doppelte Puffermechanismus in der Spielprogrammierung verwendet, um ein Flackern des Bildschirms zu verhindern. Daher wird vor dem Benutzer eine Leinwand angezeigt und beim Zeichnen wird der Bildschirminhalt zuerst angezeigt Hintergrund-Leinwand, und dann wird die Hintergrund-Leinwand gezeichnet. Die Daten in der Leinwand werden auf die vordere Leinwand gezeichnet. Dies ist eine doppelte Pufferung, aber in Canvas gibt es keine doppelte Pufferung, da moderne Browser grundsätzlich über einen integrierten Doppelpufferungsmechanismus verfügen. Daher stellt die Verwendung von Off-Screen-Canvas keine doppelte Pufferung dar, sondern behandelt Off-Screen-Canvas als Cache-Bereich. Zwischenspeichern Sie Bildschirmdaten, die wiederholt gezeichnet werden müssen, um den Verbrauch beim Aufrufen der Canvas-API zu reduzieren.
Wie wir alle wissen, verbraucht der Aufruf der Canvas-API die Leistung, wenn wir einige wiederholte Bildschirmdaten zeichnen möchten. Sie können sich die folgende DEMO ansehen
1. Es wird kein Cache verwendet
2. Cache wird verwendet, aber die Breite und Höhe der Off-Screen-Leinwand sind nicht festgelegt
3. Cache wird verwendet, aber die Breite und Höhe der Off-Screen-Leinwand sind nicht festgelegt
4. Verwenden Sie Caching und legen Sie die Breite und Höhe der Off-Screen-Leinwand fest
Sie können sehen, dass die Leistung der obigen DEMO unterschiedlich ist. Lassen Sie uns die folgenden Gründe analysieren: Um den Stil jedes Kreises zu erreichen, habe ich beim Zeichnen von Kreisen das Schleifenzeichnen verwendet Kreise auf der Seite Wenn ein bestimmter Punkt erreicht ist, ist für jeden Frame der Animation eine große Anzahl von Canvas-API-Aufrufen und eine große Menge an Berechnungen erforderlich, sodass er unabhängig von der Qualität des Browsers angezeigt wird runter.
XML/HTML-CodeInhalt in die Zwischenablage kopieren
- ctx.save();
- var j=0;
- for(var i= 1
- ;i<this.r;i =borderWidth){ ctx.beginPath();
- ctx.arc(this.x , this.y , i , 0 , 2*Math.PI);
- ctx.Stroke(); j ; }
- ctx.restore();
- 所以,我的方法很简单,每个圈圈对象里面给他一个离屏canvas作缓存区.
- 除了创建离屏canvas作为缓存之外,下面的代码中有一点很关键,就是要设置离屏canvas的宽度和高度,Leinwand生成后的默认大小是300X150;对于我的代码中每个缓存起来圈圈对象半径最大也就不超过80, 所以300X150的大小明显会造成很多空白区域, 会造成资源浪费, 所以就要设置一下离屏Leinwand的宽度和高度, 让它跟缓存起来的元素大小一致上面的四个demo很明显的显示出了性能差距,如果没有设置宽高,当页面超过400个圈圈对象时就会卡的不行了,而设置了宽高1000个圈圈对象也不觉得卡.
- XML/HTML-Code
- 复制内容到剪贴板
- var ball = function(x , y , vx , vy , useCache){
- this.x = x;
- this.y = y;
- this.vx = vx;
- this.vy = vy;
- this.color = [];
- this
- this.cacheCtx = this.cacheCanvas.getContext("2d"); this.cacheCanvas.width =
- 2*this.r; this.cacheCanvas.height
- = 2*this.r; var num
- = getZ(this.r/borderWidth); for(var j
- =0;j<num ;j ){
- this.color.push("rgba(" getZ(getRandom(0,255)) "," getZ(getRandom(0,255)) "," getZ(getRandom(0,255)) ",1)"); } this.useCache = useCache;
- if(useCache){
- this.cache();
- } }
-
Wenn ich das Kreisobjekt instanziiere, rufe ich direkt die Cache-Methode auf, zeichne den komplexen Kreis direkt in die Off-Screen-Leinwand des Kreisobjekts und speichere ihn.
XML/HTML-CodeInhalt in die Zwischenablage kopieren- cache:function(){
- this.cacheCtx.save();
- var j=0;
- this.cacheCtx.lineWidth = borderWidth; for(var i
- =1;i<this.r;i =borderWidth){ this.cacheCtx.beginPath();
- this
- this.cacheCtx.StrokeStyle = this.color[j]; this.cacheCtx.arc(this.r, this.r, i, 0, 2*Math.PI);
- this.cacheCtx.Stroke();
- j ;
- this.cacheCtx.restore();
- Dann muss ich in der nächsten Animation nur die Off-Screen-Leinwand des Kreisobjekts in die Hauptleinwand zeichnen. Auf diese Weise enthält die in jedem Frame aufgerufene CanvasAPI nur diesen Satz:
- XML/HTML-Code
ctx.drawImage(this.cacheCanvas, this.x-this.r, this.y-this.r);Im Vergleich zum vorherigen for-Schleifenzeichnen ist es wirklich viel schneller. Wenn wir also wiederholt Vektorgrafiken oder mehrere Bilder zeichnen müssen, können wir sinnvollerweise die Off-Screen-Leinwand verwenden, um die Bilddaten im Voraus zwischenzuspeichern, was den unnötigen Leistungsverbrauch bei jedem nachfolgenden Bildvorgang reduzieren kann.Inhalt in die Zwischenablage kopieren- Der Smooth-Versionscode für 1000 Kreisobjekte ist unten aufgeführt: XML/HTML-Code
- >
- <html lang="en" >
- <Kopf>
- <meta charset="UTF- 8">
- <Stil>
- Körper{
- padding:0;
- marge:0;
- Überlauf: versteckt;
- }
- #cas{
- display: block;
- background-color:rgba(0,0,0,0);
- margin:auto;
- border:1px solid;
- }
- Stil>
- <Titel>TestTitel>
- Kopf>
- <Körper>
- <div >
- <canvas id='cas' Breite="800" Höhe="600">Der Browser unterstützt kein CanvasCanvas > ;
- <div style="text- align:center">1000 Kreisobjekte bleiben nicht hängendiv>
- div>
- <Skript>
- var testBox = function(){
- var canvas = document.getElementById("cas"),
- ctx = canvas.getContext('2d'),
- borderWidth = 2,
- Bälle = []; var
- ball = function(x, y, vx, vy, useCache){
- this.x = x; this.y
- = y; this.vx = vx;
- this.vy = vy;
- this.color = [];
- this
- this.cacheCtx = this.cacheCanvas.getContext("2d"); this.cacheCanvas.width =
- 2*this.r; this.cacheCanvas.height
- = 2*this.r; var num
- = getZ(this.r/borderWidth); for(var j
- =0;j<num ;j ){
- this.color.push("rgba(" getZ(getRandom(0,255)) "," getZ(getRandom(0,255)) "," getZ(getRandom(0,255)) ",1)"); } this.useCache = useCache;
- if(useCache){
- this.cache();
- } }
- function getZ(num){
- var gerundet;
- gerundet = (0,5 num) | 0;
- // Ein double bitwise not.
- gerundet = ~~ (0,5 num);
- // Schließlich eine bitweise Linksverschiebung.
- 🎜>0; return gerundet; }
- ball.prototype = {
- paint:function(ctx){
- if(!this.useCache){
- ctx.save();
- var j=0;
- for(var i= 1
- ;i<this.r;i =borderWidth){ ctx.beginPath();
- ctx.arc(this.x , this.y , i , 0 , 2*Math.PI);
- ctx.Stroke(); j ; }
- ctx.restore();
- } else{
- ctx.drawImage(this.cacheCanvas , this.x-this.r , this.y-this.r);
- }
- },
- cache:function(){
- this.cacheCtx.save();
- var j=0;
- for(var i= 1
- ;i<this.r;i =borderWidth){ this.cacheCtx.beginPath();
- this.cacheCtx.arc(this.r , this.r , i , 0 , 2*Math.PI);
- this.cacheCtx.Stroke(); j ; }
- this.cacheCtx.restore();
- },
- move:function(){
- this.x = this.vx;
- this.y = this.vy;
- if(this.x
- > (canvas.width-this.r)||this.x
- < this.r
- ){
- 🎜>?this.r:(canvas.width-this.r); this.vx = -this.vx;
- }
- if(this.y>(canvas.height-this.r)||this.y< this.r){
- 🎜>?this.r:(canvas.height-this.r); this.vy = -this.vy; }
- this.paint(ctx);
- }
- }
- var
- Spiel = {
- init:function(){
- for(var i=
- 0;i
- <1000;i ){ var b = new ball(getRandom(0,canvas.width) , getRandom(0,canvas .height) , getRandom(-10 , 10) , getRandom(-10 , 10) , true)
- Balls.push(b); } },
- update:function(){
- ctx.clearRect(0,0,canvas.width,canvas.height);
- for(var
- i=
- 0;i
- <Kugellänge;i ){ Balls[i].move(); } },
- loop:function(){
- var _this = this;
- this.update();
- RAF(function(){
- _this.loop();
- })
- },
- start:function(){
- this.init();
- this.loop();
- }
- }
- window.RAF = (function(){
- return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || Funktion (Rückruf) {window.setTimeout(callback, 1000 / 60); };
- })();
- return Game;
- }();
- function getRandom(a , b){
- return Math.random()*(b-a) a;
- }
- window.onload = function(){
- testBox.start();
- }
- Skript>
- Körper>
- html>
Es gibt noch einen weiteren Hinweis zur Off-Screen-Leinwand: Wenn der Effekt, den Sie erzielen, darin besteht, kontinuierlich Objekte zu erstellen und zu zerstören, verwenden Sie die Off-Screen-Leinwand bitte mit Vorsicht. Binden Sie zumindest nicht die Attribute jedes Objekts, wie ich oben geschrieben habe. Stellen Sie eine Leinwand außerhalb des Bildschirms ein.
Denn wenn das Objekt auf diese Weise gebunden wird, wird auch die Leinwand außerhalb des Bildschirms zerstört, und es wird ständig eine große Anzahl von Leinwänden außerhalb des Bildschirms erstellt und zerstört, was dazu führt, dass der Leinwandpuffer a verbraucht Sie beanspruchen viele GPU-Ressourcen und führen leicht zum Absturz des Browsers oder zu ernsthaften Frame-Einfrierungen. Die Lösung besteht darin, ein Off-Screen-Canvas-Array zu erstellen, eine ausreichende Anzahl von Off-Screen-Canvas vorab zu laden, nur die noch lebenden Objekte zwischenzuspeichern und sie aus dem Cache zu entfernen, wenn die Objekte zerstört werden. Dadurch wird die Leinwand außerhalb des Bildschirms nicht zerstört.
【RequestAnimationFrame verwenden】
Ich werde das nicht im Detail erklären. Ich denke, viele Leute wissen, dass dies die beste Schleife für Animationen ist, nicht setTimeout oder setInterval. Veröffentlichen Sie direkt die Schreibmethode für die Kompatibilität:
XML/HTML-CodeInhalt in die Zwischenablage kopieren- window.RAF = (function(){
- window.requestAnimationFrame ||. window.mozRequestAnimationFrame ||. window.msRequestAnimationFrame ||.
- })();
【Gleitkommaoperationen vermeiden】
Obwohl JavaScript einige sehr praktische Rundungsmethoden bereitstellt, wie z. B. Math.floor, Math.ceil und parseInt, haben ausländische Freunde Tests durchgeführt und die parseInt-Methode erledigt einige zusätzliche Arbeiten (z. B. das Erkennen, ob die Daten ein gültiger Wert sind, parseInt). konvertiert den Parameter sogar zuerst in einen String!), daher ist die direkte Verwendung von parseInt relativ leistungsintensiver. Um es zusammenzufassen: Sie können direkt eine sehr clevere Methode verwenden, die von Ausländern geschrieben wurde:
JavaScript-CodeInhalt in die Zwischenablage kopieren1.gerundet = (0,5 Somenum) | 2.gerundet = ~~ (0,5 Somenum); 3.gerundet = (0,5 Somenum)
Wenn Sie die Operatoren nicht verstehen, können Sie einfach hier klicken: http://www.w3school.com.cn/js/pro_js_operators_bitwise.asp
Darin finden Sie detaillierte Erklärungenhttps://github.com/whxaxes/canvas-test/tree/gh-pages/src/Other-demo/cache

Heiße KI -Werkzeuge

Undresser.AI Undress
KI-gestützte App zum Erstellen realistischer Aktfotos

AI Clothes Remover
Online-KI-Tool zum Entfernen von Kleidung aus Fotos.

Undress AI Tool
Ausziehbilder kostenlos

Clothoff.io
KI-Kleiderentferner

Video Face Swap
Tauschen Sie Gesichter in jedem Video mühelos mit unserem völlig kostenlosen KI-Gesichtstausch-Tool aus!

Heißer Artikel

Heiße Werkzeuge

Notepad++7.3.1
Einfach zu bedienender und kostenloser Code-Editor

SublimeText3 chinesische Version
Chinesische Version, sehr einfach zu bedienen

Senden Sie Studio 13.0.1
Leistungsstarke integrierte PHP-Entwicklungsumgebung

Dreamweaver CS6
Visuelle Webentwicklungstools

SublimeText3 Mac-Version
Codebearbeitungssoftware auf Gottesniveau (SublimeText3)

Heiße Themen



Anleitung zum Tabellenrahmen in HTML. Hier besprechen wir verschiedene Möglichkeiten zum Definieren von Tabellenrändern anhand von Beispielen für den Tabellenrand in HTML.

Dies ist eine Anleitung für verschachtelte Tabellen in HTML. Hier diskutieren wir anhand der entsprechenden Beispiele, wie man eine Tabelle innerhalb der Tabelle erstellt.

Anleitung zum HTML-Rand links. Hier besprechen wir einen kurzen Überblick über HTML margin-left und seine Beispiele sowie seine Code-Implementierung.

Leitfaden zum HTML-Tabellenlayout. Hier besprechen wir die Werte des HTML-Tabellenlayouts zusammen mit den Beispielen und Ausgaben im Detail.

Leitfaden für HTML-Eingabeplatzhalter. Hier besprechen wir die Beispiele für HTML-Eingabeplatzhalter zusammen mit den Codes und Ausgaben.

Anleitung zum Verschieben von Text in HTML. Hier besprechen wir eine Einführung, wie Marquee-Tags funktionieren, mit Syntax und Beispielen für die Implementierung.

Leitfaden zur HTML-geordneten Liste. Hier besprechen wir auch die Einführung von HTML-geordneten Listen und Typen sowie deren Beispiele

Anleitung zum HTML-OnClick-Button. Hier diskutieren wir deren Einführung, Funktionsweise, Beispiele und Onclick-Events in verschiedenen Veranstaltungen.
