UNPKG

just-animate

Version:
293 lines (284 loc) 7.78 kB
var isInitialized; var scrubberControl; var scrubberValue; var play; var pause; var reverse; var timeline; var pausedForScrubbing = false; const controlTemplate = `<div id="ja-controls"> <div id="ja-play"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M3 22v-20l18 10-18 10z"/> </svg> </div> <div id="ja-pause"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M11 22h-4v-20h4v20zm6-20h-4v20h4v-20z"/> </svg> </div> <div id="ja-reverse"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"> <path d="M6 13v4l-6-5 6-5v4h3v2h-3zm9-2v2h3v4l6-5-6-5v4h-3zm-4-6v14h2v-14h-2z"/> </svg> </div> <input id="ja-scrubber" type="range" min="0" step="1" max="1000" value="0" /> <input id="ja-seek" type="number" placeholder="0ms" /> <div> <button data-ja-rate value=".1">10%</button> <button data-ja-rate value=".5">50%</button> <button data-ja-rate value="1" class="active">100%</button> </div> </div>`; const colorFillLower = '#2a6495'; const colorFillUpper = '#7AC7C4'; const boxShadow1 = '1px 1px 1px #000000, 0px 0px 1px #0d0d0d'; const thumbHeight = '24px'; const thumbWidth = '4px'; const trackHeight = '4px'; const thumbColor = '#9ba6c0'; const border = '0.2px solid #010101'; const stylesTemplate = `<style style="display:none"> #ja-controls { position: fixed; bottom: 10px; right: 10px; background-color: rgba(0, 0, 0, .8); border: solid thin rgba(255, 255, 255, .4); border-radius: 5px; padding: 0; } #ja-controls > * { vertical-align: middle; display: inline-block; padding: 2px 5px; } #ja-controls button[data-ja-rate] { background: none; border: solid thin rgb(175, 173, 173); font-size: .8em; border-radius: 4px; cursor: pointer; } #ja-controls button[data-ja-rate]:hover { background-color: black; } #ja-controls button[data-ja-rate].active { background-color: #4f5d7d; } #ja-controls path { fill: currentColor; } #ja-play, #ja-pause, #ja-reverse { height: 1em; width: 1em; cursor: pointer; } #ja-seek { width: 50px; text-align: right; font-size: .8em; color: white; background-color: transparent; border: none; -moz-appearance: textfield; } #ja-seek::-webkit-inner-spin-button, #ja-seek::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; } #ja-controls * { font-family: Arial; font-size: 12pt; color: white; } #ja-controls > button[data-ja-rate] { font-size: .8em; } #ja-controls > input[type=range] { -webkit-appearance: none; padding: 0; height: 30px; background-color: transparent; } #ja-controls > input[type=range]:focus { outline: none; } #ja-controls > input[type=range]::-webkit-slider-runnable-track { width: 100%; height: ${trackHeight}; cursor: pointer; animate: 0.2s; box-shadow: ${boxShadow1}; background: ${colorFillUpper}; border-radius: 1.3px; border: ${border}; } #ja-controls > input[type=range]::-webkit-slider-thumb { box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; border: ${border}; height: ${thumbHeight}; width: ${thumbWidth}; border-radius: 3px; background: ${thumbColor}; cursor: pointer; -webkit-appearance: none; margin-top: -10px; } #ja-controls > input[type=range]:focus::-webkit-slider-runnable-track { background: ${colorFillUpper}; } #ja-controls > input[type=range]::-moz-range-track { width: 100%; height: ${trackHeight}; cursor: pointer; animate: 0.2s; box-shadow: ${boxShadow1}; background: ${colorFillUpper}; border-radius: 1.3px; border: ${border}; } #ja-controls > input[type=range]::-moz-range-thumb { box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d; border: ${border}; height: ${thumbHeight}; width: ${thumbWidth}; border-radius: 3px; background: ${thumbColor}; cursor: pointer; } #ja-controls > input[type=range]::-ms-track { width: 100%; height: ${trackHeight}; cursor: pointer; background: transparent; border-color: transparent; border-width: 16px 0; color: transparent; } #ja-controls > input[type=range]::-ms-fill-lower { background: ${colorFillLower}; border: ${border}; border-radius: 2.6px; box-shadow: ${boxShadow1}; } #ja-controls > input[type=range]::-ms-fill-upper { background: ${colorFillUpper}; border: ${border}; border-radius: 2.6px; box-shadow: ${boxShadow1}; } #ja-controls > input[type=range]::-ms-thumb { box-shadow: ${boxShadow1}; border: ${border}; height: ${thumbHeight}; width: ${thumbWidth}; margin-top: 1px; border-radius: 3px; background: #ffffff; cursor: pointer; } #ja-controls > input[type=range]:focus::-ms-fill-lower { background: ${colorFillUpper}; } #ja-controls > input[type=range]:focus::-ms-fill-upper { background: ${colorFillUpper}; } </style>`; function id(identifier) { return document.getElementById(identifier); } function on(element, event, listener) { element.addEventListener(event, listener); } function onValueChanged(value) { value = Math.floor(+value); scrubberValue.value = value + ''; scrubberControl.value = value + ''; } function init() { var $wrapper = document.createElement('div'); $wrapper.id = 'ja-controls'; $wrapper.innerHTML = stylesTemplate + controlTemplate; document.body.appendChild($wrapper); scrubberControl = id('ja-scrubber'); scrubberValue = id('ja-seek'); play = id('ja-play'); pause = id('ja-pause'); reverse = id('ja-reverse'); scrubberValue.value = '0'; const scrubberChanged = (evt) => { var value = +evt.currentTarget.value; timeline.currentTime = value; onValueChanged(value); }; on(scrubberControl, 'input', scrubberChanged); on(scrubberControl, 'change', scrubberChanged); on(scrubberValue, 'mousedown', () => { if (timeline) { timeline.pause(); } }); on(scrubberControl, 'mousedown', () => { if (timeline) { if (timeline.state === 3) { pausedForScrubbing = true; } timeline.pause(); } }); on(scrubberControl, 'mouseup', () => { if (timeline && pausedForScrubbing) { pausedForScrubbing = false; timeline.play(); } }); on(scrubberValue, 'input', (evt) => { var value = +evt.currentTarget.value; timeline.currentTime = value; onValueChanged(value); }); on(play, 'click', () => { if (timeline) { timeline.play(); } }); on(pause, 'click', () => { if (timeline) { timeline.pause(); } }); on(reverse, 'click', () => { if (timeline) { timeline.reverse(); } }); const rates = [].slice.call(document.querySelectorAll('#ja-controls [data-ja-rate]')); rates.forEach((rate) => { on(rate, 'click', () => { rates.forEach((rate2) => rate2.classList.remove('active')); rate.classList.add('active'); if (timeline) { const sign = timeline.playbackRate < 0 ? -1 : 1; timeline.playbackRate = +rate.value * sign; } }); }); } export function player(timeline2) { if (!isInitialized) { init(); isInitialized = true; } if (timeline) { timeline.off('update', onValueChanged); } scrubberControl.setAttribute('max', String(timeline2.duration)); scrubberControl.value = String(timeline2.currentTime); timeline2.on('update', onValueChanged); timeline2.on('config', () => { scrubberControl.setAttribute('max', String(timeline2.duration)); }); timeline = timeline2; }