画中画
// ==UserScript==
// @name 画中画
// @name:en Pic-in-pic
// @namespace https://github.com/zaaack/tools/
// @description 在任意网站开启画中画模式,使视频漂浮在所有窗口最上层
// @description:en Enable picture-in-picture mode in any video site, make video float on top window
// @version 1.0
// @author zaaack
// @include *
// @grant unsafeWindow
// @run-at context-menu
// @homepageURL https://github.com/zaaack/tools/blob/master/tampermonkey/pic-in-pic/README.md
// @supportURL https://github.com/zaaack/tools/issues
// ==/UserScript==
;(() => {
// fork from https://github.com/GoogleChromeLabs/picture-in-picture-chrome-extension/blob/20288da7c56b525f2c21129df58d45b027d4f328/src/script.js#L2
//
//
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
function findLargestPlayingVideo() {
const videos = Array.from(document.querySelectorAll('video'))
.filter((video) => video.readyState != 0)
.filter((video) => video.disablePictureInPicture == false)
.sort((v1, v2) => {
const v1Rect = v1.getClientRects()[0] || { width: 0, height: 0 }
const v2Rect = v2.getClientRects()[0] || { width: 0, height: 0 }
return v2Rect.width * v2Rect.height - v1Rect.width * v1Rect.height
})
if (videos.length === 0) {
return
}
return videos[0]
}
async function requestPictureInPicture(video) {
await video.requestPictureInPicture()
video.setAttribute('__pip__', true)
video.addEventListener(
'leavepictureinpicture',
(event) => {
video.removeAttribute('__pip__')
},
{ once: true }
)
new ResizeObserver(maybeUpdatePictureInPictureVideo).observe(video)
}
function maybeUpdatePictureInPictureVideo(entries, observer) {
const observedVideo = entries[0].target
if (!document.querySelector('[__pip__]')) {
observer.unobserve(observedVideo)
return
}
const video = findLargestPlayingVideo()
if (video && !video.hasAttribute('__pip__')) {
observer.unobserve(observedVideo)
requestPictureInPicture(video)
}
}
;(async () => {
const video = findLargestPlayingVideo()
if (!video) {
return
}
if (video.hasAttribute('__pip__')) {
document.exitPictureInPicture()
return
}
await requestPictureInPicture(video)
// chrome.runtime.sendMessage({ message: 'enter' })
})()
})()