Created
July 15, 2017 12:06
-
-
Save Naereen/b4e71d8772ae14504b78ba28201d913d to your computer and use it in GitHub Desktop.
Add fireworks effects (from anime.js) to a reveal.js slideshow
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Source https://codepen.io/juliangarnier/pen/gmOwJX | |
// (C) Julian Garnier | |
// Adapted by Lilian Besson (Naereen) https://github.com/Naereen | |
// to add a fireworks effect on a reveal.js slideshows | |
var canvasEl = document.querySelector('.fireworks'); | |
var ctx = canvasEl.getContext('2d'); | |
var numberOfParticules = 40; | |
var pointerX = 0; | |
var pointerY = 0; | |
var tap = ('ontouchstart' in window || navigator.msMaxTouchPoints) ? 'touchstart' : 'mousedown'; | |
var colors = ['#FF1461', '#18FF92', '#5A87FF', '#FBF38C']; | |
function setCanvasSize() { | |
canvasEl.width = window.innerWidth * 2; | |
canvasEl.height = window.innerHeight * 2; | |
canvasEl.style.width = window.innerWidth + 'px'; | |
canvasEl.style.height = window.innerHeight + 'px'; | |
canvasEl.getContext('2d').scale(2, 2); | |
} | |
function updateCoords(e) { | |
pointerX = e.clientX || e.touches[0].clientX; | |
pointerY = e.clientY || e.touches[0].clientY; | |
} | |
function setParticuleDirection(p) { | |
var angle = anime.random(0, 360) * Math.PI / 180; | |
var value = anime.random(50, 180); | |
var radius = [-1, 1][anime.random(0, 1)] * value; | |
return { | |
x: p.x + radius * Math.cos(angle), | |
y: p.y + radius * Math.sin(angle) | |
} | |
} | |
function createParticule(x,y) { | |
var p = {}; | |
p.x = x; | |
p.y = y; | |
p.color = colors[anime.random(0, colors.length - 1)]; | |
p.radius = anime.random(16, 32); | |
p.endPos = setParticuleDirection(p); | |
p.draw = function() { | |
ctx.beginPath(); | |
ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true); | |
ctx.fillStyle = p.color; | |
ctx.fill(); | |
} | |
return p; | |
} | |
function createCircle(x,y) { | |
var p = {}; | |
p.x = x; | |
p.y = y; | |
p.color = '#FFF'; | |
p.radius = 0.1; | |
p.alpha = .5; | |
p.lineWidth = 6; | |
p.draw = function() { | |
ctx.globalAlpha = p.alpha; | |
ctx.beginPath(); | |
ctx.arc(p.x, p.y, p.radius, 0, 2 * Math.PI, true); | |
ctx.lineWidth = p.lineWidth; | |
ctx.strokeStyle = p.color; | |
ctx.stroke(); | |
ctx.globalAlpha = 1; | |
} | |
return p; | |
} | |
function renderParticule(anim) { | |
for (var i = 0; i < anim.animatables.length; i++) { | |
anim.animatables[i].target.draw(); | |
} | |
} | |
function animateParticules(x, y) { | |
var circle = createCircle(x, y); | |
var particules = []; | |
for (var i = 0; i < numberOfParticules; i++) { | |
particules.push(createParticule(x, y)); | |
} | |
anime.timeline().add({ | |
targets: particules, | |
x: function(p) { return p.endPos.x; }, | |
y: function(p) { return p.endPos.y; }, | |
radius: 0.1, | |
duration: anime.random(1200, 1800), | |
easing: 'easeOutExpo', | |
update: renderParticule | |
}) | |
.add({ | |
targets: circle, | |
radius: anime.random(120, 460), | |
lineWidth: 0, | |
alpha: { | |
value: 0, | |
easing: 'linear', | |
duration: anime.random(600, 800), | |
}, | |
duration: anime.random(1200, 1800), | |
easing: 'easeOutExpo', | |
update: renderParticule, | |
offset: 0 | |
}); | |
} | |
var render = anime({ | |
duration: Infinity, | |
update: function() { | |
ctx.clearRect(0, 0, canvasEl.width, canvasEl.height); | |
} | |
}); | |
var isEnabled = true; | |
// document.querySelector( '.reveal .slides' ).addEventListener(tap, function(e) { | |
document.addEventListener(tap, function(e) { | |
if (isEnabled && !Reveal.isOverview()) { | |
render.play(); | |
updateCoords(e); | |
animateParticules(pointerX, pointerY); | |
} | |
}, false); | |
// From https://stackoverflow.com/a/442474/ | |
function getOffset( el ) { | |
var _x = 0; | |
var _y = 0; | |
while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) { | |
_x += el.offsetLeft - el.scrollLeft; | |
_y += el.offsetTop - el.scrollTop; | |
el = el.offsetParent; | |
} | |
return { top: _y, left: _x }; | |
// return (_y, _x); | |
} | |
// Add the fireworks effect to all slide change | |
function handleReady() { | |
Reveal.addEventListener( 'slidechanged', function( event ) { | |
// event.previousSlide, event.currentSlide, event.indexh, event.indexv | |
if (!Reveal.isOverview()) { | |
render.play(); | |
var offsets = getOffset( document.querySelector( 'aside.controls' ) ); | |
// console.log("offsets = ", offsets); | |
animateParticules(offsets.left - 60, offsets.top - 20); | |
} | |
} ); | |
Reveal.addEventListener( 'overviewshown', function() { isEnabled = false; } ); | |
Reveal.addEventListener( 'overviewhidden', function() { isEnabled = true; } ); | |
} | |
if (Reveal.isReady()) { | |
handleReady(); | |
} else { | |
Reveal.addEventListener('ready', () => handleReady()); | |
} | |
var centerX = window.innerWidth / 2; | |
var centerY = window.innerHeight / 2; | |
setCanvasSize(); | |
window.addEventListener('resize', setCanvasSize, false); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"> | |
<meta name="author" content="Lilian Besson (@Naereen)"> | |
<title>fireworks.js for reveal.js demo</title> | |
<link type="text/css" rel="stylesheet" href="css/reveal.css"> | |
<link type="text/css" rel="stylesheet" href="css/theme/moon.css" id="theme"> | |
<!-- Theme used for syntax highlighting of code --> | |
<link type="text/css" rel="stylesheet" href="lib/css/zenburn.css"> | |
<!-- Printing and PDF exports --> | |
<script type="text/javascript"> | |
var link = document.createElement( "link" ); | |
link.rel = "stylesheet"; | |
link.type = "text/css"; | |
link.href = window.location.search.match( /print-pdf/gi ) ? "css/print/pdf.css" : "css/print/paper.css"; | |
document.getElementsByTagName( "head" )[0].appendChild( link ); | |
</script> | |
</head> | |
<body> | |
<div class="reveal"> | |
<div class="slides"> | |
<section> | |
<h1>reveal.js slideshow</h1> | |
With fireworks effect. | |
</section> | |
<section> | |
Each click event trigger a nice fireworks effect. | |
</section> | |
<section> | |
But what is really awesome is the fireworks triggered by every slide change!. | |
</section> | |
<canvas class="fireworks"></canvas> | |
</div> | |
</div> | |
<script type="text/javascript" src="lib/js/head.min.js"></script> | |
<script type="text/javascript" src="js/reveal.js"></script> | |
<script type="text/javascript"> | |
// More info about config & dependencies: | |
// - https://github.com/hakimel/reveal.js#configuration | |
// - https://github.com/hakimel/reveal.js#dependencies | |
Reveal.initialize({ | |
dependencies: [ | |
{ src: 'plugin/markdown/marked.js' }, | |
{ src: 'plugin/markdown/markdown.js' }, | |
{ src: 'plugin/highlight/highlight.js', async: true, callback: function() { hljs.initHighlightingOnLoad(); } }, | |
{ src: 'plugin/anime-js/anime.min.js' }, | |
{ src: 'plugin/anime-js/fireworks.js' }, | |
] | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Demo: