Heim >Web-Frontend >H5-Tutorial >Praktischer HTML5 Canvas-Codefall, um einen Feuerwerkseffekt zu erzielen
requestAnimationFrame wird vom Browser für das Timing verwendet Eine Schnittstelle für Schleifenoperationen , ähnlich wie setTimeout, deren Hauptzweck darin besteht, die Webseite Frame für Frame neu zu zeichnen.
Der Zweck der Einrichtung dieser API besteht darin, verschiedenen Webseitenanimationseffekten (DOM-Animation, Canvas-Animation, SVG-Animation, WebGL-Animation) einen einheitlichen Aktualisierungsmechanismus zu ermöglichen, wodurch Systemressourcen gespart und die Systemleistung verbessert wird. und Verbesserung der visuellen Effekte. Durch die Verwendung dieser API im Code teilen Sie dem Browser mit, dass Sie eine Animation ausführen möchten, und lassen den Browser eine Neuzeichnung der Webseite im nächsten Animationsframe planen.
Der Vorteil von requestAnimationFrame besteht darin, den Aktualisierungsmechanismus der Anzeige vollständig zu nutzen und Systemressourcen zu sparen. Die Anzeige verfügt über eine feste Aktualisierungsfrequenz (60 Hz oder 75 Hz), was bedeutet, dass sie nur bis zu 60 oder 75 Mal pro Sekunde neu gezeichnet werden kann. Die Grundidee von requestAnimationFrame besteht darin, mit dieser Aktualisierungsfrequenz synchron zu bleiben und diese Aktualisierungsfrequenz zu verwenden um die Seite neu zu zeichnen. Darüber hinaus stoppt die Aktualisierung der Seite mithilfe dieser API automatisch, sobald sie sich nicht mehr im aktuellen Tab des Browsers befindet. Das spart CPU, GPU und Strom.
Aber eine Sache ist zu beachten: requestAnimationFrame wird im Hauptthread abgeschlossen. Dies bedeutet, dass der Animationseffekt von requestAnimationFrame stark reduziert wird, wenn der Hauptthread sehr ausgelastet ist.
requestAnimationFrame akzeptiert eine Rückruffunktion als Parameter. Diese Rückruffunktion wird aufgerufen, bevor der Browser neu zeichnet.
requestID = window.requestAnimationFrame(callback);
Derzeit unterstützen höhere Browserversionen (Firefox 23 / IE 10 / Chrome / Safari) diese Methode. Mit der folgenden Methode können Sie prüfen, ob der Browser diese API unterstützt. Wenn dies nicht unterstützt wird, simulieren Sie die Bereitstellungsmethode selbst.
window.requestAnimFrame = (function(){ return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function( callback ){ window.setTimeout(callback, 1000 / 60); }; })();
Der obige Code simuliert requestAnimationFrame 60 Mal pro Sekunde (ungefähr einmal alle 16,7 Millisekunden).
Wenn Sie requestAnimationFrame verwenden, rufen Sie es einfach wiederholt auf.
function repeatOften() { // Do whatever requestAnimationFrame(repeatOften); } requestAnimationFrame(repeatOften);
Neuzeichnen mit cancelAnimationFrame abbrechen.
window.cancelAnimationFrame(requestID);
Sein Parameter ist ein Ganzzahlwert, der von requestAnimationFrame zurückgegeben wird und die Aufgaben-ID darstellt.
Bestimmen Sie, ob der Browser Canvas unterstützt, und stellen Sie Breite und Höhe auf die Größe des Browserfensters ein.
var canvas = document.getElementById("myCanvas"); if (!canvas.getContext) { return; } canvas.width = window.innerWidth; canvas.height = window.innerHeight;var ctx = canvas.getContext("2d");
Der Feuerwerkseffekt kann einfach so betrachtet werden, als ob er einen Punkt umgibt und die Explosion viele kleine Kugeln erzeugt, die sich zu den Seiten ausbreiten. Daher wird ein Feuerwerksobjekt benötigt. Dieses Objekt erfasst hauptsächlich den Standort des Feuerwerks und die Informationen über die umliegenden Kugeln. Unser Feuerwerksobjekt ist also wie folgt definiert.
function FireWork() { this.x = -1; this.y = -1; this.balls = []; }
Welche Methoden sollte dieses Objekt haben?
Erstelle zunächst die kleine Kugel, die explodiert.
createBalls: function () { for (var i = 0; i < 300; i++) { var angle = Math.random() * Math.PI * 2, radius = getRandom(50, 200); this.balls.push(new Ball(fwx, fwy, fwx + Math.cos(angle) * radius, fwy + Math.sin(angle) * radius)); } }
Hinweis: Hier ist fwx die X-Achsen-Koordinate der Feuerwerksposition, fwy ist die Y-Achsen-Koordinate der Feuerwerksposition, das Gleiche unten.
Die Lauflänge des Balls ist hier ein zufälliger Wert von 50 bis 200. Der Startpunkt der Flugbahn des Balls ist die Position des Feuerwerks und der Endpunkt ist ein zufälliger Punkt auf einem Kreis.
Dann muss das Feuerwerk initialisiert werden, hauptsächlich um die Position zu bestimmen und kleine Kugeln zu erzeugen.
init: function () { this.x = getRandom(200, width - 200); this.y = getRandom(200, height - 200); fwx = this.x; fwy = this.y; this.createBalls(); drawCount = 0; currBallIndex = 0; }
Hinweis: Hier ist drawCount die Anzahl der Ziehungen und currBallIndex der aktuell gezogene Ball Index .
Das gesamte FireWork ist wie folgt definiert.
function FireWork() { this.x = -1; this.y = -1; this.balls = []; } FireWork.prototype = { init: function () { this.x = getRandom(200, width - 200); this.y = getRandom(200, height - 200); fwx = this.x; fwy = this.y; this.createBalls(); drawCount = 0; currBallIndex = 0; }, run: function () { this.init(); }, createBalls: function () { for (var i = 0; i < 300; i++) { var angle = Math.random() * Math.PI * 2, radius = getRandom(50, 200); this.balls.push(new Ball(fwx, fwy, fwx + Math.cos(angle) * radius, fwy + Math.sin(angle) * radius)); } } }
Der Ball muss die Position seines Start- und Endpunkts kennen, also ist er es wie folgt definiert.
function Ball(bx, by, ex, ey) { this.bx = bx;//起点X轴坐标 this.by = by;//起点Y轴坐标 this.ex = ex;//终点X轴坐标 this.ey = ey;//终点Y轴坐标}
Der Ball muss auch in der Lage sein, die aktuellen Koordinaten und die nächsten Zeichnungskoordinaten basierend auf der aktuellen Anzahl der Zeichnungen und der Gesamtzahl der Zeichnungen zu berechnen. Die gerade Linie, die diese beiden Koordinaten verbindet, ist der Inhalt Diesmal wird gezeichnet, also Die Definition lautet wie folgt.
Ball.prototype = { getSpan: function () { var xSpan = (this.ex - this.bx) / allDrawCount, ySpan = (this.ey - this.by) / allDrawCount; return { x: xSpan, y: ySpan }; }, currPosition: function () { var span = this.getSpan(), currX = -1, currY = -1; if (drawCount < allDrawCount) { currX = this.bx + span.x * (drawCount - 1); currY = this.by + span.y * (drawCount - 1); return { x: currX, y: currY }; } return null; }, nextPosition: function () { var span = this.getSpan(), currX = -1, currY = -1; if (drawCount < allDrawCount) { currX = this.bx + span.x * drawCount; currY = this.by + span.y * drawCount; return { x: currX, y: currY }; } return null; } }
var fwx = -1, //烟花位置X轴坐标 fwy = -1, //烟花位置Y轴坐标 currFW = null, //烟花实例 currBallIndex = -1, //当前正在绘制的小球索引 drawCount = 0, //绘制次数 allDrawCount = 40, //总共需要的绘制次数 width = canvas.width, //画布宽度 height = canvas.height; //画布高度
und dann gibt es noch mehrere Tool-Methoden.
function componentToHex(c) { var hex = c.toString(16); return hex.length == 1 ? "0" + hex : hex; }function rgbToHex(r, g, b) { return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); }function getRandom(minNum, maxNum) { var iChoices = maxNum - minNum + 1; return Math.floor(Math.random() * iChoices + minNum); }
Schließlich gibt es noch eine Zeichenmethode, die von requestAnimationFrame aufgerufen wird. Diese Zeichenmethode besteht darin, den Pfad des explodierenden Balls (ein Liniensegment einschließlich Startpunkt und Endpunkt) basierend auf der aktuellen Anzahl von Zeichnungen zu ermitteln und dann den zuletzt gezeichneten Pfad zu löschen.
Wenn der Effekt eines Feuerwerks gezeichnet ist, fahren Sie mit dem Zeichnen des nächsten Feuerwerks fort.
function drawLine(span) { if (currFW && currBallIndex !== -1) { if (drawCount <p>Die Farbe hier ist ein zufälliger Wert. </p><h2> (7) Beginnen Sie mit dem Zeichnen </h2><p>Der letzte Schritt besteht darin, mit dem Zeichnen zu beginnen. </p><pre class="brush:html;toolbar:false;">currFW = new FireWork(); currFW.run(); requestAnimationFrame(drawLine);
Der gesamte Code lautet wie folgt, insgesamt 160 Zeilen.
1 (function () { 2 var requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) { 3 return window.setTimeout(callback, 1000 / 60); 4 }; 5 window.requestAnimationFrame = requestAnimationFrame; 6 })(); 7 8 var canvas = document.getElementById("myCanvas"); 9 if (!canvas.getContext) { 10 return; 11 } 12 canvas.width = window.innerWidth; 13 canvas.height = window.innerHeight; 14 15 var ctx = canvas.getContext("2d"); 16 17 var fwx = -1, 18 fwy = -1, 19 currFW = null, 20 currBallIndex = -1, 21 drawCount = 0, 22 allDrawCount = 40, 23 width = canvas.width, 24 height = canvas.height; 25 26 function componentToHex(c) { 27 var hex = c.toString(16); 28 return hex.length == 1 ? "0" + hex : hex; 29 } 30 31 function rgbToHex(r, g, b) { 32 return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b); 33 } 34 35 function getRandom(minNum, maxNum) { 36 var iChoices = maxNum - minNum + 1; 37 return Math.floor(Math.random() * iChoices + minNum); 38 } 39 40 function drawLine(span) { 41 if (currFW && currBallIndex !== -1) { 42 if (drawCount <= allDrawCount) { 43 ctx.save(); 44 drawCount++; 45 for (var i = 0, j = currFW.balls.length; i < j; i++) { 46 var currBall = currFW.balls[i], 47 beginPoint = currBall.currPosition(), 48 endPoint = currBall.nextPosition(); 49 if (beginPoint && endPoint) { 50 console.log(currBallIndex, drawCount, currBall, beginPoint, endPoint); 51 ctx.beginPath(); 52 ctx.moveTo(currBall.bx, currBall.by); 53 ctx.lineTo(beginPoint.x, beginPoint.y); 54 ctx.strokeStyle = "#000"; 55 ctx.stroke(); 56 ctx.beginPath(); 57 ctx.moveTo(beginPoint.x, beginPoint.y); 58 ctx.lineTo(endPoint.x, endPoint.y); 59 var r = getRandom(0, 255); 60 var g = getRandom(0, 255); 61 var b = getRandom(0, 255); 62 ctx.strokeStyle = rgbToHex(r, g, b); 63 ctx.stroke(); 64 } else { 65 ctx.beginPath(); 66 ctx.moveTo(currBall.bx, currBall.by); 67 ctx.lineTo(currBall.ex, currBall.ey); 68 ctx.strokeStyle = "#000"; 69 ctx.stroke(); 70 } 71 } 72 currBallIndex++; 73 currBallIndex %= currFW.balls.length; 74 ctx.restore(); 75 } else { 76 ctx.clearRect(0, 0, width, height); 77 currFW = new FireWork(); 78 currFW.run(); 79 } 80 } 81 requestAnimationFrame(drawLine); 82 } 83 84 function FireWork() { 85 this.x = -1; 86 this.y = -1; 87 this.balls = []; 88 } 89 90 FireWork.prototype = { 91 init: function () { 92 this.x = getRandom(200, width - 200); 93 this.y = getRandom(200, height - 200); 94 fwx = this.x; 95 fwy = this.y; 96 this.createBalls(); 97 drawCount = 0; 98 currBallIndex = 0; 99 }, 100 run: function () { 101 this.init(); 102 }, 103 createBalls: function () { 104 for (var i = 0; i < 300; i++) { 105 var angle = Math.random() * Math.PI * 2, 106 radius = getRandom(50, 200); 107 this.balls.push(new Ball(fwx, fwy, fwx + Math.cos(angle) * radius, fwy + Math.sin(angle) * radius)); 108 } 109 } 110 } 111 112 function Ball(bx, by, ex, ey) { 113 this.bx = bx; 114 this.by = by; 115 this.ex = ex; 116 this.ey = ey; 117 } 118 119 Ball.prototype = { 120 getSpan: function () { 121 var xSpan = (this.ex - this.bx) / allDrawCount, 122 ySpan = (this.ey - this.by) / allDrawCount; 123 return { 124 x: xSpan, 125 y: ySpan 126 }; 127 }, 128 currPosition: function () { 129 var span = this.getSpan(), 130 currX = -1, 131 currY = -1; 132 if (drawCount < allDrawCount) { 133 currX = this.bx + span.x * (drawCount - 1); 134 currY = this.by + span.y * (drawCount - 1); 135 return { 136 x: currX, 137 y: currY 138 }; 139 } 140 return null; 141 }, 142 nextPosition: function () { 143 var span = this.getSpan(), 144 currX = -1, 145 currY = -1; 146 if (drawCount < allDrawCount) { 147 currX = this.bx + span.x * drawCount; 148 currY = this.by + span.y * drawCount; 149 return { 150 x: currX, 151 y: currY 152 }; 153 } 154 return null; 155 } 156 } 157 158 currFW = new FireWork(); 159 currFW.run(); 160 requestAnimationFrame(drawLine);
Willkommen zur Diskussion.
Das obige ist der detaillierte Inhalt vonPraktischer HTML5 Canvas-Codefall, um einen Feuerwerkseffekt zu erzielen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!