Last active
December 31, 2021 17:14
-
-
Save moritzebeling/c8f1d2ed03553c0f542116bdc933c27e to your computer and use it in GitHub Desktop.
Vimeo Svelte Player
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
export function renderTime(sec) { | |
let min = Math.floor(sec / 60); | |
sec = Math.floor(sec - min * 60); | |
sec = "00" + sec; | |
return `${min}:${sec.slice(-2)}`; | |
} | |
export function renderPercent(fl) { | |
return Math.round(fl * 100); | |
} | |
export function errorHandler(err) { | |
console.error(err); | |
} |
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
<script context="module"> | |
const allPlayers = new Set(); | |
</script> | |
<script> | |
import Player from "@vimeo/player"; | |
import Progress from "./Progress.svelte"; | |
import { onDestroy } from "svelte"; | |
import { renderTime, renderPercent, errorHandler } from "./helpers.js"; | |
/* parameters */ | |
export let id; | |
export let controls = false; | |
export let audio = false; | |
export let progress = false; | |
export let options = {}; | |
/* vimeo options https://www.npmjs.com/package/@vimeo/player#embed-options */ | |
const vimeoOptions = { | |
id: id, | |
width: 640, | |
background: true, | |
muted: true, | |
autoplay: true, | |
...options | |
}; | |
/* status */ | |
let player; | |
let message = "Loading..."; | |
let isLoaded = false; | |
let isMuted = options.muted || true; | |
let isPlaying = options.autoplay || true; | |
let videoTime = 0; | |
let videoProgress = 0; | |
let videoDuration = 0; | |
/* mount & destroy */ | |
function init(element) { | |
player = new Player(element, vimeoOptions); | |
/* events https://www.npmjs.com/package/@vimeo/player#events */ | |
player.on("loaded", () => { | |
isLoaded = true; | |
}); | |
player.on("playing", () => { | |
isPlaying = true; | |
}); | |
player.on("pause", () => { | |
isPlaying = false; | |
}); | |
if (progress) { | |
player.on("timeupdate", data => { | |
videoProgress = data.percent; | |
videoTime = data.seconds; | |
videoDuration = data.duration; | |
}); | |
} | |
player.on("volumechange", ({volume}) => { | |
player.getMuted().then(function(muted) { | |
isMuted = muted; | |
}).catch(errorHandler); | |
console.log('volumechange', isMuted); | |
}); | |
allPlayers.add(player); | |
} | |
onDestroy(() => { | |
player.pause(); | |
let empty = function() {}; | |
player.off("loaded", empty); | |
player.off("playing", empty); | |
player.off("pause", empty); | |
player.off("timeupdate", empty); | |
allPlayers.delete(player); | |
player.destroy(); | |
player = undefined; | |
}); | |
/* controls https://www.npmjs.com/package/@vimeo/player#methods */ | |
function mute(){ | |
player.setMuted(true); | |
} | |
function unMute(){ | |
allPlayers.forEach(pl => { | |
if (pl !== player) pl.setMuted(true); | |
}); | |
player.setMuted(false); | |
} | |
function play() { | |
player | |
.play() | |
.then(function() { | |
console.log("Play"); | |
}) | |
.catch(function(error) { | |
switch (error.name) { | |
case "PasswordError": | |
console.warn("Video is password protected"); | |
break; | |
case "PrivacyError": | |
console.warn("Video is private"); | |
break; | |
default: | |
errorHandler(error); | |
break; | |
} | |
}); | |
} | |
function pause() { | |
player.pause(); | |
} | |
function seek(event) { | |
let percent = event.detail; | |
let seekto = percent * videoDuration; | |
player | |
.setCurrentTime(seekto) | |
.then(function(seconds) { | |
videoTime = seconds; | |
videoProgress = percent; | |
}) | |
.catch(function(error) { | |
switch (error.name) { | |
case "RangeError": | |
console.error("Seek value was out of bounds"); | |
break; | |
default: | |
errorHandler(error); | |
break; | |
} | |
}); | |
} | |
</script> | |
<div use:init></div> | |
{#if isLoaded} | |
{#if controls} | |
<div> | |
{#if isPlaying} | |
<button on:click={pause}>Pause</button> | |
{:else} | |
<button on:click={play}>Play</button> | |
{/if} | |
</div> | |
{/if} | |
{#if audio} | |
<div> | |
{#if isMuted} | |
<button on:click={unMute}>Unmute</button> | |
{:else} | |
<button on:click={mute}>Mute</button> | |
{/if} | |
</div> | |
{/if} | |
{#if progress} | |
<div> | |
{renderTime(videoTime)} / {renderTime(videoDuration)} ({renderPercent(videoProgress)}%) | |
</div> | |
<div> | |
<Progress {videoProgress} on:seek={seek} /> | |
</div> | |
{/if} | |
{:else} | |
<div>{message}</div> | |
{/if} |
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
<script> | |
import { createEventDispatcher } from "svelte"; | |
export let videoProgress; | |
const dispatch = createEventDispatcher(); | |
let barWidth; | |
function seek(event) { | |
let seekto = event.offsetX / barWidth; | |
console.log(seekto); | |
dispatch("seek", seekto); | |
} | |
</script> | |
<div class="bar" on:click={seek} bind:offsetWidth={barWidth}> | |
<div class="progress" style="width:{videoProgress*100}%;"></div> | |
</div> | |
<style> | |
.bar { | |
background-color: #eee; | |
cursor: pointer; | |
} | |
.progress { | |
height: 1rem; | |
background-color: #000; | |
transition: width 200ms ease; | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
NPM Vimeo
https://www.npmjs.com/package/@vimeo/player
Codesandbox Example
https://codesandbox.io/s/gracious-parm-l92qs?file=/Player.svelte
Usage
Aim