/*! * artplayer-proxy-canvas.js v1.1.0 * Github: https://github.com/zhw2590582/ArtPlayer * (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); }; } 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() { try { if (typeof createImageBitmap !== "undefined") { const bitmap = await createImageBitmap(video); ctx.drawImage(bitmap, 0, 0, canvas.width, canvas.height); bitmap.close(); } else { ctx.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); } } async function animation() { await draw(); animationId = requestAnimationFrame(animation); } function resize() { const player = art.template?.$player; if (!player || art.option.autoSize) 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; } 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` }); } 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); }); } }; } export { artplayerProxyCanvas as default };