refactor(canvas): [PKG-CANVAS-03] own media and frame lifecycle in strict TypeScript

This commit is contained in:
Harvey Zhao committed 2026-09-12 13:11:07 +08:00
1 parent e931520e66
commit 2b319109cd
29 files changed
+2015 -362

No files matched your search

+1 -1
View File
@@ -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.artplayerProxyCanvas=t(),define(function(){return t.artplayerProxyCanvas})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerProxyCanvas=t()}(this,function(){"use strict";return function(e){return t=>{const{constructor:n}=t,{createElement:i}=n.utils,o=i("canvas"),a=i("video"),r=o.getContext("2d");let c=null;const d={};for(const e in o)"function"===typeof o[e]&&(d[e]=o[e].bind(o));for(const e in a)e in o||Object.defineProperty(o,e,{get(){const t=a[e];return"function"===typeof t?t.bind(a):t},set(t){a[e]=t},configurable:!0,enumerable:!0});for(const e in d)o[e]=function(...t){return e in d?d[e](...t):a[e](...t)};return function(){const{events:e}=n.config;setTimeout(()=>{e.forEach(e=>{t.proxy(a,e,e=>{t.emit(`video:${e.type}`,e)})})})}(),t.on("video:loadedmetadata",()=>{o.width=a.videoWidth,o.height=a.videoHeight}),t.on("video:play",()=>{cancelAnimationFrame(c),f()}),t.on("video:pause",()=>{cancelAnimationFrame(c)}),t.on("resize",()=>{!function(){const e=t.template?.$player;if(!e||t.option.autoSize)return;const n=a.videoWidth/a.videoHeight,i=e.clientWidth,r=e.clientHeight;let c,d;i/r>n?(d=r,c=d*n):(c=i,d=c/n),o.width=c,o.height=d;const s=(i-c)/2,f=(r-d)/2;Object.assign(o.style,{padding:`${f}px ${s}px`})}(),s()}),t.on("destroy",()=>{cancelAnimationFrame(c)}),o;async function s(){try{if("undefined"!==typeof createImageBitmap){const e=await createImageBitmap(a);r.drawImage(e,0,0,o.width,o.height),e.close()}else r.drawImage(a,0,0,o.width,o.height);e&&e(r,a),t.emit("artplayerProxyCanvas:draw",r,a)}catch(n){t.emit("artplayerProxyCanvas:error",n)}}async function f(){await s(),c=requestAnimationFrame(f)}}}});
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerProxyCanvas=t(),define(function(){return e.artplayerProxyCanvas})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerProxyCanvas=t()}(this,function(){"use strict";function e(e){return Number.isFinite(e.videoWidth)&&Number.isFinite(e.videoHeight)&&e.videoWidth>0&&e.videoHeight>0}function t(e,t){let n=!1,i=!1,o=!1,r=!1,a=0,s=null;function l(){null!==s&&cancelAnimationFrame(s),s=null}function c(){if(!o&&!i&&t())if(r){r=!1,o=!0;const n=a,s=()=>{o=!1,c()};e(()=>!i&&t()&&a===n).then(s,s)}else n&&null===s&&(s=requestAnimationFrame(()=>{s=null,r=!0,c()}))}function u(){!i&&t()&&(a++,r=!0,l(),c())}function f(){n=!1,r=!1,a++,l()}return{request:u,start(){n||i||!t()||(n=!0,u())},stop:f,destroy(){i=!0,f()}}}return function(n){return i=>{const o=i.constructor,r=o.utils.createElement("canvas"),a=o.utils.createElement("video");let s=i,l=i.isDestroy,c=null;const u=[],f=()=>!l&&!s?.isDestroy,d=function(e,t,n){let i=!1;return{mount(){if(i||!n())return;const o=t();o&&(e.setAttribute("aria-hidden","true"),e.tabIndex=-1,e.playsInline=!0,Object.assign(e.style,{position:"absolute",width:"auto",height:"auto",opacity:"0",pointerEvents:"none",left:"0",top:"0"}),o.appendChild(e),i=!0,n()||e.remove())},destroy(){const t=[],n=()=>{e.srcObject=null};for(const i of[()=>e.pause(),()=>e.removeAttribute("src"),n,()=>e.load(),()=>e.remove()])try{i()}catch(o){t.push(o)}if(i=!1,t.length)throw t[0]}}}(a,()=>s?.template?.$player,f),p=function(t,n,i,o,r){const a=t.getContext("2d");let s=!1;return{available:()=>!!a||(s||(s=!0,r(new Error("Canvas 2D context is unavailable"))),!1),async draw(s){const l=()=>s()&&n.readyState>=2&&!n.seeking;if(!a||!l()||!e(n)||!t.width||!t.height)return;let c=!1;try{if("undefined"!==typeof createImageBitmap){c=!0;const e=await createImageBitmap(n);c=!1;try{l()&&a.drawImage(e,0,0,t.width,t.height)}finally{e.close()}}else a.drawImage(n,0,0,t.width,t.height);if(!l())return;i&&i(a,n),l()&&o(a,n)}catch(u){const e=c&&"object"===typeof u&&null!==u&&"name"in u&&"InvalidStateError"===u.name&&0===n.currentTime&&"function"===typeof n.getVideoPlaybackQuality&&0===n.getVideoPlaybackQuality().totalVideoFrames;l()&&!e&&r(u)}}}}(r,a,n,(e,t)=>s?.emit("artplayerProxyCanvas:draw",e,t),e=>s?.emit("artplayerProxyCanvas:error",e)),h=t(p.draw,f);if(function(e,t,n,i,o){const r=new Map;for(const a in e){const t=Reflect.get(e,a);"function"===typeof t&&r.set(a,(...n)=>Reflect.apply(t,e,n))}for(const a in t)a in e||Object.defineProperty(e,a,{get(){const e=Reflect.get(t,a);return"function"!==typeof e?e:(...r)=>n()?("load"===a&&i(),"play"===a&&o(),Reflect.apply(e,t,r)):"play"===a?Promise.resolve():void 0},set(e){n()&&("src"!==a&&"srcObject"!==a||i(),Reflect.set(t,a,e))},configurable:!0,enumerable:!0});for(const[a,s]of r)Reflect.set(e,a,s)}(r,a,f,h.stop,d.mount),l)return s=null,r;function y(){if(l)return;l=!0,h.destroy(),null!==c&&clearTimeout(c),c=null;const e=[];for(const n of[...u.splice(0).reverse(),d.destroy])try{n()}catch(t){e.push(t)}if(s=null,r.width=0,r.height=0,e.length)throw e[0]}function m(e,t){if(!f())return;const n=()=>{("destroy"===e||f())&&t()},o=()=>i.off(e,n);u.push(o),i.on(e,n),l&&o()}function v(){p.available()&&h.request()}try{m("destroy",y),m("video:loadedmetadata",()=>{e(a)&&(r.width=a.videoWidth,r.height=a.videoHeight)}),m("video:play",()=>{d.mount(),p.available()&&h.start()}),m("video:pause",h.stop),m("video:emptied",h.stop),m("video:seeked",v),m("resize",()=>{!function(t,n,i,o){if(!i||o||!e(n))return;const r=i.clientWidth,a=i.clientHeight;if(!Number.isFinite(r)||!Number.isFinite(a)||r<=0||a<=0)return;const s=n.videoWidth/n.videoHeight,l=r/a>s?a*s:r,c=r/a>s?a:r/s;t.width=l,t.height=c,t.style.padding=`${(a-c)/2}px ${(r-l)/2}px`}(r,a,s?.template?.$player,s?.option.autoSize),v()}),f()&&(c=setTimeout(()=>{if(c=null,f())try{d.mount();for(const e of o.config.events){if(!f())break;const t=e=>{f()&&s?.emit(`video:${e.type}`,e)},n=()=>a.removeEventListener(e,t);u.push(n);const o=i.proxy(a,e,t);f()?u.push(o):o()}}catch(e){try{y()}catch{}i.emit("artplayerProxyCanvas:error",e)}}))}catch(g){try{y()}catch{}throw g}return r}}});
@@ -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.artplayerProxyCanvas=t(),define(function(){return t.artplayerProxyCanvas})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerProxyCanvas=t()}(this,function(){"use strict";var e=(e,t,n)=>new Promise((i,o)=>{var r=e=>{try{c(n.next(e))}catch(t){o(t)}},a=e=>{try{c(n.throw(e))}catch(t){o(t)}},c=e=>e.done?i(e.value):Promise.resolve(e.value).then(r,a);c((n=n.apply(e,t)).next())});return function(t){return n=>{const{constructor:i}=n,{createElement:o}=i.utils,r=o("canvas"),a=o("video"),c=r.getContext("2d");let d=null;const l={};for(const e in r)"function"===typeof r[e]&&(l[e]=r[e].bind(r));for(const e in a)e in r||Object.defineProperty(r,e,{get(){const t=a[e];return"function"===typeof t?t.bind(a):t},set(t){a[e]=t},configurable:!0,enumerable:!0});for(const e in l)r[e]=function(...t){return e in l?l[e](...t):a[e](...t)};return function(){const{events:e}=i.config;setTimeout(()=>{e.forEach(e=>{n.proxy(a,e,e=>{n.emit(`video:${e.type}`,e)})})})}(),n.on("video:loadedmetadata",()=>{r.width=a.videoWidth,r.height=a.videoHeight}),n.on("video:play",()=>{cancelAnimationFrame(d),u()}),n.on("video:pause",()=>{cancelAnimationFrame(d)}),n.on("resize",()=>{!function(){var e;const t=null==(e=n.template)?void 0:e.$player;if(!t||n.option.autoSize)return;const i=a.videoWidth/a.videoHeight,o=t.clientWidth,c=t.clientHeight;let d,l;o/c>i?(l=c,d=l*i):(d=o,l=d/i),r.width=d,r.height=l;const s=(o-d)/2,u=(c-l)/2;Object.assign(r.style,{padding:`${u}px ${s}px`})}(),s()}),n.on("destroy",()=>{cancelAnimationFrame(d)}),r;function s(){return e(this,null,function*(){try{if("undefined"!==typeof createImageBitmap){const e=yield createImageBitmap(a);c.drawImage(e,0,0,r.width,r.height),e.close()}else c.drawImage(a,0,0,r.width,r.height);t&&t(c,a),n.emit("artplayerProxyCanvas:draw",c,a)}catch(e){n.emit("artplayerProxyCanvas:error",e)}})}function u(){return e(this,null,function*(){yield s(),d=requestAnimationFrame(u)})}}}});
!function(e,t){"object"===typeof exports&&"undefined"!==typeof module?module.exports=t():"function"==typeof define&&define.amd?(e.artplayerProxyCanvas=t(),define(function(){return e.artplayerProxyCanvas})):(e="undefined"!==typeof globalThis?globalThis:e||self).artplayerProxyCanvas=t()}(this,function(){"use strict";function e(e){return Number.isFinite(e.videoWidth)&&Number.isFinite(e.videoHeight)&&e.videoWidth>0&&e.videoHeight>0}function t(t,n,i,o,r){const l=t.getContext("2d");let a=!1;return{available:()=>!!l||(a||(a=!0,r(new Error("Canvas 2D context is unavailable"))),!1),draw(a){return s=this,u=null,c=function*(){const s=()=>a()&&n.readyState>=2&&!n.seeking;if(!l||!s()||!e(n)||!t.width||!t.height)return;let u=!1;try{if("undefined"!==typeof createImageBitmap){u=!0;const e=yield createImageBitmap(n);u=!1;try{s()&&l.drawImage(e,0,0,t.width,t.height)}finally{e.close()}}else l.drawImage(n,0,0,t.width,t.height);if(!s())return;i&&i(l,n),s()&&o(l,n)}catch(c){const e=u&&"object"===typeof c&&null!==c&&"name"in c&&"InvalidStateError"===c.name&&0===n.currentTime&&"function"===typeof n.getVideoPlaybackQuality&&0===n.getVideoPlaybackQuality().totalVideoFrames;s()&&!e&&r(c)}},new Promise((e,t)=>{var n=e=>{try{o(c.next(e))}catch(n){t(n)}},i=e=>{try{o(c.throw(e))}catch(n){t(n)}},o=t=>t.done?e(t.value):Promise.resolve(t.value).then(n,i);o((c=c.apply(s,u)).next())});var s,u,c}}}function n(e,t){let n=!1,i=!1,o=!1,r=!1,l=0,a=null;function s(){null!==a&&cancelAnimationFrame(a),a=null}function u(){if(!o&&!i&&t())if(r){r=!1,o=!0;const n=l,a=()=>{o=!1,u()};e(()=>!i&&t()&&l===n).then(a,a)}else n&&null===a&&(a=requestAnimationFrame(()=>{a=null,r=!0,u()}))}function c(){!i&&t()&&(l++,r=!0,s(),u())}function d(){n=!1,r=!1,l++,s()}return{request:c,start(){n||i||!t()||(n=!0,c())},stop:d,destroy(){i=!0,d()}}}return function(i){return o=>{const r=o.constructor,l=r.utils.createElement("canvas"),a=r.utils.createElement("video");let s=o,u=o.isDestroy,c=null;const d=[],f=()=>!u&&!(null==s?void 0:s.isDestroy),h=function(e,t,n){let i=!1;return{mount(){if(i||!n())return;const o=t();o&&(e.setAttribute("aria-hidden","true"),e.tabIndex=-1,e.playsInline=!0,Object.assign(e.style,{position:"absolute",width:"auto",height:"auto",opacity:"0",pointerEvents:"none",left:"0",top:"0"}),o.appendChild(e),i=!0,n()||e.remove())},destroy(){const t=[],n=()=>{e.srcObject=null};for(const i of[()=>e.pause(),()=>e.removeAttribute("src"),n,()=>e.load(),()=>e.remove()])try{i()}catch(o){t.push(o)}if(i=!1,t.length)throw t[0]}}}(a,()=>{var e;return null==(e=null==s?void 0:s.template)?void 0:e.$player},f),p=t(l,a,i,(e,t)=>null==s?void 0:s.emit("artplayerProxyCanvas:draw",e,t),e=>null==s?void 0:s.emit("artplayerProxyCanvas:error",e)),y=n(p.draw,f);if(function(e,t,n,i,o){const r=new Map;for(const l in e){const t=Reflect.get(e,l);"function"===typeof t&&r.set(l,(...n)=>Reflect.apply(t,e,n))}for(const l in t)l in e||Object.defineProperty(e,l,{get(){const e=Reflect.get(t,l);return"function"!==typeof e?e:(...r)=>n()?("load"===l&&i(),"play"===l&&o(),Reflect.apply(e,t,r)):"play"===l?Promise.resolve():void 0},set(e){n()&&("src"!==l&&"srcObject"!==l||i(),Reflect.set(t,l,e))},configurable:!0,enumerable:!0});for(const[l,a]of r)Reflect.set(e,l,a)}(l,a,f,y.stop,h.mount),u)return s=null,l;function v(){if(u)return;u=!0,y.destroy(),null!==c&&clearTimeout(c),c=null;const e=[];for(const n of[...d.splice(0).reverse(),h.destroy])try{n()}catch(t){e.push(t)}if(s=null,l.width=0,l.height=0,e.length)throw e[0]}function m(e,t){if(!f())return;const n=()=>{("destroy"===e||f())&&t()},i=()=>o.off(e,n);d.push(i),o.on(e,n),u&&i()}function g(){p.available()&&y.request()}try{m("destroy",v),m("video:loadedmetadata",()=>{e(a)&&(l.width=a.videoWidth,l.height=a.videoHeight)}),m("video:play",()=>{h.mount(),p.available()&&y.start()}),m("video:pause",y.stop),m("video:emptied",y.stop),m("video:seeked",g),m("resize",()=>{var t;!function(t,n,i,o){if(!i||o||!e(n))return;const r=i.clientWidth,l=i.clientHeight;if(!Number.isFinite(r)||!Number.isFinite(l)||r<=0||l<=0)return;const a=n.videoWidth/n.videoHeight,s=r/l>a?l*a:r,u=r/l>a?l:r/a;t.width=s,t.height=u,t.style.padding=`${(l-u)/2}px ${(r-s)/2}px`}(l,a,null==(t=null==s?void 0:s.template)?void 0:t.$player,null==s?void 0:s.option.autoSize),g()}),f()&&(c=setTimeout(()=>{if(c=null,f())try{h.mount();for(const e of r.config.events){if(!f())break;const t=e=>{f()&&(null==s||s.emit(`video:${e.type}`,e))},n=()=>a.removeEventListener(e,t);d.push(n);const i=o.proxy(a,e,t);f()?d.push(i):i()}}catch(e){try{v()}catch(t){}o.emit("artplayerProxyCanvas:error",e)}}))}catch(b){try{v()}catch(w){}throw b}return l}}});
+302 -99
View File
@@ -4,119 +4,322 @@
* (c) 2017-2026 Harvey Zhao
* Released under the MIT License.
*/
function artplayerProxyCanvas(callback) {
return (art) => {
const { constructor } = art;
const { createElement } = constructor.utils;
const canvas = createElement("canvas");
const video = createElement("video");
const ctx = canvas.getContext("2d");
let animationId = null;
const originalCanvasMethods = {};
for (const prop in canvas) {
if (typeof canvas[prop] === "function") {
originalCanvasMethods[prop] = canvas[prop].bind(canvas);
}
}
for (const prop in video) {
if (!(prop in canvas)) {
Object.defineProperty(canvas, prop, {
get() {
const value = video[prop];
return typeof value === "function" ? value.bind(video) : value;
},
set(value) {
video[prop] = value;
},
configurable: true,
enumerable: true
});
}
}
for (const prop in originalCanvasMethods) {
canvas[prop] = function(...args) {
if (prop in originalCanvasMethods) {
return originalCanvasMethods[prop](...args);
}
return video[prop](...args);
function forwardMedia(canvas, video, active, invalidate, mount) {
const methods = /* @__PURE__ */ new Map();
for (const name in canvas) {
const value = Reflect.get(canvas, name);
if (typeof value === "function")
methods.set(name, (...args) => Reflect.apply(value, canvas, args));
}
for (const name in video) {
if (name in canvas)
continue;
Object.defineProperty(canvas, name, {
get() {
const value = Reflect.get(video, name);
if (typeof value !== "function")
return value;
return (...args) => {
if (!active())
return name === "play" ? Promise.resolve() : void 0;
if (name === "load")
invalidate();
if (name === "play")
mount();
return Reflect.apply(value, video, args);
};
},
set(value) {
if (!active())
return;
if (name === "src" || name === "srcObject")
invalidate();
Reflect.set(video, name, value);
},
configurable: true,
enumerable: true
});
}
for (const [name, method] of methods)
Reflect.set(canvas, name, method);
}
function hasDimensions(video) {
return Number.isFinite(video.videoWidth) && Number.isFinite(video.videoHeight) && video.videoWidth > 0 && video.videoHeight > 0;
}
function resizeCanvas(canvas, video, player, autoSize) {
if (!player || autoSize || !hasDimensions(video))
return;
const width = player.clientWidth;
const height = player.clientHeight;
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0)
return;
const aspect = video.videoWidth / video.videoHeight;
const canvasWidth = width / height > aspect ? height * aspect : width;
const canvasHeight = width / height > aspect ? height : width / aspect;
canvas.width = canvasWidth;
canvas.height = canvasHeight;
canvas.style.padding = `${(height - canvasHeight) / 2}px ${(width - canvasWidth) / 2}px`;
}
function ownMedia(video, parent, active) {
let mounted = false;
return {
mount() {
if (mounted || !active())
return;
const target = parent();
if (!target)
return;
video.setAttribute("aria-hidden", "true");
video.tabIndex = -1;
video.playsInline = true;
Object.assign(video.style, { position: "absolute", width: "auto", height: "auto", opacity: "0", pointerEvents: "none", left: "0", top: "0" });
target.appendChild(video);
mounted = true;
if (!active())
video.remove();
},
destroy() {
const failures = [];
const clearObject = () => {
video.srcObject = null;
};
for (const release of [() => video.pause(), () => video.removeAttribute("src"), clearObject, () => video.load(), () => video.remove()]) {
try {
release();
} catch (error) {
failures.push(error);
}
}
mounted = false;
if (failures.length)
throw failures[0];
}
setupEventListeners();
setupArtPlayerEvents();
return canvas;
function setupEventListeners() {
const { events } = constructor.config;
setTimeout(() => {
events.forEach((event) => {
art.proxy(video, event, (event2) => {
art.emit(`video:${event2.type}`, event2);
});
});
});
}
async function draw() {
};
}
function createRenderer(canvas, video, callback, notify, error) {
const context = canvas.getContext("2d");
let reported = false;
return {
available() {
if (context)
return true;
if (!reported) {
reported = true;
error(new Error("Canvas 2D context is unavailable"));
}
return false;
},
async draw(valid) {
const usable = () => valid() && video.readyState >= 2 && !video.seeking;
if (!context || !usable() || !hasDimensions(video) || !canvas.width || !canvas.height)
return;
let acquiring = false;
try {
if (typeof createImageBitmap !== "undefined") {
acquiring = true;
const bitmap = await createImageBitmap(video);
ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
bitmap.close();
acquiring = false;
try {
if (usable())
context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
} finally {
bitmap.close();
}
} else {
ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
context.drawImage(video, 0, 0, canvas.width, canvas.height);
}
callback && callback(ctx, video);
art.emit("artplayerProxyCanvas:draw", ctx, video);
} catch (error) {
art.emit("artplayerProxyCanvas:error", error);
if (!usable())
return;
if (callback)
callback(context, video);
if (usable())
notify(context, video);
} catch (failure) {
const awaitingFirstFrame = acquiring && typeof failure === "object" && failure !== null && "name" in failure && failure.name === "InvalidStateError" && video.currentTime === 0 && typeof video.getVideoPlaybackQuality === "function" && video.getVideoPlaybackQuality().totalVideoFrames === 0;
if (usable() && !awaitingFirstFrame)
error(failure);
}
}
async function animation() {
await draw();
animationId = requestAnimationFrame(animation);
};
}
function createFrameScheduler(draw, active) {
let running = false;
let closed = false;
let busy = false;
let pending = false;
let generation = 0;
let frame = null;
function cancel() {
if (frame !== null)
cancelAnimationFrame(frame);
frame = null;
}
function drain() {
if (busy || closed || !active())
return;
if (pending) {
pending = false;
busy = true;
const version = generation;
const valid = () => !closed && active() && generation === version;
const complete = () => {
busy = false;
drain();
};
void draw(valid).then(complete, complete);
} else if (running && frame === null) {
frame = requestAnimationFrame(() => {
frame = null;
pending = true;
drain();
});
}
function resize() {
const player = art.template?.$player;
if (!player || art.option.autoSize)
}
function request() {
if (closed || !active())
return;
generation++;
pending = true;
cancel();
drain();
}
function stop() {
running = false;
pending = false;
generation++;
cancel();
}
return {
request,
start() {
if (running || closed || !active())
return;
const aspectRatio = video.videoWidth / video.videoHeight;
const containerWidth = player.clientWidth;
const containerHeight = player.clientHeight;
const containerRatio = containerWidth / containerHeight;
let canvasWidth, canvasHeight;
if (containerRatio > aspectRatio) {
canvasHeight = containerHeight;
canvasWidth = canvasHeight * aspectRatio;
} else {
canvasWidth = containerWidth;
canvasHeight = canvasWidth / aspectRatio;
running = true;
request();
},
stop,
destroy() {
closed = true;
stop();
}
};
}
function artplayerProxyCanvas(callback) {
return (art) => {
const constructor = art.constructor;
const canvas = constructor.utils.createElement("canvas");
const video = constructor.utils.createElement("video");
let host = art;
let closed = art.isDestroy;
let timer = null;
const releases = [];
const active = () => !closed && !host?.isDestroy;
const media = ownMedia(video, () => host?.template?.$player, active);
const renderer = createRenderer(canvas, video, callback, (context, source) => host?.emit("artplayerProxyCanvas:draw", context, source), (error) => host?.emit("artplayerProxyCanvas:error", error));
const scheduler = createFrameScheduler(renderer.draw, active);
forwardMedia(canvas, video, active, scheduler.stop, media.mount);
if (closed) {
host = null;
return canvas;
}
function destroy() {
if (closed)
return;
closed = true;
scheduler.destroy();
if (timer !== null)
clearTimeout(timer);
timer = null;
const failures = [];
for (const release of [...releases.splice(0).reverse(), media.destroy]) {
try {
release();
} catch (error) {
failures.push(error);
}
}
canvas.width = canvasWidth;
canvas.height = canvasHeight;
const paddingLeft = (containerWidth - canvasWidth) / 2;
const paddingTop = (containerHeight - canvasHeight) / 2;
Object.assign(canvas.style, {
padding: `${paddingTop}px ${paddingLeft}px`
});
host = null;
canvas.width = 0;
canvas.height = 0;
if (failures.length)
throw failures[0];
}
function setupArtPlayerEvents() {
art.on("video:loadedmetadata", () => {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
});
art.on("video:play", () => {
cancelAnimationFrame(animationId);
animation();
});
art.on("video:pause", () => {
cancelAnimationFrame(animationId);
});
art.on("resize", () => {
resize();
draw();
});
art.on("destroy", () => {
cancelAnimationFrame(animationId);
});
function listen(name, handler) {
if (!active())
return;
const listener = () => {
if (name === "destroy" || active())
handler();
};
const release = () => art.off(name, listener);
releases.push(release);
art.on(name, listener);
if (closed)
release();
}
function request() {
if (renderer.available())
scheduler.request();
}
try {
listen("destroy", destroy);
listen("video:loadedmetadata", () => {
if (hasDimensions(video)) {
canvas.width = video.videoWidth;
canvas.height = video.videoHeight;
}
});
listen("video:play", () => {
media.mount();
if (renderer.available())
scheduler.start();
});
listen("video:pause", scheduler.stop);
listen("video:emptied", scheduler.stop);
listen("video:seeked", request);
listen("resize", () => {
resizeCanvas(canvas, video, host?.template?.$player, host?.option.autoSize);
request();
});
if (active()) {
timer = setTimeout(() => {
timer = null;
if (!active())
return;
try {
media.mount();
for (const name of constructor.config.events) {
if (!active())
break;
const forward = (event) => {
if (active())
host?.emit(`video:${event.type}`, event);
};
const remove = () => video.removeEventListener(name, forward);
releases.push(remove);
const release = art.proxy(video, name, forward);
if (active())
releases.push(release);
else
release();
}
} catch (error) {
try {
destroy();
} catch {
}
art.emit("artplayerProxyCanvas:error", error);
}
});
}
} catch (error) {
try {
destroy();
} catch {
}
throw error;
}
return canvas;
};
}
export {