mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-12 06:26:16 -08:00
refactor(ambilight): [PKG-AMBILIGHT-03] split typed lifecycle and recover native canvas sampling
This commit is contained in:
1 parent
43f0e9a8c6
commit
6caee44dbf
25 files changed
+1680
-306
No files matched your search
@@ -4,4 +4,4 @@
|
||||
* (c) 2017-2026 Harvey Zhao
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(t.artplayerPluginAmbilight=t(),define(function(){return t.artplayerPluginAmbilight})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginAmbilight=t()}(this,function(){"use strict";return function(e={}){return t=>{const{$video:n}=t.template,{createElement:r,addClass:i,setStyles:o}=t.constructor.utils,{blur:a="50px",opacity:l=.5,frequency:u=10,duration:f=.3}=e,s=r("div"),d=((c=s).innerHTML=Array.from({length:9}).fill("<div></div>").join(""),Array.from(c.children));var c,m,p,g;!function(e,t){i(e,"artplayer-plugin-ambilight"),t.parentNode.insertBefore(e,t),o(e,{position:"absolute",top:0,left:0,zIndex:9,inset:0,display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gridTemplateRows:"1fr 1fr 1fr"})}(s,n),m=a,p=l,g=f,d.forEach(e=>{o(e,{opacity:p,filter:`blur(${m})`,transition:`background-color ${g}s ease`})});const y=function(e,n,i){const o=r("canvas"),a=o.getContext("2d");o.width=3,o.height=3;let l=0;return function r(){const o=performance.now();if(o-l<1e3/i||!t.playing)return void(h=requestAnimationFrame(r));l=o;const u=e.videoWidth/3,f=e.videoHeight/3,s=[[0,0],[u,0],[2*u,0],[0,f],[u,f],[2*u,f],[0,2*f],[u,2*f],[2*u,2*f]].map(([t,n])=>function(t,n,r,i){a.drawImage(e,t,n,r,i,0,0,1,1);const[o,l,u]=a.getImageData(0,0,1,1).data;return`rgb(${o}, ${l}, ${u})`}(t,n,u,f));n.forEach((e,t)=>{e.style.backgroundColor=s[t]}),h=requestAnimationFrame(r)}}(n,d,u);let h=null;function b(){h||y()}function v(){h&&(cancelAnimationFrame(h),h=null)}return t.on("ready",b),t.on("destroy",v),{name:"artplayerPluginAmbilight",start:b,stop:v}}}});
|
||||
!function(t,n){"object"===typeof exports&&"undefined"!==typeof module?module.exports=n():"function"==typeof define&&define.amd?(t.artplayerPluginAmbilight=n(),define(function(){return t.artplayerPluginAmbilight})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginAmbilight=n()}(this,function(){"use strict";function t(t,n,e){let r="stopped",o=null,i=0,l=!1,u=0;function c(){const s=i,f=()=>"running"===r&&s===i;l=!0;try{const r=performance.now();if(r-u<1e3/t||!n()||!f())return;u=r,e(f)}finally{l=!1,"running"===r&&null===o&&function(){const t=i;try{o=requestAnimationFrame(()=>{"running"===r&&t===i&&(o=null,c())})}catch(n){throw r="stopped",i++,n}}()}}return{start:function(){"stopped"===r&&(r="running",i++,l||c())},stop:function(){if("destroyed"===r)return;r="stopped",i++;const t=o;o=null,null!==t&&cancelAnimationFrame(t)},destroy:function(){if("destroyed"===r)return;r="destroyed",i++;const t=o;o=null,null!==t&&cancelAnimationFrame(t)}}}return function(n={}){return e=>{let r=e,o=e.isDestroy,i=null,l=null,u=null;const c=[],s={name:"artplayerPluginAmbilight",start(){o||u?.start()},stop(){o||u?.stop()}};if(o)return r=null,s;function f(){const t=[u?.destroy,l?.destroy,i?.destroy];u=null,l=null,i=null;const n=[];for(const r of t)try{r?.()}catch(e){n.push(e)}if(n.length)throw n[0]}function a(){if(o)return;o=!0;const t=r;r=null;const n=[];for(const[r,o]of c.splice(0))try{t?.off(r,o)}catch(e){n.push(e)}try{f()}catch(e){n.push(e)}if(n.length)throw n[0]}function d(t,n){c.push([t,n]),r?.on(t,n)}try{if(d("destroy",a),o)return s;const{$video:c}=e.template,h=e.constructor.utils,{blur:y="50px",opacity:p=.5,frequency:g=10,duration:m=.3}=n;if(o)return s;if(i=function(t){const n=t.createElement("div");n.innerHTML=Array.from({length:9}).fill("<div></div>").join("");const e=Array.from(n.children);return{mount:function(r,o,i){if(i()&&(t.addClass(n,"artplayer-plugin-ambilight"),i()&&(r.parentNode.insertBefore(n,r),i()))){t.setStyles(n,{position:"absolute",top:0,left:0,zIndex:9,inset:0,display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gridTemplateRows:"1fr 1fr 1fr"});for(const n of e){if(!i())return;t.setStyles(n,{opacity:o.opacity,filter:`blur(${o.blur})`,transition:`background-color ${o.duration}s ease`})}}},render:function(t,n){for(let r=0;r<t.length;r++){if(!n())return;const o=e[r],i=t[r];o&&void 0!==i&&(o.style.backgroundColor=i)}},destroy:function(){try{n.parentNode?.removeChild(n)}finally{e.length=0}}}}(h),o||i.mount(c,{blur:y,opacity:p,duration:m},()=>!o),o)return f(),s;const b=h.createElement("canvas");if(o)return b.width=0,b.height=0,s;if(l=function(t,n,e){let r;try{r=t.getContext("2d"),t.width=3,t.height=3}catch(l){throw t.width=0,t.height=0,l}let o=!1,i=!1;return{read:function(l){if(o||!l())return null;const u=n.videoWidth,c=n.videoHeight;if(!Number.isFinite(u)||!Number.isFinite(c)||u<=0||c<=0)return null;const s=u/3,f=c/3,a=[];try{if(i){const n=e();if(o||!l())return n.width=0,n.height=0,null;if(r=null,r=(t=n).getContext("2d"),o||!l())return t.width=0,t.height=0,null;t.width=3,t.height=3,i=!1}if(!r)return null;for(let t=0;t<3;t++)for(let e=0;e<3;e++){if(o||!l())return null;if(r.drawImage(n,e*s,t*f,s,f,0,0,1,1),o||!l())return null;const[i,u,c]=r.getImageData(0,0,1,1).data;a.push(`rgb(${i}, ${u}, ${c})`)}return a}catch{return o||(i=!0,t.width=0,t.height=0),null}},destroy:function(){o||(o=!0,t.width=0,t.height=0)}}}(b,c,()=>h.createElement("canvas")),o)return f(),s;u=t(g,()=>Boolean(r?.playing),t=>{const n=l?.read(t);n&&t()&&i?.render(n,t)}),d("ready",s.start),o&&f()}catch(h){try{a()}catch{}try{f()}catch{}throw h}return s}}});
|
||||
@@ -4,4 +4,4 @@
|
||||
* (c) 2017-2026 Harvey Zhao
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(t.artplayerPluginAmbilight=t(),define(function(){return t.artplayerPluginAmbilight})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerPluginAmbilight=t()}(this,function(){"use strict";return function(e={}){return t=>{const{$video:n}=t.template,{createElement:r,addClass:i,setStyles:o}=t.constructor.utils,{blur:a="50px",opacity:l=.5,frequency:u=10,duration:f=.3}=e,s=r("div"),d=((c=s).innerHTML=Array.from({length:9}).fill("<div></div>").join(""),Array.from(c.children));var c,m,p,g;!function(e,t){i(e,"artplayer-plugin-ambilight"),t.parentNode.insertBefore(e,t),o(e,{position:"absolute",top:0,left:0,zIndex:9,inset:0,display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gridTemplateRows:"1fr 1fr 1fr"})}(s,n),m=a,p=l,g=f,d.forEach(e=>{o(e,{opacity:p,filter:`blur(${m})`,transition:`background-color ${g}s ease`})});const y=function(e,n,i){const o=r("canvas"),a=o.getContext("2d");o.width=3,o.height=3;let l=0;return function r(){const o=performance.now();if(o-l<1e3/i||!t.playing)return void(h=requestAnimationFrame(r));l=o;const u=e.videoWidth/3,f=e.videoHeight/3,s=[[0,0],[u,0],[2*u,0],[0,f],[u,f],[2*u,f],[0,2*f],[u,2*f],[2*u,2*f]].map(([t,n])=>function(t,n,r,i){a.drawImage(e,t,n,r,i,0,0,1,1);const[o,l,u]=a.getImageData(0,0,1,1).data;return`rgb(${o}, ${l}, ${u})`}(t,n,u,f));n.forEach((e,t)=>{e.style.backgroundColor=s[t]}),h=requestAnimationFrame(r)}}(n,d,u);let h=null;function b(){h||y()}function v(){h&&(cancelAnimationFrame(h),h=null)}return t.on("ready",b),t.on("destroy",v),{name:"artplayerPluginAmbilight",start:b,stop:v}}}});
|
||||
!function(t,n){"object"===typeof exports&&"undefined"!==typeof module?module.exports=n():"function"==typeof define&&define.amd?(t.artplayerPluginAmbilight=n(),define(function(){return t.artplayerPluginAmbilight})):(t="undefined"!==typeof globalThis?globalThis:t||self).artplayerPluginAmbilight=n()}(this,function(){"use strict";function t(t,n,e){let r="stopped",o=null,i=0,l=!1,u=0;function c(){const s=i,f=()=>"running"===r&&s===i;l=!0;try{const r=performance.now();if(r-u<1e3/t||!n()||!f())return;u=r,e(f)}finally{l=!1,"running"===r&&null===o&&function(){const t=i;try{o=requestAnimationFrame(()=>{"running"===r&&t===i&&(o=null,c())})}catch(n){throw r="stopped",i++,n}}()}}return{start:function(){"stopped"===r&&(r="running",i++,l||c())},stop:function(){if("destroyed"===r)return;r="stopped",i++;const t=o;o=null,null!==t&&cancelAnimationFrame(t)},destroy:function(){if("destroyed"===r)return;r="destroyed",i++;const t=o;o=null,null!==t&&cancelAnimationFrame(t)}}}return function(n={}){return e=>{let r=e,o=e.isDestroy,i=null,l=null,u=null;const c=[],s={name:"artplayerPluginAmbilight",start(){o||null==u||u.start()},stop(){o||null==u||u.stop()}};if(o)return r=null,s;function f(){const t=[null==u?void 0:u.destroy,null==l?void 0:l.destroy,null==i?void 0:i.destroy];u=null,l=null,i=null;const n=[];for(const r of t)try{null==r||r()}catch(e){n.push(e)}if(n.length)throw n[0]}function a(){if(o)return;o=!0;const t=r;r=null;const n=[];for(const[r,o]of c.splice(0))try{null==t||t.off(r,o)}catch(e){n.push(e)}try{f()}catch(e){n.push(e)}if(n.length)throw n[0]}function d(t,n){c.push([t,n]),null==r||r.on(t,n)}try{if(d("destroy",a),o)return s;const{$video:c}=e.template,h=e.constructor.utils,{blur:y="50px",opacity:p=.5,frequency:g=10,duration:m=.3}=n;if(o)return s;if(i=function(t){const n=t.createElement("div");n.innerHTML=Array.from({length:9}).fill("<div></div>").join("");const e=Array.from(n.children);return{mount:function(r,o,i){if(i()&&(t.addClass(n,"artplayer-plugin-ambilight"),i()&&(r.parentNode.insertBefore(n,r),i()))){t.setStyles(n,{position:"absolute",top:0,left:0,zIndex:9,inset:0,display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gridTemplateRows:"1fr 1fr 1fr"});for(const n of e){if(!i())return;t.setStyles(n,{opacity:o.opacity,filter:`blur(${o.blur})`,transition:`background-color ${o.duration}s ease`})}}},render:function(t,n){for(let r=0;r<t.length;r++){if(!n())return;const o=e[r],i=t[r];o&&void 0!==i&&(o.style.backgroundColor=i)}},destroy:function(){var t;try{null==(t=n.parentNode)||t.removeChild(n)}finally{e.length=0}}}}(h),o||i.mount(c,{blur:y,opacity:p,duration:m},()=>!o),o)return f(),s;const b=h.createElement("canvas");if(o)return b.width=0,b.height=0,s;if(l=function(t,n,e){let r;try{r=t.getContext("2d"),t.width=3,t.height=3}catch(l){throw t.width=0,t.height=0,l}let o=!1,i=!1;return{read:function(l){if(o||!l())return null;const u=n.videoWidth,c=n.videoHeight;if(!Number.isFinite(u)||!Number.isFinite(c)||u<=0||c<=0)return null;const s=u/3,f=c/3,a=[];try{if(i){const n=e();if(o||!l())return n.width=0,n.height=0,null;if(r=null,r=(t=n).getContext("2d"),o||!l())return t.width=0,t.height=0,null;t.width=3,t.height=3,i=!1}if(!r)return null;for(let t=0;t<3;t++)for(let e=0;e<3;e++){if(o||!l())return null;if(r.drawImage(n,e*s,t*f,s,f,0,0,1,1),o||!l())return null;const[i,u,c]=r.getImageData(0,0,1,1).data;a.push(`rgb(${i}, ${u}, ${c})`)}return a}catch(d){return o||(i=!0,t.width=0,t.height=0),null}},destroy:function(){o||(o=!0,t.width=0,t.height=0)}}}(b,c,()=>h.createElement("canvas")),o)return f(),s;u=t(g,()=>Boolean(null==r?void 0:r.playing),t=>{const n=null==l?void 0:l.read(t);n&&t()&&(null==i||i.render(n,t))}),d("ready",s.start),o&&f()}catch(h){try{a()}catch(y){}try{f()}catch(y){}throw h}return s}}});
|
||||
@@ -4,99 +4,299 @@
|
||||
* (c) 2017-2026 Harvey Zhao
|
||||
* Released under the MIT License.
|
||||
*/
|
||||
function createColorSampler(canvas, video, createCanvas) {
|
||||
let context;
|
||||
try {
|
||||
context = canvas.getContext("2d");
|
||||
canvas.width = 3;
|
||||
canvas.height = 3;
|
||||
} catch (error) {
|
||||
canvas.width = 0;
|
||||
canvas.height = 0;
|
||||
throw error;
|
||||
}
|
||||
let destroyed = false;
|
||||
let replaceCanvas = false;
|
||||
function read(active) {
|
||||
if (destroyed || !active())
|
||||
return null;
|
||||
const width = video.videoWidth;
|
||||
const height = video.videoHeight;
|
||||
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0)
|
||||
return null;
|
||||
const w = width / 3;
|
||||
const h = height / 3;
|
||||
const colors = [];
|
||||
try {
|
||||
if (replaceCanvas) {
|
||||
const replacement = createCanvas();
|
||||
if (destroyed || !active()) {
|
||||
replacement.width = 0;
|
||||
replacement.height = 0;
|
||||
return null;
|
||||
}
|
||||
canvas = replacement;
|
||||
context = null;
|
||||
context = canvas.getContext("2d");
|
||||
if (destroyed || !active()) {
|
||||
canvas.width = 0;
|
||||
canvas.height = 0;
|
||||
return null;
|
||||
}
|
||||
canvas.width = 3;
|
||||
canvas.height = 3;
|
||||
replaceCanvas = false;
|
||||
}
|
||||
if (!context)
|
||||
return null;
|
||||
for (let row = 0; row < 3; row++) {
|
||||
for (let column = 0; column < 3; column++) {
|
||||
if (destroyed || !active())
|
||||
return null;
|
||||
context.drawImage(video, column * w, row * h, w, h, 0, 0, 1, 1);
|
||||
if (destroyed || !active())
|
||||
return null;
|
||||
const [r, g, b] = context.getImageData(0, 0, 1, 1).data;
|
||||
colors.push(`rgb(${r}, ${g}, ${b})`);
|
||||
}
|
||||
}
|
||||
return colors;
|
||||
} catch {
|
||||
if (!destroyed) {
|
||||
replaceCanvas = true;
|
||||
canvas.width = 0;
|
||||
canvas.height = 0;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
function destroy() {
|
||||
if (destroyed)
|
||||
return;
|
||||
destroyed = true;
|
||||
canvas.width = 0;
|
||||
canvas.height = 0;
|
||||
}
|
||||
return { read, destroy };
|
||||
}
|
||||
function createFrameLoop(frequency, playing, update) {
|
||||
let state = "stopped";
|
||||
let pending = null;
|
||||
let generation = 0;
|
||||
let inFrame = false;
|
||||
let lastUpdateTime = 0;
|
||||
function schedule() {
|
||||
const current = generation;
|
||||
try {
|
||||
pending = requestAnimationFrame(() => {
|
||||
if (state !== "running" || current !== generation)
|
||||
return;
|
||||
pending = null;
|
||||
tick();
|
||||
});
|
||||
} catch (error) {
|
||||
state = "stopped";
|
||||
generation++;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
function tick() {
|
||||
const current = generation;
|
||||
const active = () => state === "running" && current === generation;
|
||||
inFrame = true;
|
||||
try {
|
||||
const now = performance.now();
|
||||
if (now - lastUpdateTime < 1e3 / frequency || !playing() || !active())
|
||||
return;
|
||||
lastUpdateTime = now;
|
||||
update(active);
|
||||
} finally {
|
||||
inFrame = false;
|
||||
if (state === "running" && pending === null)
|
||||
schedule();
|
||||
}
|
||||
}
|
||||
function start() {
|
||||
if (state !== "stopped")
|
||||
return;
|
||||
state = "running";
|
||||
generation++;
|
||||
if (!inFrame)
|
||||
tick();
|
||||
}
|
||||
function stop() {
|
||||
if (state === "destroyed")
|
||||
return;
|
||||
state = "stopped";
|
||||
generation++;
|
||||
const frame = pending;
|
||||
pending = null;
|
||||
if (frame !== null)
|
||||
cancelAnimationFrame(frame);
|
||||
}
|
||||
function destroy() {
|
||||
if (state === "destroyed")
|
||||
return;
|
||||
state = "destroyed";
|
||||
generation++;
|
||||
const frame = pending;
|
||||
pending = null;
|
||||
if (frame !== null)
|
||||
cancelAnimationFrame(frame);
|
||||
}
|
||||
return { start, stop, destroy };
|
||||
}
|
||||
function createAmbilightView(utils) {
|
||||
const element = utils.createElement("div");
|
||||
element.innerHTML = Array.from({ length: 9 }).fill("<div></div>").join("");
|
||||
const items = Array.from(element.children);
|
||||
function mount(video, option, active) {
|
||||
if (!active())
|
||||
return;
|
||||
utils.addClass(element, "artplayer-plugin-ambilight");
|
||||
if (!active())
|
||||
return;
|
||||
video.parentNode.insertBefore(element, video);
|
||||
if (!active())
|
||||
return;
|
||||
utils.setStyles(element, { position: "absolute", top: 0, left: 0, zIndex: 9, inset: 0, display: "grid", gridTemplateColumns: "1fr 1fr 1fr", gridTemplateRows: "1fr 1fr 1fr" });
|
||||
for (const item of items) {
|
||||
if (!active())
|
||||
return;
|
||||
utils.setStyles(item, { opacity: option.opacity, filter: `blur(${option.blur})`, transition: `background-color ${option.duration}s ease` });
|
||||
}
|
||||
}
|
||||
function render(colors, active) {
|
||||
for (let index = 0; index < colors.length; index++) {
|
||||
if (!active())
|
||||
return;
|
||||
const item = items[index];
|
||||
const color = colors[index];
|
||||
if (item && color !== void 0)
|
||||
item.style.backgroundColor = color;
|
||||
}
|
||||
}
|
||||
function destroy() {
|
||||
try {
|
||||
element.parentNode?.removeChild(element);
|
||||
} finally {
|
||||
items.length = 0;
|
||||
}
|
||||
}
|
||||
return { mount, render, destroy };
|
||||
}
|
||||
function artplayerPluginAmbilight(option = {}) {
|
||||
return (art) => {
|
||||
const { $video } = art.template;
|
||||
const { createElement, addClass, setStyles } = art.constructor.utils;
|
||||
const { blur = "50px", opacity = 0.5, frequency = 10, duration = 0.3 } = option;
|
||||
const $ambilight = createElement("div");
|
||||
const gridItems = createGridItems($ambilight);
|
||||
setupAmbilight($ambilight, $video);
|
||||
setupGridItems(gridItems, blur, opacity, duration);
|
||||
const updateColors = createColorUpdater($video, gridItems, frequency);
|
||||
let animationFrameId = null;
|
||||
function start() {
|
||||
if (!animationFrameId) {
|
||||
updateColors();
|
||||
}
|
||||
}
|
||||
function stop() {
|
||||
if (animationFrameId) {
|
||||
cancelAnimationFrame(animationFrameId);
|
||||
animationFrameId = null;
|
||||
}
|
||||
}
|
||||
art.on("ready", start);
|
||||
art.on("destroy", stop);
|
||||
return {
|
||||
let host = art;
|
||||
let closed = art.isDestroy;
|
||||
let view = null;
|
||||
let sampler = null;
|
||||
let loop = null;
|
||||
const subscriptions = [];
|
||||
const result = {
|
||||
name: "artplayerPluginAmbilight",
|
||||
start,
|
||||
stop
|
||||
};
|
||||
function createGridItems($ambilight2) {
|
||||
$ambilight2.innerHTML = Array.from({ length: 9 }).fill("<div></div>").join("");
|
||||
return Array.from($ambilight2.children);
|
||||
}
|
||||
function setupAmbilight($ambilight2, $video2) {
|
||||
addClass($ambilight2, "artplayer-plugin-ambilight");
|
||||
$video2.parentNode.insertBefore($ambilight2, $video2);
|
||||
setStyles($ambilight2, {
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
zIndex: 9,
|
||||
inset: 0,
|
||||
display: "grid",
|
||||
gridTemplateColumns: "1fr 1fr 1fr",
|
||||
gridTemplateRows: "1fr 1fr 1fr"
|
||||
});
|
||||
}
|
||||
function setupGridItems(gridItems2, blur2, opacity2, duration2) {
|
||||
gridItems2.forEach(($item) => {
|
||||
setStyles($item, {
|
||||
opacity: opacity2,
|
||||
filter: `blur(${blur2})`,
|
||||
transition: `background-color ${duration2}s ease`
|
||||
});
|
||||
});
|
||||
}
|
||||
function createColorUpdater($video2, gridItems2, frequency2) {
|
||||
const canvas = createElement("canvas");
|
||||
const ctx = canvas.getContext("2d");
|
||||
canvas.width = 3;
|
||||
canvas.height = 3;
|
||||
function getAverageColor(x, y, w, h) {
|
||||
ctx.drawImage($video2, x, y, w, h, 0, 0, 1, 1);
|
||||
const [r, g, b] = ctx.getImageData(0, 0, 1, 1).data;
|
||||
return `rgb(${r}, ${g}, ${b})`;
|
||||
start() {
|
||||
if (!closed)
|
||||
loop?.start();
|
||||
},
|
||||
stop() {
|
||||
if (!closed)
|
||||
loop?.stop();
|
||||
}
|
||||
let lastUpdateTime = 0;
|
||||
return function updateColors2() {
|
||||
const now = performance.now();
|
||||
if (now - lastUpdateTime < 1e3 / frequency2 || !art.playing) {
|
||||
animationFrameId = requestAnimationFrame(updateColors2);
|
||||
return;
|
||||
}
|
||||
lastUpdateTime = now;
|
||||
const w = $video2.videoWidth / 3;
|
||||
const h = $video2.videoHeight / 3;
|
||||
const colors = [
|
||||
[0, 0],
|
||||
[w, 0],
|
||||
[2 * w, 0],
|
||||
[0, h],
|
||||
[w, h],
|
||||
[2 * w, h],
|
||||
[0, 2 * h],
|
||||
[w, 2 * h],
|
||||
[2 * w, 2 * h]
|
||||
].map(([x, y]) => getAverageColor(x, y, w, h));
|
||||
gridItems2.forEach(($item, index) => {
|
||||
$item.style.backgroundColor = colors[index];
|
||||
});
|
||||
animationFrameId = requestAnimationFrame(updateColors2);
|
||||
};
|
||||
};
|
||||
if (closed) {
|
||||
host = null;
|
||||
return result;
|
||||
}
|
||||
function releaseResources() {
|
||||
const releases = [loop?.destroy, sampler?.destroy, view?.destroy];
|
||||
loop = null;
|
||||
sampler = null;
|
||||
view = null;
|
||||
const failures = [];
|
||||
for (const release of releases) {
|
||||
try {
|
||||
release?.();
|
||||
} catch (error) {
|
||||
failures.push(error);
|
||||
}
|
||||
}
|
||||
if (failures.length)
|
||||
throw failures[0];
|
||||
}
|
||||
function destroy() {
|
||||
if (closed)
|
||||
return;
|
||||
closed = true;
|
||||
const current = host;
|
||||
host = null;
|
||||
const failures = [];
|
||||
for (const [event, callback] of subscriptions.splice(0)) {
|
||||
try {
|
||||
current?.off(event, callback);
|
||||
} catch (error) {
|
||||
failures.push(error);
|
||||
}
|
||||
}
|
||||
try {
|
||||
releaseResources();
|
||||
} catch (error) {
|
||||
failures.push(error);
|
||||
}
|
||||
if (failures.length)
|
||||
throw failures[0];
|
||||
}
|
||||
function listen(event, callback) {
|
||||
subscriptions.push([event, callback]);
|
||||
host?.on(event, callback);
|
||||
}
|
||||
try {
|
||||
listen("destroy", destroy);
|
||||
if (closed)
|
||||
return result;
|
||||
const { $video } = art.template;
|
||||
const utils = art.constructor.utils;
|
||||
const { blur = "50px", opacity = 0.5, frequency = 10, duration = 0.3 } = option;
|
||||
if (closed)
|
||||
return result;
|
||||
view = createAmbilightView(utils);
|
||||
if (!closed)
|
||||
view.mount($video, { blur, opacity, duration }, () => !closed);
|
||||
if (closed) {
|
||||
releaseResources();
|
||||
return result;
|
||||
}
|
||||
const canvas = utils.createElement("canvas");
|
||||
if (closed) {
|
||||
canvas.width = 0;
|
||||
canvas.height = 0;
|
||||
return result;
|
||||
}
|
||||
sampler = createColorSampler(canvas, $video, () => utils.createElement("canvas"));
|
||||
if (closed) {
|
||||
releaseResources();
|
||||
return result;
|
||||
}
|
||||
loop = createFrameLoop(frequency, () => Boolean(host?.playing), (valid) => {
|
||||
const colors = sampler?.read(valid);
|
||||
if (colors && valid())
|
||||
view?.render(colors, valid);
|
||||
});
|
||||
listen("ready", result.start);
|
||||
if (closed)
|
||||
releaseResources();
|
||||
} catch (error) {
|
||||
try {
|
||||
destroy();
|
||||
} catch {
|
||||
}
|
||||
try {
|
||||
releaseResources();
|
||||
} catch {
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
}
|
||||
export {
|
||||
|
||||
Reference in new issue
Block a user