Create beautiful, seekable, mobile-friendly-auto-playable HTML videos (faked with sprite animations and canvas).
npm install flicker
npm install flicker
(create video) --> video
(photoshop export) --> image sequence(s)
(flicker package) --> packed sprites & JSON frame coord map
(flicker.min.js) --> canvas animation goodness
npm install flicker, you should notice the following folders in the package directory:
.
+-- sequences/ (where to put your image sequences)
+-- flicker/ (where the sequences are exported to packaged sprites and frame coord map)
sequences/ folder.
.
+-- sequences/
| +-- sequence1/
| | +-- image1.jpg
| | +-- image2.jpg
| +-- sequence2/
| | +-- image1.jpg
| | +-- image2.jpg
+-- flicker/
npm start from the package directory - this process can take a little while, depending on the amount of images
flicker/:
.
+-- sequences/
| +-- sequence1/
| | +-- image1.jpg
| | +-- image2.jpg
| +-- sequence2/
| | +-- image1.jpg
| | +-- image2.jpg
+-- flicker/
| +-- sequence1_sprite.jpg/
| +-- sequence2_sprite.jpg/
| +-- flicker_map.json/
width and height attributes have been set according to the native size of each
.controls range slider which acts as a seek control
Flicker.seek() function.
<div id="flicker1" class="flicker">
<canvas class="canvas" width="560" height="420"></canvas>
<div class="controls">
<input type="range" min="0" max="1" value="0" step="1" oninput="this.setAttribute('value', this.value);"/>
</div>
<div class="sprites" style="display: none;">
<img class="sprite" src="flicker/sequence001_sprite.jpg" alt=" "/>
<img class="sprite" src="flicker/sequence002_sprite.jpg" alt=" "/>
</div>
</div>
<script type="text/javascript" src="js/flicker.min.js"></script>
var map = // copy flicker_map.json into a variable here, like { frames: [SUPER LONG ARRAY] };
// register the Flicker object
var myFlicker = new Flicker({
animation: map, // specify the frame coordinate map
rootPath: 'flicker/', // specify the root path for the sprites (defaults to flicker/)
container: document.getElementById('flicker1') // specify the context for the flicker
});
// flicker provides a utility called waitOnImages which waits for the source sprites to load
// this is necessary when using high res images, as playing the animation before the images
// have loaded results in the canvas drawing a blank image
myFlicker.utils.waitOnImages(function () {
console.log('done loading');
/*
BACKGROUND LOOP EXAMPLE
play from current frame (defaults to frame 0 (the beginning)),
then register an event handler on flickerEnd to play the flicker
from the beginning whenever the flicker finishes
*/
this.play();
this.on('flickerEnd', function(direction){
console.log('flicker ended whilst playing %s', direction);
this.play(0); // play from the beginning
});
/*
ILLUSTRATIVE EXAMPLE
play from current frame, wait for 2 seconds, pause, wait for 3 seconds,
reverse from current frame, wait for one second, play from frame 0 (the beginning)
*/
// this.play().wait(2).pause().wait(3).reverse().wait(1).play(0);
});
// naturally, event handlers can also be registered outside the
// waitOnImages function, directly on the flicker object
// the sequenceChange event is emitted whenever the flicker transitions
// from one sequence to another
myFlicker.on('sequenceChange', function(seq){
console.log('transitioned to sprite sequence: %s', seq);
/*
STOP PLAYTHROUGH EXAMPLE
pauses between each sequence, requiring manual replaying
to continue the flicker (perhaps triggered by a scroll event?)
*/
// this.pause();
});