A perfectly looping image sequence player with fullscreen capabilities, built with mobile performance and keyboard accessibility in mind.
A perfectly looping image sequence player with fullscreen capabilities, built with mobile performance and keyboard accessibility in mind.
Demo: https://admiralpotato.github.io/vue-perfectlooper/
This project’s primary objective is to allow seamless playback of short, perfectly looping animations in the browser, at the highest possible visual quality, optionally in fullscreen mode. Providing frames at the full resolution of your intended output device with no visible compression artifacts is strongly recommended.
.vue
file flavor:npm install --save vue-perfectlooper
myLoop.vue
:
<template>
<vue-perfectlooper v-bind="loop"></vue-perfectlooper>
</template>
<script>
import VuePerfectlooper from 'vue-perfectlooper';
let amazonCDN = 'https://aws-website-videonuclearpixelcom-tgl8t.s3.amazonaws.com/content/';
export default {
components: {VuePerfectlooper},
data: function(){
return {
loop: {
"id": "crusaderarts_red_room_tribute-24",
"poster": amazonCDN + "crusaderarts_red_room_tribute-24-preview.jpg",
"src": amazonCDN + "crusaderarts_red_room_tribute-24-1920x1080/",
"frames": 24
}
}
}
};
</script>
In your HTML:
<div id="myLoopHolder">
<vue-perfectlooper v-bind="loop"></vue-perfectlooper>
</div>
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-perfectlooper"></script>
<script>
Vue.component('vue-perfectlooper', VuePerfectlooper);
var amazonCDN = 'https://aws-website-videonuclearpixelcom-tgl8t.s3.amazonaws.com/content/';
new Vue({
el: '#myLoopHolder',
data: {
loop: {
"id": "crusaderarts_red_room_tribute-24",
"poster": amazonCDN + "crusaderarts_red_room_tribute-24-preview.jpg",
"src": amazonCDN + "crusaderarts_red_room_tribute-24-1920x1080/",
"frames": 24
}
}
});
</script>
All configurations require the following parameters:
id
: this is the primary key by which the source images are cached in-memory to prevent unnecessary HTTP traffic in the case that the player is spawned and destroyed more than once in a session after initial load; also used as the analytics identifier in the scenario that the vue-analytics plugin has been installed.
poster
: a path to the preview image which is displayed before the user chooses to play the animation.
There are currently several different formats which may be used to provide frames to the player:
All properties specified here are required for this configuration.
{
"id": "electric_flower",
"poster": "https://cdn.example.com/loops/electric_flower-preview.jpg",
"src": "https://cdn.example.com/loops/electric_flower/",
"frames": 48
}
In this example, the required file structure is:
http://cdn.example.com/loops/electric_flower-preview.jpg
http://cdn.example.com/loops/electric_flower/(0001.jpg ~ 0048.jpg)
There are additional configuration parameters that can be specified for a structured file name sequence. Note the addition of the following properties: sequenceTemplate
, startIndex
, prefix
, suffix
{
"id": "infernal_recursion",
"poster": "https://cdn.example.com/loops/infernal_recursion.jpg",
"src": "https://cdn.example.com/loops/",
"frames": 24,
"startIndex": 0,
"sequenceTemplate": "00",
"prefix": "infernal_recursion-",
"suffix": ".png"
}
In this example, the required file structure is:
https://cdn.example.com/loops/infernal_recursion.jpg
https://cdn.example.com/loops/infernal_recursion-(00 ~ 23).png
In this example, there are no expectations of asset organization, as each frame path is completely specified explicitly; As a side effect of this, the number of frames does not need to be specified in this configuration.
{
"id": "ghost_wins_at_candy_corn-24",
"poster": "https://i.imgur.com/GraKGsu.jpg",
"src": [
"https://i.imgur.com/GraKGsu.jpg",
"https://i.imgur.com/Y1g1hiK.jpg",
"https://i.imgur.com/rHfKoSK.jpg",
"https://i.imgur.com/siZcgeZ.jpg",
"https://i.imgur.com/kTrrtwn.jpg",
"https://i.imgur.com/6Y045sP.jpg",
"https://i.imgur.com/9Vhetui.jpg",
"https://i.imgur.com/4a4rNI2.jpg",
"https://i.imgur.com/uyi5teq.jpg",
"https://i.imgur.com/4aWoBVB.jpg",
"https://i.imgur.com/M4ukBi5.jpg",
"https://i.imgur.com/14N83Cz.jpg",
"https://i.imgur.com/PseVZFY.jpg",
"https://i.imgur.com/SKx2Uws.jpg",
"https://i.imgur.com/x9qyGow.jpg",
"https://i.imgur.com/xFouIvs.jpg",
"https://i.imgur.com/SaguQJe.jpg",
"https://i.imgur.com/5ohSkY1.jpg",
"https://i.imgur.com/y60nEjV.jpg",
"https://i.imgur.com/INUdQD1.jpg",
"https://i.imgur.com/iof2JHQ.jpg",
"https://i.imgur.com/vRFn9tT.jpg",
"https://i.imgur.com/gqB3Vnz.jpg",
"https://i.imgur.com/11Wvp6T.jpg"
]
}
In this example, the only two required attributes are id
and srcImgurAlbumId
. The poster
attribute is not required, as the Imgur Album’s cover
image can be used. If the poster
attribute is passed, it will be displayed before the AJAX request for the album’s frame list returns.
It is recommended when hosting image sequences at Imgur, that you upload only PNG sequences; Imgur will both host the original PNGs, as well as automatically generate JPGs at multiple resolutions that may be used for quality presets in a future version of the player. By default, the player uses Imgur’s highest quality generated JPGs for playback, which are almost completely without visible compression artifacts. Uploading PNGs also comes with the benefit that you can configure the player to load and play the original PNG sequence, in the case that Imgur’s highest quality JPGs did not meet your quality requirements.
https://imgur-api-readonly.glitch.me/
and wait for a response before it will become interactive - so there may be a 0.25sec ~ 5sec delay before the cover
and frame paths load.{
"id": "hyper_mograph_networking-48",
"srcImgurAlbumId": "HMstF"
}
{
"id": "hyper_mograph_networking-48",
"poster": "https://i.imgur.com/o4Jj2u3.jpg",
"srcImgurAlbumId": "HMstF",
"suffix": ".png"
}
You may configure the player with these additional options:
fps
: Sets the framerate of image sequence playback. Default is 24.aspect
: Explicitly set the aspect ratio of the player, overriding and ignoring the aspect ratio of the poster image and animation images. This will also cause the player to display at the desired size even before the poster image has loaded. This value can be calculated as height / width
. Default value is automatically calculated as soon as the poster image is loaded, at which point the player will be displayed.