Particles are cool
Cogmind
<canvas id="canvas" width="800" height="600"></canvas>
id or class to access in JS
width/height: don't resize in CSS! use JS or inline style
<canvas id="canvas" width="300" height="150"></canvas>
<canvas id="canvas" style="height: 400px;width:150px;"></canvas>
<canvas id="canvas" width="300" height="150"></canvas>
var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d');
context.beginPath(); // x, y, radius, startAngle, endAngle, antiClockwise context.arc(150, 75, 20, 0, Math.PI*2, true); context.closePath(); // colour it in so we can see it context.fillStyle = '#ff3'; context.fill();
context.beginPath(); context.arc(150, 75, 20, 0, Math.PI*2, true); context.closePath(); context.fillStyle = '#ff3'; context.fill(); context.beginPath(); context.arc(10, 95, 10, 0, Math.PI*2, true); context.closePath(); context.fillStyle = '#f33'; context.fill(); context.beginPath(); context.arc(80, 120, 25, 0, Math.PI*2, true); context.closePath(); context.fillStyle = '#3f3'; context.fill(); context.beginPath(); context.arc(220, 35, 30, 0, Math.PI*2, true); context.closePath(); context.fillStyle = '#3ff'; context.fill();
function drawCircle(context, x, y, radius, colour) { context.beginPath(); context.arc(x, y, radius, 0, Math.PI*2, true); context.closePath(); context.fillStyle = colour; context.fill(); } var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); drawCircle(context, 150, 75, 20, '#ff3'); drawCircle(context, 10, 95, 10, '#f33'); drawCircle(context, 80, 20, 25, '#3f3'); drawCircle(context, 220, 35, 30, '#3ff');
Tell the particle to make itself
function Particle() { this.x = randomHorzPosition(); this.y = randomVertPosition(); this.radius = randomSize(); this.colour = randomColour(); } function drawCircle(ctx, particle) { ctx.beginPath(); ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI*2, true); ctx.closePath(); ctx.fillStyle = particle.colour; ctx.fill(); } for(var i = 0; i < 10; i++) { drawCircle(new Particle()); }
The fun stuff
Lots of drawing
60fps = call drawCircle() 60 times per second
var particles = []; for(var i = 0; i < 10; i++) { particles.push(new Particle()); } setInterval(function() { for(var i = 0; i < particles.length; i++) { drawCircle(particles[i]); } }, 16); // 1000ms / 60fps = ~16ms
// named function containing rAF (function animation() { // call rAF and pass in your animation loop requestAnimationFrame(animation); // do all your drawing for(var i = 0; i < particles.length; i++) { drawCircle(particles[i]); } })(); // IIFE
(function animation() { requestAnimationFrame(animation); for(var i = 0; i < particles.length; i++) { var particle = particles[i]; // update each particle particle.x += randomHorzMovement(); particle.y += randomVertMovement(); // draw drawCircle(particle); } })();
(function animation() { requestAnimationFrame(animation); // clear screen context.clearRect(0, 0, context.canvas.width, context.canvas.height); for(var i = 0; i < particles.length; i++) { var particle = particles[i]; // update each particle particle.x += randomHorzMovement(); particle.y += randomVertMovement(); // draw drawCircle(particle); } })();
function Particle() { this.x = randomHorzPosition(); this.y = randomVertPosition(); this.velocityX = randomHorzMovememnt(); this.velocityY = randomVertMovement(); this.radius = randomSize(); this.colour = randomColour(); }Could also use velocity and angle - depends on use case
Particles should come from the same point
var x = context.canvas.width / 2; var y = context.canvas.width / 2; (function animation() { requestAnimationFrame(animation); // clear screen context.clearRect(0, 0, context.canvas.width, context.canvas.height); for(var i = 0; i < particles.length; i++) { var particle = particles[i]; // update each particle particle.x += particle.velocityX; particle.y += particle.velocityY; // draw drawCircle(particle); } })();
Let's use letters
// Find the character code of lowercase a 'a'.charCodeAt(0) // -> 97 // ... and uppercase 'A'.charCodeAt(0) // -> 65
Uppercase letters start at 65, lowercase letters start at 97, punctuation starts at 33
String.fromCharCode(33) // -> "!" String.fromCharCode(65) // -> "A"
function randomNumberInRange(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } function pickALetterAnyLetter() { // interesting characters in the range 33 - 126 return String.fromCharCode(randomNumberInRange(33, 126)); } function Particle() { ... this.letter = pickALetterAnyLetter(); }
function drawParticle(context, particle) { context.fillStyle = particle.colour; context.font = 'bold 14px arial'; context.fillText(particle.letter, particle.x, particle.y); }
function changeParticleLetter(particle) { particle.letter = pickALetterAnyLetter(); } (function animloop(){ requestAnimFrame(animloop); context.clearRect(0, 0, context.canvas.width, context.canvas.height); for(var i = 0; i < particles.length; i++) { // change the letter changeParticleLeter(particles[i]); updateParticlePosition(particles[i]); drawParticle(context, particles[i]); } })();
Letters change every frame - not what we want
Animation tied to framerate can lead to unexpected results
eg move character 600px per second. At 60fps, need to move 10px per frame.
On slower machine, running at 30fps - now character only moves 300px per second
FPS locked at 30fps
Modders changed to 60fps
Cars moved twice as fast as the player
As enemies killed, fewer entities to draw = frames rendered faster = enemies faster
Liked the effect so kept it (but unplayable on modern hardware!)
Check how much time has elapsed since the last frame
Use the difference (delta) between last frame and current time as basis for movement
// store the current time var time; function Particle() { ... // last time particle changed letter var changeLetterDelta = 0; // how long should we wait for the letter to change? var changeLetterThreshold = 250; // 250ms } (function animloop() { requestAnimFrame(animloop); // get current time var now = new Date().getTime(); // difference between last frame (time) and current time (now) var delta = now - (time || now); // since we're now rendering a frame, save the current time as the time of the last frame time = now; context.clearRect(0, 0, context.canvas.width, context.canvas.height); for(var i = 0; i < particles.length; i++) { var particle = particles[i]; // particles keep track of the last time they changed letter particle.changeLetterDelta += delta; // add the current time to the last time particle changed letter // if it's past a certain point (changeLetterThreshold) then change if(particle.changeLetterDelta >= particle.changeLetterThreshold) { changeParticleLeter(particle); particle.changeLetterDelta = 0; } updateParticlePosition(particle); drawParticle(context, particle); } })();
Slides can be nested inside of other slides, try pressing down.
Press down or up to navigate.
Cornify
That's it, time to go back up.
Not a coder? No problem. There's a fully-featured visual editor for authoring these, try it out at http://slid.es.
Press ESC to enter the slide overview.
Hold down alt and click on any element to zoom in on it using zoom.js. Alt + click anywhere to zoom back out.
Try it out! You can swipe through the slides and pinch your way to the overview.
For those of you who like that sort of thing. Instructions and a bit more info available here.
<section data-markdown> ## Markdown support For those of you who like that sort of thing. Instructions and a bit more info available [here](https://github.com/hakimel/reveal.js#markdown). </section>
You can select from different transitions, like: Cube - Page - Concave - Zoom - Linear - Fade - None - Default
Reveal.js comes with a few themes built in: Default - Sky - Beige - Simple - Serif - Night Moon - Solarized
* Theme demos are loaded after the presentation which leads to flicker. In production you should load your theme in the <head> using a <link>.
Set data-state="something" on a slide and "something" will be added as a class to the document element when the slide is open. This lets you apply broader style changes, like switching the background.
Additionally custom events can be triggered on a per slide basis by binding to the data-state name.
Reveal.addEventListener( 'customevent', function() { console.log( '"customevent" has fired' ); } );
Set data-background="#007777" on a slide to change the full page background to the given color. All CSS color formats are supported.
<section data-background="image.png">
<section data-background="image.png" data-background-repeat="repeat" data-background-size="100px">
Pass reveal.js the backgroundTransition: 'slide' config argument to make backgrounds slide rather than fade.
You can override background transitions per slide by using data-background-transition="slide".
These guys come in two forms, inline: “The nice thing about standards is that there are so many to choose from” and block:
“For years there has been a theory that millions of monkeys typing at random on millions of typewriters would reproduce the entire works of Shakespeare. The Internet has proven this theory to be untrue.”function linkify( selector ) { if( supports3DTransforms ) { var nodes = document.querySelectorAll( selector ); for( var i = 0, len = nodes.length; i < len; i++ ) { var node = nodes[i]; if( !node.className ) { node.className += ' roll'; } } } }
Courtesy of highlight.js.
You can link between slides internally, like this.
Hit the next arrow...
... to step through ...
any type of view fragments This slide has fragments which are also stepped through in the notes window.There's a few styles of fragments, like:
grow
shrink
roll-in
fade-out
highlight-red
highlight-green
highlight-blue
current-visible
highlight-current-blue
Presentations can be exported to PDF, below is an example that's been uploaded to SlideShare.
Press b or period on your keyboard to enter the 'paused' mode. This mode is helpful when you want to take distracting slides off the screen during a presentation.