Skip to content

Instantly share code, notes, and snippets.

@Naereen
Created July 15, 2017 12:06
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Naereen/b4e71d8772ae14504b78ba28201d913d to your computer and use it in GitHub Desktop.
Save Naereen/b4e71d8772ae14504b78ba28201d913d to your computer and use it in GitHub Desktop.
Add fireworks effects (from anime.js) to a reveal.js slideshow
// 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);
<!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>
@Naereen
Copy link
Author

Naereen commented Jul 15, 2017

It requires a normal installation of reveal.js, as well as the file fireworks.js and anime.min.js (from @JulianGarnier anime project) to be located in plugin/anime-js/.

@Naereen
Copy link
Author

Naereen commented Jul 15, 2017

Demo: gifrecord_2017-07-15_140958

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment