mirror of
https://github.com/zhw2590582/ArtPlayer.git
synced 2026-10-09 03:17:46 -08:00
190 lines
7.0 KiB
JavaScript
190 lines
7.0 KiB
JavaScript
var artplayerPluginDocumentPip = (function() {
|
|
"use strict";
|
|
const style = ".artplayer-document-pip.art-video-player {\n width: 100% !important;\n height: 100% !important;\n}\n";
|
|
function artplayerPluginDocumentPip2(userOptions = {}) {
|
|
const options = {
|
|
width: 480,
|
|
height: 270,
|
|
fallbackToVideoPiP: true,
|
|
placeholder: `Playing in Document Picture-in-Picture`,
|
|
...userOptions
|
|
};
|
|
return (art) => {
|
|
const isSupported = "documentPictureInPicture" in window && typeof window.documentPictureInPicture?.requestWindow === "function";
|
|
const { proxy, icons, i18n, template: { $player }, constructor: { utils: { append, tooltip, addClass, removeClass, sleep } } } = art;
|
|
const state = {
|
|
win: null,
|
|
originalParent: null,
|
|
originalNext: null,
|
|
currentDoc: null,
|
|
placeholder: null
|
|
};
|
|
function copyStylesTo(targetDoc) {
|
|
const base = targetDoc.createElement("style");
|
|
base.textContent = `
|
|
html, body { margin:0; padding:0; width:100%; height:100%; background:#000; overflow:hidden; }
|
|
#__art_dpip_root { position:absolute; inset:0; display:flex; }
|
|
#__art_dpip_root > * { width:100% !important; height:100% !important; }
|
|
`;
|
|
targetDoc.head.appendChild(base);
|
|
if (!targetDoc.querySelector('meta[name="viewport"]')) {
|
|
const meta = targetDoc.createElement("meta");
|
|
meta.name = "viewport";
|
|
meta.content = "width=device-width,initial-scale=1";
|
|
targetDoc.head.appendChild(meta);
|
|
}
|
|
try {
|
|
document.querySelectorAll('link[rel="stylesheet"]').forEach((link) => {
|
|
const clone = targetDoc.createElement("link");
|
|
clone.rel = "stylesheet";
|
|
clone.href = link.href;
|
|
if (link.media)
|
|
clone.media = link.media;
|
|
if (link.crossOrigin)
|
|
clone.crossOrigin = link.crossOrigin;
|
|
if (link.referrerPolicy)
|
|
clone.referrerPolicy = link.referrerPolicy;
|
|
targetDoc.head.appendChild(clone);
|
|
});
|
|
} catch {
|
|
}
|
|
try {
|
|
document.querySelectorAll("style").forEach((style2) => {
|
|
const clone = targetDoc.createElement("style");
|
|
clone.textContent = style2.textContent;
|
|
targetDoc.head.appendChild(clone);
|
|
});
|
|
} catch {
|
|
}
|
|
}
|
|
async function open() {
|
|
if (!isSupported && options.fallbackToVideoPiP) {
|
|
art.pip = true;
|
|
console.warn("[artplayer-plugin-document-pip] Document Picture-in-Picture is not supported, falling back to Video Picture-in-Picture");
|
|
return;
|
|
}
|
|
if (state.win)
|
|
return;
|
|
try {
|
|
const pipWin = await window.documentPictureInPicture.requestWindow({
|
|
width: options.width,
|
|
height: options.height
|
|
});
|
|
state.win = pipWin;
|
|
state.currentDoc = pipWin.document;
|
|
state.placeholder = document.createElement("div");
|
|
state.placeholder.className = "artplayer-document-pip-placeholder";
|
|
state.placeholder.style.cssText = `display:flex;justify-content:center;align-items:center;width:100%;height:100%;`;
|
|
state.placeholder.textContent = options.placeholder;
|
|
state.originalParent = $player.parentNode;
|
|
state.originalNext = $player.nextSibling;
|
|
state.originalParent.insertBefore(state.placeholder, state.originalNext);
|
|
const root = pipWin.document.createElement("div");
|
|
root.id = "__art_dpip_root";
|
|
pipWin.document.body.appendChild(root);
|
|
copyStylesTo(pipWin.document);
|
|
const adopted = pipWin.document.adoptNode($player);
|
|
root.appendChild(adopted);
|
|
state.currentDoc = pipWin.document;
|
|
const onResize = () => art.resize?.();
|
|
const onClose = () => close();
|
|
pipWin.addEventListener("resize", onResize);
|
|
pipWin.addEventListener("pagehide", onClose);
|
|
pipWin.addEventListener("unload", onClose);
|
|
state.cleanup = () => {
|
|
pipWin.removeEventListener("resize", onResize);
|
|
pipWin.removeEventListener("pagehide", onClose);
|
|
pipWin.removeEventListener("unload", onClose);
|
|
};
|
|
addClass($player, "artplayer-document-pip");
|
|
art.events.bindGlobalEvents?.();
|
|
art.emit("document-pip", true);
|
|
await sleep(100);
|
|
art.emit("resize");
|
|
} catch (err) {
|
|
art.notice.show = "Document Picture-in-Picture open failed";
|
|
console.warn("[artplayer-plugin-document-pip] open failed:", err);
|
|
}
|
|
}
|
|
function restoreToOriginalDocument() {
|
|
if (!state.placeholder)
|
|
return;
|
|
const backDoc = state.placeholder.ownerDocument || document;
|
|
const adoptedBack = backDoc.adoptNode($player);
|
|
state.originalParent.insertBefore(adoptedBack, state.placeholder);
|
|
state.placeholder.remove();
|
|
state.placeholder = null;
|
|
state.currentDoc = backDoc;
|
|
}
|
|
async function close() {
|
|
if (!state.win)
|
|
return;
|
|
try {
|
|
state.cleanup?.();
|
|
restoreToOriginalDocument();
|
|
state.win.close();
|
|
state.win = null;
|
|
removeClass($player, "artplayer-document-pip");
|
|
art.events.bindGlobalEvents?.();
|
|
art.emit("document-pip", false);
|
|
await sleep(100);
|
|
art.emit("resize");
|
|
} catch (err) {
|
|
art.notice.show = "Document Picture-in-Picture close failed";
|
|
console.warn("[artplayer-plugin-document-pip] close failed:", err);
|
|
}
|
|
}
|
|
function toggle() {
|
|
if (state.win) {
|
|
close();
|
|
} else {
|
|
open();
|
|
}
|
|
}
|
|
art.controls.add({
|
|
name: "document-pip",
|
|
position: "right",
|
|
index: 40,
|
|
tooltip: art.i18n.get("PIP Mode"),
|
|
mounted: ($control) => {
|
|
append($control, icons.pip);
|
|
proxy($control, "click", toggle);
|
|
art.on("document-pip", (value) => {
|
|
tooltip($control, i18n.get(value ? "Exit PIP Mode" : "PIP Mode"));
|
|
});
|
|
}
|
|
});
|
|
art.on("destroy", close);
|
|
return {
|
|
name: "artplayerPluginDocumentPip",
|
|
get isSupported() {
|
|
return isSupported;
|
|
},
|
|
get isActive() {
|
|
return !!state.win;
|
|
},
|
|
open,
|
|
close,
|
|
toggle
|
|
};
|
|
};
|
|
}
|
|
if (typeof document !== "undefined") {
|
|
const id = "artplayer-plugin-document-pip";
|
|
let $style = document.getElementById(id);
|
|
if (!$style) {
|
|
$style = document.createElement("style");
|
|
$style.id = id;
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
document.head.appendChild($style);
|
|
});
|
|
} else {
|
|
(document.head || document.documentElement).appendChild($style);
|
|
}
|
|
}
|
|
$style.textContent = style;
|
|
}
|
|
return artplayerPluginDocumentPip2;
|
|
})();
|