Advertisement
  1. Web Design
  2. Animation

HTML5 Canvas-Optimierung: Ein praktisches Beispiel 

Scroll to top
Read Time: 34 min

() translation by (you can also view the original English article)

Wenn Sie getan haben JavaScript-Entwicklung lange genug, haben Sie wahrscheinlich crashed Sie Ihren browser ein paar mal. Das problem in der Regel stellt sich heraus, dass einige JavaScript-Fehler, wie eine endlose while-Schleife; wenn nicht, ist der nächste verdächtige ist die Seite von Transformationen oder Animationen - die Art, die beinhalten das hinzufügen und entfernen von Elemente aus der Webseite oder das animieren von CSS-Eigenschaften.   Dieses tutorial konzentriert sich auf die Optimierung der Animationen erzeugt mit JS und HTML5 - - element.

Dieses tutorial beginnt und endet mit dem, was die HTML5-animation widget, das Sie unten sehen: 

Wir nehmen Sie mit auf eine Reise, die Erkundung der verschiedenen schwellen-Leinwand-Optimierung Tipps und Techniken und wenden Sie Sie auf die widget-JavaScript-source-code. Das Ziel ist die Verbesserung auf dem widget die Ausführung, die Geschwindigkeit und am Ende eine glattere, mehr Flüssigkeit animation widget, angetrieben durch schlankere, effizientere JavaScript. 

Der source-download-enthält die HTML-und JavaScript von jedem Schritt im tutorial, so können Sie entlang Folgen von jedem Punkt. 

Nehmen wir den ersten Schritt. 


Schritt 1: Spielen Sie den Film-Anhänger 

 Das widget oben ist auf der Grundlage der Film-trailer zu Sintel, ein 3D-Animationsfilm der Blender Foundation. Es ist gebaut mit Hilfe von zwei HTML5 beliebtesten Ergänzungen: das und - Elemente.

 Das - lädt und spielt die Sintel video-Datei, während das erzeugt seine eigene animation Sequenz von Momentaufnahmen der Wiedergabe von Videos und mischen es mit text und anderen Grafiken. Wenn Sie klicken, um das video abzuspielen, wird die Leinwand zu neuem Leben erweckt, mit einem dunklen hintergrund, der eine größere schwarze und weiße Kopie der Wiedergabe von video.  Kleinere, farbige screen-shots des Videos kopiert werden, um die Szene, und gleiten über die es als Teil einer Filmrolle, illustration.

 In der linken oberen Ecke, wir haben den Titel und ein paar Zeilen beschreibenden text, fade in und out, während die animation spielt.  Das Skript ist Leistung, Geschwindigkeit und verwandten Metriken sind Teil der animation, in der kleinen schwarzen box in der linken unteren Ecke mit einem Diagramm und lebendigen text. Wir werden uns an dieser besonderen Sache im detail später.

 Schließlich gibt es einen großen, sich drehenden Klinge, die fliegt über die Szene am Anfang der animation, dessen Grafik geladen wird, eine externe PNG-Bild-Datei.


Schritt 2: die Quelle Anzeigen 

 Der Quellcode enthält die übliche Mischung von HTML, CSS und Javascript. Die HTML ist spärlich: nur die und - tags eingeschlossen in einem container :

1
<div id="animationWidget" >
2
  <canvas width="368" height="208" id="mainCanvas" ></canvas>	
3
	<video width="184" height="104" id="video" autobuffer="autobuffer" controls="controls" poster="poster.jpg" >
4
		<source src="sintel.mp4" type="video/mp4" ></source>
5
		<source src="sintel.webm" type="video/webm" ></source>
6
	</video>
7
</div>

 Der container eine ID (animationWidget), die fungiert als einen Haken für alle CSS-Regeln angewendet und Ihr Inhalt (unten).

1
 
2
#animationWidget{
3
	border:1px #222 solid;
4
	position:relative;
5
	width: 570px;
6
	height: 220px;
7
}
8
#animationWidget canvas{
9
	border:1px #222 solid;
10
	position:absolute;
11
	top:5px;
12
	left:5px;			
13
}
14
#animationWidget video{
15
	position:absolute;
16
	top:110px;
17
	left:380px;		
18
}

 Während HTML und CSS sind Sie die Marinade Gewürze und Gewürze, die die JavaScript, die das Fleisch des widgets.

  • An der Spitze, haben wir die wichtigsten Objekte, die oft benutzt werden durch das Skript, einschließlich der Verweise auf das canvas-element und sein 2D-Kontext. 
  • Die init () - Funktion wird aufgerufen, wenn die video-Wiedergabe beginnt, und setzt alle Objekte in dem Skript verwendet. 
  • Die sampleVideo () - Funktion erfasst den aktuellen frame der Wiedergabe von video, während setBlade() lädt eine externe Bild erforderlich, die von der animation. 
  •  Das Tempo und die Inhalte des canvas-animation gesteuert werden, die von der main () - Funktion, die wie das Skript Herzschlag. Führen Sie in regelmäßigen Abständen, einmal das video zu spielen beginnt, sind es Malt jedes Bild der animation, indem Sie zunächst das clearing der Leinwand, dann ruft jeder von dem Skript die fünf Funktionen zum zeichnen:
    • drawBackground() 
    •  drawFilm()
    • drawTitle() 
    • drawDescription() 
    •  drawStats()

 Wie die Namen bereits andeuten, jede Zeichnung Funktion ist verantwortlich für die Zeichnung ein Element in der animation Szene. Die Strukturierung der code auf diese Weise erhöht die Flexibilität und macht zukünftige Wartung zu erleichtern.

 Das volle Skript ist unten gezeigt. Nehmen Sie sich einen moment Zeit, um zu bewerten, und sehen, ob Sie können vor Ort alle änderungen, die Sie machen würde, um ihn zu beschleunigen.

1
(function(){
2
	if( !document.createElement("canvas").getContext ){ return; } //the canvas tag isn't supported

3
	
4
	var mainCanvas = document.getElementById("mainCanvas"); // points to the HTML canvas element above

5
	var mainContext = mainCanvas.getContext('2d'); //the drawing context of the canvas element

6
	var video = document.getElementById("video"); // points to the HTML video element

7
	var frameDuration = 33; // the animation's speed in milliseconds

8
	video.addEventListener( 'play', init ); // The init() function is called whenever the user presses play & the video starts/continues playing

9
	video.addEventListener( 'ended', function(){ drawStats(true); } ); //drawStats() is called one last time when the video end, to sum up all the statistics 		

10
	
11
	var videoSamples; // this is an array of images, used to store all the snapshots of the playing video taken over time. These images are used to create the 'film reel'

12
	var backgrounds; // this is an array of images, used to store all the snapshots of the playing video taken over time. These images are used as the canvas background

13
	var blade; //An canvas element to store the image copied from blade.png 

14
	var bladeSrc = 'blade.png'; //path to the blade's image source file

15
	
16
	var lastPaintCount = 0; // stores the last value of mozPaintCount sampled

17
	var paintCountLog = []; // an array containing all measured values of mozPaintCount over time

18
	var speedLog = []; // an array containing all the execution speeds of main(), measured in milliseconds

19
	var fpsLog = []; // an array containing the calculated frames per secong (fps) of the script, measured by counting the calls made to main() per second

20
	var frameCount = 0; // counts the number of times main() is executed per second.

21
	var frameStartTime = 0; // the last time main() was called

22
	
23
	// Called when the video starts playing. Sets up all the javascript objects required to generate the canvas animation and measure perfomance

24
	function init(){ 
25
		if( video.currentTime > 1 ){ return; }		
26
27
		bladeSrc = new Image();
28
		bladeSrc.src = "blade.png";
29
		bladeSrc.onload = setBlade;
30
		
31
		backgrounds = [];			
32
		videoSamples = [];
33
		fpsLog = [];
34
		paintCountLog = [];	
35
		if( window.mozPaintCount ){ lastPaintCount = window.mozPaintCount; }
36
		speedLog = [];
37
		frameCount = 0;	
38
		frameStartTime = 0;
39
		main(); 
40
		setTimeout( getStats, 1000 );
41
	}
42
	
43
	// As the scripts main function, it controls the pace of the animation

44
	function main(){	
45
		setTimeout( main, frameDuration );
46
		if( video.paused || video.ended ){ return; }
47
		
48
		var now = new Date().getTime(); 
49
		if( frameStartTime ){ 
50
			speedLog.push( now - frameStartTime );
51
		}
52
		frameStartTime = now;
53
		if( video.readyState < 2 ){ return; }
54
		
55
		frameCount++;
56
		mainCanvas.width = mainCanvas.width; //clear the canvas

57
		drawBackground(); 
58
		drawFilm();
59
		drawDescription();
60
		drawStats();
61
		drawBlade();
62
		drawTitle();
63
	}
64
	
65
	// This function is called every second, and it calculates and stores the current frame rate

66
	function getStats(){
67
		if( video.readyState >= 2 ){
68
			if( window.mozPaintCount ){ //this property is specific to firefox, and tracks how many times the browser has rendered the window since the document was loaded

69
				paintCountLog.push( window.mozPaintCount - lastPaintCount );
70
				lastPaintCount = window.mozPaintCount;
71
			}			
72
			
73
			fpsLog.push(frameCount);
74
			frameCount = 0;	
75
		}
76
		setTimeout( getStats, 1000 );
77
	}
78
	
79
	// create blade, the ofscreen canavs that will contain the spining animation of the image copied from blade.png

80
	function setBlade(){
81
		blade = document.createElement("canvas");
82
		blade.width = 400;
83
		blade.height = 400;			
84
		blade.angle = 0;
85
		blade.x = -blade.height * 0.5;
86
		blade.y = mainCanvas.height/2 - blade.height/2; 
87
	}
88
			
89
	// Creates and returns a new image that contains a snapshot of the currently playing video.

90
	function sampleVideo(){
91
		var newCanvas = document.createElement("canvas");
92
		newCanvas.width = video.width;
93
		newCanvas.height = video.height; 
94
		newCanvas.getContext("2d").drawImage( video, 0, 0, video.width, video.height );
95
		return newCanvas;	
96
	}
97
	
98
	// renders the dark background for the whole canvas element. The background features a greyscale sample of the video and a gradient overlay

99
	function drawBackground(){
100
		var newCanvas = document.createElement("canvas");
101
		var newContext = newCanvas.getContext("2d");
102
		newCanvas.width = mainCanvas.width;
103
		newCanvas.height = mainCanvas.height; 
104
		newContext.drawImage(  video, 0, video.height * 0.1, video.width, video.height * 0.5, 0, 0, mainCanvas.width, mainCanvas.height  );
105
			
106
		var imageData, data;
107
		try{
108
			imageData = newContext.getImageData( 0, 0, mainCanvas.width, mainCanvas.height );
109
			data = imageData.data;
110
		} catch(error){ // CORS error (eg when viewed from a local file). Create a solid fill background instead

111
			newContext.fillStyle = "yellow";
112
			newContext.fillRect( 0, 0, mainCanvas.width, mainCanvas.height );
113
			imageData = mainContext.createImageData( mainCanvas.width, mainCanvas.height );
114
			data = imageData.data;
115
		}
116
		
117
		//loop through each pixel, turning its color into a shade of grey

118
		for( var i = 0; i < data.length; i += 4 ){
119
			var red = data[i]; 
120
			var green = data[i + 1]; 
121
			var blue = data[i + 2]; 
122
			var grey = Math.max( red, green, blue );
123
			
124
			data[i] =  grey;
125
			data[i+1] = grey;
126
			data[i+2] = grey;
127
		}
128
		newContext.putImageData( imageData, 0, 0 );
129
		
130
		//add the gradient overlay

131
		var gradient = newContext.createLinearGradient( mainCanvas.width/2, 0, mainCanvas.width/2, mainCanvas.height );
132
		gradient.addColorStop( 0, '#000' );
133
		gradient.addColorStop( 0.2, '#000' );
134
		gradient.addColorStop( 1, "rgba(0,0,0,0.5)" );
135
		newContext.fillStyle = gradient;
136
		newContext.fillRect( 0, 0, mainCanvas.width, mainCanvas.height );
137
		
138
		mainContext.save();
139
		mainContext.drawImage( newCanvas, 0, 0, mainCanvas.width, mainCanvas.height );
140
		
141
		mainContext.restore();
142
	}
143
	
144
	// renders the 'film reel' animation that scrolls across the canvas

145
	function drawFilm(){
146
		var sampleWidth = 116; // the width of a sampled video frame, when painted on the canvas as part of a 'film reel'

147
		var sampleHeight = 80; // the height of a sampled video frame, when painted on the canvas as part of a 'film reel'

148
		var filmSpeed = 20; // determines how fast the 'film reel' scrolls across the generated canvas animation.

149
		var filmTop = 120; //the y co-ordinate of the 'film reel' animation

150
		var filmAngle = -10 * Math.PI / 180; //the slant of the 'film reel'

151
		var filmRight = ( videoSamples.length > 0 )? videoSamples[0].x + videoSamples.length * sampleWidth : mainCanvas.width; //the right edge of the 'film reel' in pixels, relative to the canvas		

152
		
153
		//here, we check if the first frame of the 'film reel' has scrolled out of view 

154
		if( videoSamples.length > 0 ){
155
			var bottomLeftX = videoSamples[0].x + sampleWidth;
156
			var bottomLeftY = filmTop + sampleHeight;
157
			bottomLeftX = Math.floor( Math.cos(filmAngle) * bottomLeftX - Math.sin(filmAngle) * bottomLeftY ); // the final display position after rotation

158
			
159
			if( bottomLeftX < 0 ){ //the frame is offscreen, remove it's refference from the film array

160
				videoSamples.shift();			
161
			}			
162
		}			
163
		
164
		// add new frames to the reel as required

165
		while( filmRight <= mainCanvas.width ){
166
			var newFrame = {};
167
			newFrame.x = filmRight;
168
			newFrame.canvas = sampleVideo();
169
			videoSamples.push(newFrame);			
170
			filmRight += sampleWidth;			
171
		}
172
		
173
		// create the gradient fill for the reel

174
		var gradient = mainContext.createLinearGradient( 0, 0, mainCanvas.width, mainCanvas.height );
175
		gradient.addColorStop( 0, '#0D0D0D' );
176
		gradient.addColorStop( 0.25, '#300A02' );
177
		gradient.addColorStop( 0.5, '#AF5A00' );
178
		gradient.addColorStop( 0.75, '#300A02' );
179
		gradient.addColorStop( 1, '#0D0D0D' );			
180
			
181
		mainContext.save();
182
		mainContext.globalAlpha = 0.9;
183
		mainContext.fillStyle = gradient;			
184
		mainContext.rotate(filmAngle);
185
		
186
		// loops through all items of film array, using the stored co-ordinate values of each to draw part of the 'film reel'

187
		for( var i in videoSamples ){
188
			var sample = videoSamples[i];				
189
			var punchX, punchY, punchWidth = 4, punchHeight = 6, punchInterval = 11.5;
190
			
191
			//draws the main rectangular box of the sample

192
			mainContext.beginPath();
193
			mainContext.moveTo( sample.x, filmTop );
194
			mainContext.lineTo( sample.x + sampleWidth, filmTop );
195
			mainContext.lineTo( sample.x + sampleWidth, filmTop + sampleHeight );
196
			mainContext.lineTo( sample.x, filmTop + sampleHeight );
197
			mainContext.closePath();				
198
			
199
			//adds the small holes lining the top and bottom edges of the 'fim reel'

200
			for( var j = 0; j < 10; j++ ){
201
				punchX = sample.x + ( j * punchInterval ) + 5;
202
				punchY = filmTop + 4;
203
				mainContext.moveTo( punchX, punchY + punchHeight );
204
				mainContext.lineTo( punchX + punchWidth, punchY + punchHeight );
205
				mainContext.lineTo( punchX + punchWidth, punchY );				
206
				mainContext.lineTo( punchX, punchY );
207
				mainContext.closePath();
208
				punchX = sample.x + ( j * punchInterval ) + 5;
209
				punchY = filmTop + 70;
210
				mainContext.moveTo( punchX, punchY + punchHeight );
211
				mainContext.lineTo( punchX + punchWidth, punchY + punchHeight );
212
				mainContext.lineTo( punchX + punchWidth, punchY );				
213
				mainContext.lineTo( punchX, punchY );
214
				mainContext.closePath();
215
			} 
216
			mainContext.fill();			
217
		}		
218
		
219
		//loop through all items of videoSamples array, update the x co-ordinate values of each item, and draw its stored image onto the canvas

220
		mainContext.globalCompositeOperation = 'lighter';
221
		for( var i in videoSamples ){
222
			var sample = videoSamples[i];
223
			sample.x -= filmSpeed;	
224
			mainContext.drawImage( sample.canvas, sample.x + 5, filmTop + 10, 110, 62 );			
225
		}
226
		
227
		mainContext.restore();			
228
	}
229
	
230
	// renders the canvas title

231
	function drawTitle(){
232
		mainContext.save();
233
		mainContext.fillStyle = 'black';
234
		mainContext.fillRect( 0, 0, 368, 25 ); 
235
		mainContext.fillStyle = 'white';
236
		mainContext.font = "bold 21px Georgia";
237
		mainContext.fillText( "SINTEL", 10, 20 );	
238
		mainContext.restore();
239
	}
240
	
241
	// renders all the text appearing at the top left corner of the canvas

242
	function drawDescription(){		
243
		var text = []; //stores all text items, to be displayed over time. the video is 60 seconds, and each will be visible for 10 seconds.

244
		text[0] = "Sintel is an independently produced short film, initiated by the Blender Foundation.";
245
		text[1] = "For over a year an international team of 3D animators and artists worked in the studio of the Amsterdam Blender Institute on the computer-animated short 'Sintel'.";
246
		text[2] = "It is an epic short film that takes place in a fantasy world, where a girl befriends a baby dragon.";
247
		text[3] = "After the little dragon is taken from her violently, she undertakes a long journey that leads her to a dramatic confrontation.";
248
		text[4] = "The script was inspired by a number of story suggestions by Martin Lodewijk around a Cinderella character (Cinder in Dutch is 'Sintel'). ";
249
		text[5] = "Screenwriter Esther Wouda then worked with director Colin Levy to create a script with multiple layers, with strong characterization and dramatic impact as central goals.";			
250
		text = text[Math.floor( video.currentTime / 10 )]; //use the videos current time to determine which text item to display.  

251
		
252
		mainContext.save();
253
		var alpha = 1 - ( video.currentTime % 10 ) / 10;
254
		mainContext.globalAlpha = ( alpha < 5 )? alpha : 1;
255
		mainContext.fillStyle = '#fff';
256
		mainContext.font = "normal 12px Georgia";
257
		
258
		//break the text up into several lines as required, and write each line on the canvas

259
		text = text.split(' ');
260
		var colWidth = mainCanvas.width * .75;
261
		var line = '';
262
		var y = 40;
263
		for(var i in text ){
264
			line += text[i] + ' ';
265
			if( mainContext.measureText(line).width > colWidth ){
266
				mainContext.fillText( line, 10, y ); 
267
				line = '';
268
				y += 12;				
269
			}			
270
		}
271
		mainContext.fillText( line, 10, y ); 
272
		
273
		mainContext.restore();
274
	}
275
	
276
	//updates the bottom-right potion of the canvas with the latest perfomance statistics

277
	function drawStats( average ){			
278
		var x = 245.5, y = 130.5, graphScale = 0.25;
279
		
280
		mainContext.save();
281
		mainContext.font = "normal 10px monospace";
282
		mainContext.textAlign = 'left';
283
		mainContext.textBaseLine = 'top';
284
		mainContext.fillStyle = 'black';
285
		mainContext.fillRect( x, y, 120, 75 );			
286
		
287
		//draw the x and y axis lines of the graph

288
		y += 30;	
289
		x += 10;			
290
		mainContext.beginPath();
291
		mainContext.strokeStyle = '#888';
292
		mainContext.lineWidth = 1.5;
293
		mainContext.moveTo( x, y );
294
		mainContext.lineTo( x + 100, y );
295
		mainContext.stroke();
296
		mainContext.moveTo( x, y );
297
		mainContext.lineTo( x, y - 25 );
298
		mainContext.stroke();			
299
		
300
		// draw the last 50 speedLog entries on the graph

301
		mainContext.strokeStyle = '#00ffff';
302
		mainContext.fillStyle = '#00ffff';
303
		mainContext.lineWidth = 0.3;
304
		var imax = speedLog.length;
305
		var i = ( speedLog.length > 50 )? speedLog.length - 50 : 0
306
		mainContext.beginPath();				
307
		for( var j = 0; i < imax; i++, j += 2 ){				
308
			mainContext.moveTo( x + j, y );
309
			mainContext.lineTo( x + j, y - speedLog[i] * graphScale );		
310
			mainContext.stroke();
311
		}
312
		
313
		// the red line, marking the desired maximum rendering time

314
		mainContext.beginPath();
315
		mainContext.strokeStyle = '#FF0000';
316
		mainContext.lineWidth = 1;
317
		var target = y - frameDuration * graphScale;				
318
		mainContext.moveTo( x, target );
319
		mainContext.lineTo( x + 100, target );		
320
		mainContext.stroke();
321
		
322
		// current/average speedLog items

323
		y += 12;
324
		if( average ){
325
			var speed = 0;
326
			for( i in speedLog ){ speed += speedLog[i]; }
327
			speed = Math.floor( speed / speedLog.length * 10) / 10;
328
		}else {
329
			speed = speedLog[speedLog.length-1];
330
		}
331
		mainContext.fillText( 'Render Time: ' + speed, x, y );
332
		
333
		// canvas fps

334
		mainContext.fillStyle = '#00ff00';
335
		y += 12;
336
		if( average ){
337
			fps = 0;
338
			for( i in fpsLog ){ fps += fpsLog[i]; }
339
			fps = Math.floor( fps / fpsLog.length * 10) / 10;
340
		}else {
341
			fps = fpsLog[fpsLog.length-1];
342
		}
343
		mainContext.fillText( ' Canvas FPS: ' + fps, x, y );
344
		
345
		// browser frames per second (fps), using window.mozPaintCount (firefox only)

346
		if( window.mozPaintCount ){ 	
347
			y += 12;
348
			if( average ){
349
				fps = 0;
350
				for( i in paintCountLog ){ fps += paintCountLog[i]; }
351
				fps = Math.floor( fps / paintCountLog.length * 10) / 10;
352
			}else {	
353
				fps = paintCountLog[paintCountLog.length-1];	
354
			}
355
			mainContext.fillText( 'Browser FPS: ' + fps, x, y );
356
		}
357
		
358
		mainContext.restore();
359
	}
360
	
361
	//draw the spining blade that appears in the begining of the animation	

362
	function drawBlade(){ 
363
		if( !blade || blade.x > mainCanvas.width ){ return; }
364
		blade.x += 2.5;
365
		blade.angle = ( blade.angle - 45 ) % 360;
366
		
367
		//update blade, an ofscreen canvas containing the blade's image

368
		var angle = blade.angle * Math.PI / 180;			
369
		var bladeContext = blade.getContext('2d');
370
		blade.width = blade.width; //clear the canvas

371
		bladeContext.save(); 
372
		bladeContext.translate( 200, 200 ); 
373
		bladeContext.rotate(angle); 
374
		bladeContext.drawImage( bladeSrc, -bladeSrc.width/2, -bladeSrc.height/2 );
375
		bladeContext.restore();
376
		
377
		mainContext.save(); 
378
		mainContext.globalAlpha = 0.95;
379
		mainContext.drawImage( blade, blade.x, blade.y + Math.sin(angle) * 50 ); 
380
		mainContext.restore();
381
	}	
382
})();

Schritt 3: Code-Optimierung: die Regeln Kennen 

Die erste Regel der code-performance Optimierung ist: nicht. 

Der Sinn dieser Regel ist zu entmutigen Optimierung für die Optimierung Willen, da der Prozess kommt zu einem Preis. 

 Ein optimiertes Skript wird leichter sein, für die browser Parsen und verarbeiten, aber in der Regel mit einer Belastung für die Menschen, die finden es schwieriger zu Folgen und pflegen. Wenn Sie entscheiden, dass einige Optimierung erforderlich ist, setzen einige Ziele, die vorher, so dass Sie nicht auf Abwege geraten durch den Prozess und es übertreiben.

 Das Ziel bei der Optimierung dieses widget wird an die main () - Funktion ausgeführt, die in weniger als 33 Millisekunden, wie es sollte, die passt die frame-rate der Wiedergabe von video-Dateien (sintel.mp4 und sintel.webm). Diese Dateien verschlüsselt wurden, an eine Wiedergabe-Geschwindigkeit von 30 (dreißig Bilder pro Sekunde), was übersetzt etwa 0.33 Sekunden oder 33 Millisekunden pro Bild ( 1 Sekunde ÷ 30 frames ).

 Da JavaScript zeichnet eine neue animation frame auf die Leinwand jedes mal die main () - Funktion aufgerufen, die das Ziel der Optimierung wird der Prozess sein, um diese Funktion nutzen 33 Millisekunden oder weniger jedes mal, wenn es läuft. Diese Funktion wiederholt sich mit einem setTimeout (), Javascript-timer, wie unten gezeigt.

1
 
2
var frameDuration = 33; // set the animation's target speed in milliseconds	

3
function main(){
4
	if( video.paused || video.ended ){ return false; }			
5
	setTimeout( main, frameDuration );

.

 Diese Regel unterstreicht den Punkt, dass die Optimierung sollte immer durchgeführt werden, am Ende des Entwicklungsprozesses, wenn Sie bereits konkretisiert einige komplette, funktionierende code. Die Optimierung der Polizei lassen Sie uns gehen Sie auf dieser ein, da die widget-Skript ist ein perfektes Beispiel für die komplette, Arbeits-Programm, das ist bereit für den Prozess.

Die Dritte Regel: nicht doch, und Profil den ersten. 

Diese Regel ist zu verstehen, Ihr Programm in Bezug auf die Laufzeit-performance. Profiling hilft Ihnen, zu wissen, anstatt zu erraten, welche Funktionen oder Bereiche der Skript nehmen sich die meisten Zeit oder am häufigsten verwendet werden, so dass Sie sich auf diejenigen, die in den Optimierungsprozess.   Es ist wichtig genug, um in führende Browser-Schiff mit eingebauten JavaScript-Profiler, oder haben Erweiterungen, die diese Dienstleistung erbringen.

Ich lief das widget unter dem profiler in Firebug, und unten ist ein screenshot der Ergebnisse. 


Schritt 4: Legen Sie Sich Einige Der Performance-Metriken 

 Als Sie lief das widget, ich bin sicher, Sie finden alle Sintel Sachen in Ordnung, und waren absolut hin und Weg von dem Punkt auf der rechten unteren Ecke der Leinwand, die man mit einer schönen Grafik und glänzend text.

 Es ist nicht nur ein hübsches Gesicht, dass die box liefert auch einige real-time-performance-Statistiken über das laufende Programm. Es ist eigentlich eine einfache, bare-bones-Javascript-profiler.  Das ist richtig! Yo, ich hörte Sie wie profiling, also habe ich ein profiler in Ihren Film, so dass Sie Profil es, während Sie beobachten. 

Die Grafik tracks die Render-Zeit, ermittelt durch die Messung, wie lange jeder ausführen von main() übernimmt in Millisekunden.  Da diese Funktion zeichnet jedes frame der animation, es ist effektiv der animation frame rate. Jede vertikale Blaue Linie im Diagramm zeigt die Zeit, die ein frame.   Die rote horizontale Linie ist die soll-Geschwindigkeit, die wir bei 33ms, passen Sie die video-Datei der frame-raten. Direkt unter der Grafik, die Geschwindigkeit von dem letzten Aufruf von main() ist in Millisekunden angegeben.

 Der profiler ist auch eine praktische browser-rendering-Geschwindigkeit testen. Im moment, die Durchschnittliche render-Zeit in Firefox ist 55 MS, 90 MS, im IE 9, 41ms in Chrom, 148ms in Oper und 63ms in Safari.  Alle Browser wurden unter Windows XP, außer für den IE 9, die profiliert wurde auf Windows Vista.

 Die nächste Metrische unten, die Leinwand FPS (Leinwand Bilder pro Sekunde), die durch das zählen, wie viele Male main() aufgerufen wird pro Sekunde. Der profiler zeigt die neuesten Leinwand-FPS-rate, wenn das video noch abgespielt wird, und wenn es endet, es zeigt die Durchschnittliche Geschwindigkeit aller Aufrufe von main().

 Die Letzte Metrik ist Browser-FPS, die misst, wie viele der browser aktualisiert das aktuelle Fenster in jeder Sekunde. Dieser ist nur verfügbar, wenn Sie das widget in Firefox, da kommt es auf ein feature derzeit nur in diesem browser-Fenster genannt.mozPaintCount., eine JavaScript-Eigenschaft, die Spur hält, wie viele Male das browser-Fenster neu gestrichen wurde, da die Webseite zum ersten mal geladen wird.

Die repaints in der Regel auftreten, wenn ein Ereignis oder eine Aktion, ändert sich das Aussehen einer Seite Auftritt, wie wenn Sie nach unten Blättern oder mit der Maus über einen link. Es ist effektiv die browser-Echtzeit-frame-rate, die bestimmt ist von, wie beschäftigt die aktuelle Webseite ist. 

Um welche Auswirkungen abschätzen die UN-optimierte Canvas-Animation auf MozPaintCount hatte, entfernte ich das Canvas-Tag und alle JavaScript, um die Browser-Frame-Rate zu verfolgen, wenn nur das Video abgespielt. Meine Tests erfolgten in Firebug Konsole, mit der folgenden Funktion:

1
	var lastPaintCount = window.mozPaintCount;
2
	setInterval( function(){
3
		console.log( window.mozPaintCount - lastPaintCount );
4
		lastPaintCount = window.mozPaintCount;
5
	}, 1000);

 Die Ergebnisse: Der browser frame-rate war zwischen 30 und 32 FPS, wenn das video abgespielt wurde, und fiel auf 0-1 FPS, wenn das video beendet. Dies bedeutet, dass Firefox war seine Einstellung Fenster repaint Frequenz, mit der die Wiedergabe von video, codiert mit 30fps.  Wenn der test wurde mit der un-optimiert canvas-animation und video-spielen zusammen, es verlangsamt 16fps, wie der browser wurde jetzt kämpfen, um ausführen alle JavaScript-und immer noch neu streichen der Fenster auf, so dass sowohl die video-Wiedergabe und canvas-Animationen träge.

 Wir werden jetzt beginnen, tweaking, unser Programm, und wie wir das tun, werden wir merken, in die Render-Zeit, Canvas FPS und Browser-FPS zu Messen, die Auswirkungen unserer änderungen.


Schritt 5: Verwenden Sie requestAnimationFrame() 

Die letzten zwei JavaScript-Schnipsel oben verwenden Sie die setTimeout() und setInterval () - timer-Funktionen. Um diese Funktionen zu verwenden, geben Sie einen Zeitintervall in Millisekunden und die callback-Funktion, die Sie wollen ausgeführt, wenn die Zeit verstreicht.   Der Unterschied zwischen den beiden ist, dass setTimeout() ruft die Funktion nur einmal, während setInterval() wird es wiederholt.

 Während diese Funktionen schon immer unverzichtbaren Werkzeugen in der JavaScript animator ' s kit, haben Sie ein paar Fehler:

Erste, der Zeitintervall ist nicht immer zuverlässig. Wenn das Programm immer noch in der Mitte der Ausführung etwas anderes, wenn das Intervall verstreicht, wird die callback-Funktion wird ausgeführt, später als ursprünglich festgelegt, sobald der browser wird nicht mehr beschäftigt.  In der main () - Funktion, setzen wir das Intervall auf 33 Millisekunden, aber als der profiler zeigt, ist die Funktion tatsächlich aufgerufen wird jedes 148 Millisekunden in der Oper. 

Zweitens, es gibt ein Problem mit dem browser aktualisiert. Hätten wir eine callback-Funktion generiert, dass die 20 frames einer animation pro Sekunde, während der browser neu gestrichen-Fenster wird nur 12 mal in der Sekunde, 8-Aufrufe zu dieser Funktion wird verschwendet werden, da der Anwender nie zu sehen bekommt, die Ergebnisse. 

Endlich, der browser hat keine Möglichkeit zu wissen, dass die Funktion aufgerufen wird, wird die Animation der Elemente im Dokument. Dies bedeutet, dass, wenn diese Elemente scrollen aus der Ansicht oder klickt der Benutzer auf einen anderen tab, wird der Rückruf wird immer noch wiederholt ausgeführt, Verschwendung von CPU-Zyklen. 

 Mit requestAnimationFrame() löst die meisten dieser Probleme, und es kann verwendet werden, anstelle der timer-Funktionen im HTML5-Animationen. Statt der Angabe einer Zeitspanne, requestAnimationFrame() synchronisiert die Funktion ruft mit dem browser-Fenster aktualisiert.  Dies führt zu mehr Flüssigkeit, konsistent animation, da keine frames verworfen werden, und die browser können weitere interne Optimierungen zu wissen, eine animation im Gange ist.

Ersetzen Sie setTimeout() mit requestAnimationFrame in unserem widget, die wir zuerst fügen Sie die folgende Zeile an der Spitze unseres Skripts: 

1
requestAnimationFrame = window.requestAnimationFrame || 
2
						window.mozRequestAnimationFrame || 
3
						window.webkitRequestAnimationFrame || 
4
						window.msRequestAnimationFrame || 
5
						setTimeout;

 Als Spezifikation ist noch Recht neu, manche Browser oder browser-Versionen haben Ihre eigenen experimentellen Implementierungen, diese Zeile stellt sicher, dass der name der Funktion Punkte für die richtige Methode, wenn es verfügbar ist, und fällt zurück auf setTimeout (), wenn nicht. Dann in der main () - Funktion, ändern wir diese Zeile: 

1
 
2
	setTimeout( main, frameDuration );

...:  

1
	requestAnimationFrame( main, canvas );

Der erste parameter nimmt die callback-Funktion, die in diesem Fall ist die main () - Funktion. Der zweite parameter ist optional und gibt das DOM-element mit der animation. Es soll verwendet werden, um zu berechnen, weitere Optimierungen. 

Beachten Sie, dass die getStats () - Funktion verwendet auch ein setTimeout(), aber das lassen wir, dass man im Ort auf, da diese spezielle Funktion nichts zu tun hat mit dem animieren der Szene. requestAnimationFrame() wurde speziell für Animationen, so dass, wenn Sie Ihre callback-Funktion, die nicht tun, animation, können Sie setTimeout() oder setInterval(). 


 Schritt 6: Benutzen Sie die Page-Visibility-API

Im letzten Schritt haben wir gemacht requestAnimationFrame macht den canvas animation, und jetzt haben wir ein neues problem. Wenn wir beginnen, von dem widget, dann minimieren Sie das browser-Fenster oder wechseln zu einem neuen tab, wird das widget-Fenster repaint-rate drosselt runter um Strom zu sparen.  Dadurch verlangsamt sich auch die canvas-animation da ist es jetzt synchronisiert mit dem repaint-rate - das wäre perfekt, wenn das video nicht spielen, auf der Ende. 

Wir brauchen eine Möglichkeit, zu erkennen, wenn die Seite nicht angezeigt wird, so dass wir anhalten der Wiedergabe von Videos; das ist, wo die Page-Visibility-API kommt zur Rettung. 

Die API enthält eine Reihe von Eigenschaften, Funktionen und Ereignisse, die wir verwenden können, um zu erkennen, ob eine Webseite in der Ansicht oder ausgeblendet werden.   Wir können dann code hinzufügen, passt sich unser Verhalten entsprechend. Wir verwenden diese API, um zu pausieren das widget die Wiedergabe von video, wenn die Seite inaktiv ist.

Wir beginnen, indem Sie eine neue Ereignis-listener, um unser Skript: 

1
 
2
	document.addEventListener( 'visibilitychange', onVisibilityChange, false);

Als Nächstes kommt die event-handler-Funktion: 

1
 
2
// Adjusts the program behavior, based on whether the webpage is active or hidden

3
function onVisibilityChange() {
4
	if( document.hidden && !video.paused ){  
5
		video.pause();  
6
	}else  if( video.paused ){  
7
		video.play();  
8
	}  
9
}

Schritt 7: Für Kundenspezifische Formen, Ziehen den Ganzen Weg Auf Einmal 

 Pfade werden verwendet, um zu erstellen, und zeichnen Sie eigene Formen und Umrisse auf dem - element, das zu allen Zeiten haben einen aktiven Pfad.

Ein Pfad enthält eine Liste von Nebenpfade und jedes Sub-Pfad setzt sich aus Leinwand koordinieren Punkte durch eine Linie oder einen Bogen miteinander verbunden. Der Weg machen und Zeichenfunktionen sind Eigenschaften von der Leinwand Kontextobjekt und können in zwei Gruppen eingeteilt werden. 

Es gibt die Unterpfad-making-Funktionen, verwendet um zu definieren, einen Unterpfad und gehören lineTo(), quadraticCurveTo(), bezierCurveTo () und arc().   Dann haben wir die stroke() und fill () der Pfad/Unterpfad Zeichnung Funktionen. Mit stroke() wird ein Umriss, während die fill () - erzeugt eine Form gefüllt, indem Sie entweder eine Farbe, Farbverlauf oder Muster. 

Beim zeichnen von Formen und umrissen auf die Leinwand, es ist effizienter erstellen Sie den gesamten Pfad zuerst, dann nur stroke() oder fill() ist es einmal, eher als die Definition und Zeichnung der einzelnen supbath zu einer Zeit. Unter der profiler-Graphen beschrieben, der in Schritt 4 als ein Beispiel, jede einzelne vertikale Blaue Linie ist ein Unterpfad, während Sie alle zusammen machen bis der ganze Strom Weg.   

Der stroke () - Methode wird derzeit aufgerufen, innerhalb einer Schleife, die definiert jeder Unterpfad:  

1
 
2
	mainContext.beginPath();				
3
	for( var j = 0; i < imax; i++, j += 2 ){				
4
		mainContext.moveTo( x + j, y ); // define the subpaths starting point

5
		mainContext.lineTo( x + j, y - speedLog[i] * graphScale );	// set the subpath as a line, and define its endpoint	

6
		mainContext.stroke(); // draw the subpath to the canvas

7
	}

 Dieser graph gezeichnet werden können, wesentlich effizienter zu gestalten, definieren Sie zunächst alle Unterpfade, dann ist nur die Erstellung der gesamten aktuellen Pfad auf einmal, wie unten gezeigt.

1
 
2
	mainContext.beginPath();				
3
	for( var j = 0; i < imax; i++, j += 2 ){				
4
		mainContext.moveTo( x + j, y ); // define the subpaths starting point

5
		mainContext.lineTo( x + j, y - speedLog[i] * graphScale );	// set the subpath as a line, and define its endpoint

6
	}	
7
	mainContext.stroke(); // draw the whole current path to the mainCanvas.

Schritt 8: Verwenden Sie eine Off-Screen-Leinwand Zum Erstellen der Szene 

 Diese Optimierung der Technik ist in Bezug auf die in der vorherigen Schritt, dass Sie beide basieren auf dem gleichen Prinzip der Minimierung der Webseite aktualisiert.

 Wann immer etwas passiert, dass änderungen eines Dokuments suchen oder Inhalte, die der browser hat, um einen Zeitplan repaint Betrieb bald nach, dass ein update der Benutzeroberfläche. Neu kann eine teure operation sein in Bezug auf die CPU-Zyklen und Kraft, vor allem für den dichten Seiten mit einer Menge von Elementen und animation geht.  Wenn Sie den Aufbau einer komplexen animation, Szene, indem viele Elemente ein zu einer Zeit, die , jede neue Ergänzung darf nur der Auslöser einer ganzen repaint.

 Es ist besser und viel schneller zu bauen die Szene auf einem Bildschirm angezeigt (in der Erinnerung) , und sobald Sie dies getan haben, malen Sie die ganze Szene nur einmal auf dem Bildschirm sichtbar .

 Einfach unten den code, erhält Referenz auf das widget - und seinem Kontext, wir werden das hinzufügen von fünf neuen Linien, erstellen Sie eine off-screen-Leinwand-DOM-Objekt und entsprechen seine Abmessungen mit dem original, sichtbar .

1
 
2
	var mainCanvas = document.getElementById("mainCanvas"); // points to the on-screen, original HTML canvas element

3
	var mainContext = mainCanvas.getContext('2d'); // the drawing context of the on-screen canvas element 

4
	var osCanvas = document.createElement("canvas"); // creates a new off-screen canvas element

5
	var osContext = osCanvas.getContext('2d'); //the drawing context of the off-screen canvas element

6
	osCanvas.width = mainCanvas.width; // match the off-screen canvas dimensions with that of #mainCanvas

7
	osCanvas.height = mainCanvas.height;

 Wir werden dann tun, wie suchen und ersetzen in allen Zeichenfunktionen für alle Verweise auf "mainCanvas" und ändern Sie Sie auf "osCanvas".  Verweise auf "mainContext" wird ersetzt mit "osContext". Alles wird nun erstellt, um die neue off-screen-Leinwand, anstelle von den original - .

 Schließlich, fügen wir eine weitere Zeile in main (), die Malt, was derzeit auf den off-screen - - in unserem original .

1
 
2
// As the scripts main function, it controls the pace of the animation

3
function main(){
4
	requestAnimationFrame( main, mainCanvas );
5
	if( video.paused || video.currentTime > 59  ){ return; }
6
	
7
	var now = new Date().getTime(); 
8
	if( frameStartTime ){ 
9
		speedLog.push( now - frameStartTime );
10
	}
11
	frameStartTime = now;
12
	if( video.readyState < 2 ){ return; }
13
	
14
	frameCount++;
15
	osCanvas.width = osCanvas.width; //clear the offscreen canvas

16
	drawBackground(); 
17
	drawFilm();
18
	drawDescription();
19
	drawStats();
20
	drawBlade();
21
	drawTitle();
22
	mainContext.drawImage( osCanvas, 0, 0 ); // copy the off-screen canvas graphics to the on-screen canvas

23
}

Schritt 9: Cache-Pfade, Die Als Bitmap-Bilder, Wenn Möglich 

 Für viele Arten von Grafiken, die Verwendung der Methode drawImage() wird viel schneller als konstruieren Sie das gleiche Bild auf Leinwand mithilfe von Pfaden. Wenn Sie feststellen, dass eine große potion von deinem script ausgegeben wird, zeichnen der wiederholt die gleichen Formen und Konturen immer und immer wieder, Sie können speichern die browser einige arbeiten durch die Zwischenspeicherung der resultierenden Grafik als bitmap-Bild, dann malen Sie nur einmal auf die Leinwand, wenn erforderlich, mit der Methode drawImage().

Es gibt zwei Möglichkeiten, dies zu tun. 

 Die erste ist durch die Schaffung einer externen Bild-Datei als JPG -, GIF-oder PNG-Bild, dann laden Sie es dynamisch mit JavaScript und kopieren es auf Ihre Leinwand. Der einzige Nachteil dieser Methode ist die zusätzliche Dateien, wird Ihr Programm zum herunterladen aus dem Netz, aber je nach Art der Grafik oder was Ihre Anwendung tut, könnte dies tatsächlich eine gute Lösung.  Die animation widget verwendet diese Methode zum laden der spinning blade Grafik -, was unmöglich gewesen wäre, neu zu erstellen mit nur den canvas-Pfad zeichnen-Funktionen.

 Die zweite Methode beinhaltet die Zeichnung nur die Grafik einmal, um eine off-screen-Leinwand, anstatt das laden eines externen Bilds. Wir verwenden diese Methode, um cache-der Titel der animation widget.  Zuerst erstellen wir eine variable als Verweis auf die neue off-screen-canvas-element erstellt werden. Der Standardwert ist false, so dass wir sagen können, ob oder nicht eine Bild-cache wurde erstellt und gespeichert, sobald das script gestartet wird:

1
 
2
	var titleCache = false; // points to an off-screen canvas used to cache the animation scene's title

 Wir Bearbeiten Sie dann die drawTitle () - Funktion zuerst überprüfen, ob das titleCache Leinwand Bild erstellt wurde. Wenn nicht, erstellt es ein Offscreen-image und speichert einen Verweis darauf in titleCache:

1
 
2
// renders the canvas title

3
function drawTitle(){
4
	if( titleCache == false ){ // create and save the title image

5
		titleCache = document.createElement('canvas');
6
		titleCache.width = osCanvas.width;
7
		titleCache.height = 25;
8
		
9
		var context = titleCache.getContext('2d');			
10
		context.fillStyle = 'black';
11
		context.fillRect( 0, 0, 368, 25 ); 
12
		context.fillStyle = 'white';
13
		context.font = "bold 21px Georgia";
14
		context.fillText( "SINTEL", 10, 20 );		
15
	}
16
17
	osContext.drawImage( titleCache, 0, 0 ); 
18
}

Schritt 10: Löschen Sie die Leinwand Mit clearRect() 

 Der erste Schritt in der Zeichnung eine neue animation frame ist, deaktivieren Sie die Leinwand von der aktuellen. Dies kann entweder geschehen, indem das zurücksetzen der Breite des canvas-element, oder verwenden Sie die clearRect () - Funktion.

 Zurücksetzen der Breite hat auch einen Nebeneffekt löschen des aktuellen canvas-Kontext zurück zu seinem default-Zustand ist, die Dinge verlangsamen. Mit clearRect() ist immer der schnellere und bessere Weg zum löschen der Leinwand.

 In der main () - Funktion, wir werden das ändern:

1
 
2
	osCanvas.width = osCanvas.width; //clear the off-screen canvas

 ...:

1
 
2
	osContext.clearRect( 0, 0, osCanvas.width, osCanvas.height ); //clear the offscreen canvas

Schritt 11: Umsetzen Schichten 

 Wenn Sie gearbeitet haben, mit Bild oder video-editing-software wie Gimp oder Photoshop vor, dann sind Sie bereits vertraut mit dem Konzept von Schichten, auf denen ein Bild zusammengesetzt ist, die durch stapeln viele Bilder übereinander, und jeder kann gewählt werden und separat bearbeitet.

 Angewendet auf eine Leinwand, animation Szene, jede Ebene eine separate canvas-element, platziert auf der Oberseite jeder anderen Verwendung von CSS, um die illusion von einem einzigen element. Als eine Optimierung der Technik, es funktioniert am besten, wenn es eine klare Unterscheidung zwischen Vordergrund-und hintergrund-Elemente einer Szene, mit der die meisten der Aktion stattfindet, in den Vordergrund. Der hintergrund kann dann gezeichnet werden auf einem canvas-element, ändert sich nicht viel zwischen den frames einer animation, und die Vordergrundfarbe auf eine weitere dynamische canvas-element oben. Auf diese Weise wird die gesamte Szene muss nicht neu gezeichnet werden wieder für jedes Animations-frame. 

 Leider ist die animation widget ist ein gutes Beispiel für eine Szene, wo können wir sinnvoll die Anwendung dieser Technik, da sowohl die Vordergrund-und hintergrund-Elemente sind sehr animiert.


Schritt 12: Aktualisierung Nur Die sich Ändernden Bereiche einer Animation Szene 

Dies ist eine weitere Optimierung der Technik, hängt stark von der animation Szene Komposition.  Es kann verwendet werden, wenn der Szene-animation ist konzentriert um einen bestimmten rechteckigen Bereich auf der Leinwand. Wir könnten dann löschen und neu zeichnen, nur neu gezeichnet, die region.  

Zum Beispiel, die Sintel-Titel bleibt unverändert, während die meisten der animation, so dass wir verlassen konnte, dass dieser Bereich intakt, wenn das clearing der Leinwand für den nächsten Animations-frame. 

Diese Technik implementieren, ersetzen wir die Zeile, fordert die Titel-Zeichnung Funktion in main() mit den folgenden block: 

1
 
2
	if( titleCache == false ){ // If titleCache is false, the animation's title hasn't been drawn yet

3
		drawTitle(); // we draw the title. This function will now be called just once, when the program starts

4
		osContext.rect( 0, 25, osCanvas.width, osCanvas.height ); // this creates a path covering the area outside by the title

5
		osContext.clip(); // we use the path to create a clipping region, that ignores the title's region

6
	}

 Schritt 13: Setzen Sie Das Sub-Pixel-Rendering

 Sub-pixel-rendering oder anti-aliasing erfolgt, wenn der browser automatisch für die Grafik-Effekte zum entfernen von gezackten Kanten. Es führt zu einer glatteren Suche Bilder und Animationen, und wird automatisch aktiviert, wenn Sie angeben, Bruch-Koordinaten, sondern als ganze Zahl, wenn die Zeichnung auf die Leinwand.

 Jetzt gibt es keinen standard, genau wie es getan werden sollte, so subpixel-rendering ist ein wenig inkonsistent zu allen Browsern in Bezug auf die gerenderte Ausgabe.  Es verlangsamt die rendering-Geschwindigkeit im browser zu tun einige Berechnungen zu generieren, die Wirkung. Als Leinwand anti-aliasing werden nicht direkt abgeschaltet, der einzige Weg, um zu bekommen es ist immer mit ganzen zahlen in der Zeichnung, koordiniert.

 Wir verwenden Math.floor (), um sicherzustellen, ganzen zahlen in unserem Skript immer anwendbar. Beispielsweise die folgende Zeile in drawFilm():

1
 
2
	punchX = sample.x + ( j * punchInterval ) + 5; // the x co-ordinate

...ist auch so geschrieben: 

1
 
2
	punchX = sample.x + ( j * punchInterval ) + 5; // the x co-ordinate

 Schritt 14: die Ergebnisse Messen

Wir habe schon ein paar canvas-animation-Optimierung Techniken, und es jetzt Zeit, um das Ergebnis zu überprüfen. 

Diese Tabelle zeigt die vor und nach der durchschnittlichen Render-Zeiten und Leinwand FPS.   Wir sehen einige signifikante Verbesserungen auf allen Browsern, obwohl es nur Chrome, die wirklich nahe kommt, um unsere ursprüngliche Ziel, eine maximale 33ms Renderzeit. Dies bedeutet, es ist noch viel Arbeit getan werden, um das gewählte Ziel.

Wir weiterfahren konnten durch die Anwendung allgemeiner JavaScript-Optimierung Techniken, und wenn das immer noch fehlschlägt, vielleicht betrachten toning down die animation, indem einige Glocken und Pfeifen. Aber wir werden nicht auf der Suche auf alle diese Techniken heute, da der Fokus lag hier auf Optimierungen für das  - animation.

Die Canvas-API ist noch sehr neu und wächst jeden Tag, so halten Sie Experimentieren, testen, erforschen und weitergeben. Vielen Dank für das Lesen der Anleitung. 

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Web Design tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.