在 動畫瘋 加入 截圖 的功能
// ==UserScript==
// @name 動畫瘋 - 截圖工具
// @namespace hbl917070
// @version 0.3
// @description 在 動畫瘋 加入 截圖 的功能
// @author hbl917070(深海異音)
// @match https://ani.gamer.com.tw/animeVideo.php?sn=*
// @grant none
// ==/UserScript==
/**
* 最後修改日期:
* 2020/05/09
*
* 說明:
* 在 動畫瘋 加入 截圖 的功能
*
* 作者小屋:
* https://home.gamer.com.tw/homeindex.php?owner=hbl917070
*
*/
/**
*
* 版本說明
*
* 2020/05/09:修復BUG
* 2019/09/08:修復某些圖片附檔名錯誤的BUG
*
*/
(function () {
//要插入的html
var s_html = `
<div class="ct_div">
<style>
/*最外層的框*/
.ct_div {
background-color: #FFF;
padding: 5px;
padding-left: 11px;
}
/*「截圖」按鈕*/
.but_ct {
margin-top: 10px;
padding: 3px 10px;
border: 1px solid #00B4D8;
color: #00B4D8;
display: inline-block;
text-align: center;
line-height: 27px;
font-size: 1.3em;
margin-right: 10px;
}
.but_ct:hover {
background-color: #00B4D8;
border: 1px solid #00B4D8;
color: #FFF;
display: inline-block;
}
/*放每一個截圖的區域*/
#ct_output {
max-height: 500px;
overflow: auto;
margin-top: 10px;
}
/*每一個截圖項目*/
.ct_item {
margin-bottom: 10px;
margin-right: 10px;
border: 1px solid #d9d9d9;
float: left;
padding: 5px;
white-space: nowrap;
}
.ct_img {
max-width: 195px;
max-height: 150px;
}
/*影片時間*/
.ct_time {
float: left;
margin-top: 5px;
font-size: 18px;
}
/*下載圖片*/
.ct_download {
float: right;
display: block;
width: 20px;
height: 20px;
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE2LjAuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPCFET0NUWVBFIHN2ZyBQVUJMSUMgIi0vL1czQy8vRFREIFNWRyAxLjEvL0VOIiAiaHR0cDovL3d3dy53My5vcmcvR3JhcGhpY3MvU1ZHLzEuMS9EVEQvc3ZnMTEuZHRkIj4NCjxzdmcgdmVyc2lvbj0iMS4xIiBpZD0iQ2FwYV8xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4PSIwcHgiIHk9IjBweCINCgkgd2lkdGg9IjQzMy41cHgiIGhlaWdodD0iNDMzLjVweCIgdmlld0JveD0iMCAwIDQzMy41IDQzMy41IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA0MzMuNSA0MzMuNTsiIHhtbDpzcGFjZT0icHJlc2VydmUiDQoJPg0KPGc+DQoJPGcgaWQ9ImZpbGUtZG93bmxvYWQiPg0KCQk8cGF0aCBkPSJNMzk1LjI1LDE1M2gtMTAyVjBoLTE1M3YxNTNoLTEwMmwxNzguNSwxNzguNUwzOTUuMjUsMTUzeiBNMzguMjUsMzgyLjV2NTFoMzU3di01MUgzOC4yNXoiLz4NCgk8L2c+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8L3N2Zz4NCg==);
background-size: 90% 90%;
background-position: center center;
background-repeat: no-repeat;
opacity: 0.2;
margin-top: 3px;
}
.ct_download:hover {
opacity: 1;
}
/*刪除圖片*/
.ct_delete {
float: right;
display: block;
width: 20px;
height: 20px;
background-image: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjQyN3B0IiB2aWV3Qm94PSItNDAgMCA0MjcgNDI3LjAwMTMxIiB3aWR0aD0iNDI3cHQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTIzMi4zOTg0MzggMTU0LjcwMzEyNWMtNS41MjM0MzggMC0xMCA0LjQ3NjU2My0xMCAxMHYxODljMCA1LjUxOTUzMSA0LjQ3NjU2MiAxMCAxMCAxMCA1LjUyMzQzNyAwIDEwLTQuNDgwNDY5IDEwLTEwdi0xODljMC01LjUyMzQzNy00LjQ3NjU2My0xMC0xMC0xMHptMCAwIi8+PHBhdGggZD0ibTExNC4zOTg0MzggMTU0LjcwMzEyNWMtNS41MjM0MzggMC0xMCA0LjQ3NjU2My0xMCAxMHYxODljMCA1LjUxOTUzMSA0LjQ3NjU2MiAxMCAxMCAxMCA1LjUyMzQzNyAwIDEwLTQuNDgwNDY5IDEwLTEwdi0xODljMC01LjUyMzQzNy00LjQ3NjU2My0xMC0xMC0xMHptMCAwIi8+PHBhdGggZD0ibTI4LjM5ODQzOCAxMjcuMTIxMDk0djI0Ni4zNzg5MDZjMCAxNC41NjI1IDUuMzM5ODQzIDI4LjIzODI4MSAxNC42Njc5NjggMzguMDUwNzgxIDkuMjg1MTU2IDkuODM5ODQ0IDIyLjIwNzAzMiAxNS40MjU3ODEgMzUuNzMwNDY5IDE1LjQ0OTIxOWgxODkuMjAzMTI1YzEzLjUyNzM0NC0uMDIzNDM4IDI2LjQ0OTIxOS01LjYwOTM3NSAzNS43MzA0NjktMTUuNDQ5MjE5IDkuMzI4MTI1LTkuODEyNSAxNC42Njc5NjktMjMuNDg4MjgxIDE0LjY2Nzk2OS0zOC4wNTA3ODF2LTI0Ni4zNzg5MDZjMTguNTQyOTY4LTQuOTIxODc1IDMwLjU1ODU5My0yMi44MzU5MzggMjguMDc4MTI0LTQxLjg2MzI4Mi0yLjQ4NDM3NC0xOS4wMjM0MzctMTguNjkxNDA2LTMzLjI1MzkwNi0zNy44Nzg5MDYtMzMuMjU3ODEyaC01MS4xOTkyMTh2LTEyLjVjLjA1ODU5My0xMC41MTE3MTktNC4wOTc2NTctMjAuNjA1NDY5LTExLjUzOTA2My0yOC4wMzEyNS03LjQ0MTQwNi03LjQyMTg3NS0xNy41NTA3ODEtMTEuNTU0Njg3NS0yOC4wNjI1LTExLjQ2ODc1aC04OC43OTY4NzVjLTEwLjUxMTcxOS0uMDg1OTM3NS0yMC42MjEwOTQgNC4wNDY4NzUtMjguMDYyNSAxMS40Njg3NS03LjQ0MTQwNiA3LjQyNTc4MS0xMS41OTc2NTYgMTcuNTE5NTMxLTExLjUzOTA2MiAyOC4wMzEyNXYxMi41aC01MS4xOTkyMTljLTE5LjE4NzUuMDAzOTA2LTM1LjM5NDUzMSAxNC4yMzQzNzUtMzcuODc4OTA3IDMzLjI1NzgxMi0yLjQ4MDQ2OCAxOS4wMjczNDQgOS41MzUxNTcgMzYuOTQxNDA3IDI4LjA3ODEyNiA0MS44NjMyODJ6bTIzOS42MDE1NjIgMjc5Ljg3ODkwNmgtMTg5LjIwMzEyNWMtMTcuMDk3NjU2IDAtMzAuMzk4NDM3LTE0LjY4NzUtMzAuMzk4NDM3LTMzLjV2LTI0NS41aDI1MHYyNDUuNWMwIDE4LjgxMjUtMTMuMzAwNzgyIDMzLjUtMzAuMzk4NDM4IDMzLjV6bS0xNTguNjAxNTYyLTM2Ny41Yy0uMDY2NDA3LTUuMjA3MDMxIDEuOTgwNDY4LTEwLjIxODc1IDUuNjc1NzgxLTEzLjg5NDUzMSAzLjY5MTQwNi0zLjY3NTc4MSA4LjcxNDg0My01LjY5NTMxMyAxMy45MjU3ODEtNS42MDU0NjloODguNzk2ODc1YzUuMjEwOTM3LS4wODk4NDQgMTAuMjM0Mzc1IDEuOTI5Njg4IDEzLjkyNTc4MSA1LjYwNTQ2OSAzLjY5NTMxMyAzLjY3MTg3NSA1Ljc0MjE4OCA4LjY4NzUgNS42NzU3ODIgMTMuODk0NTMxdjEyLjVoLTEyOHptLTcxLjE5OTIxOSAzMi41aDI3MC4zOTg0MzdjOS45NDE0MDYgMCAxOCA4LjA1ODU5NCAxOCAxOHMtOC4wNTg1OTQgMTgtMTggMThoLTI3MC4zOTg0MzdjLTkuOTQxNDA3IDAtMTgtOC4wNTg1OTQtMTgtMThzOC4wNTg1OTMtMTggMTgtMTh6bTAgMCIvPjxwYXRoIGQ9Im0xNzMuMzk4NDM4IDE1NC43MDMxMjVjLTUuNTIzNDM4IDAtMTAgNC40NzY1NjMtMTAgMTB2MTg5YzAgNS41MTk1MzEgNC40NzY1NjIgMTAgMTAgMTAgNS41MjM0MzcgMCAxMC00LjQ4MDQ2OSAxMC0xMHYtMTg5YzAtNS41MjM0MzctNC40NzY1NjMtMTAtMTAtMTB6bTAgMCIvPjwvc3ZnPg==);
background-size: 90% 90%;
background-position: center center;
background-repeat: no-repeat;
opacity: 0.2;
margin-top: 3px;
margin-right: 20px;
}
.ct_delete:hover {
opacity: 1;
}
/*開啟圖片*/
.ct_open {
float: right;
display: block;
width: 20px;
height: 20px;
background-image: url(data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE5LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPg0KPHN2ZyB2ZXJzaW9uPSIxLjEiIGlkPSJDYXBhXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4Ig0KCSB2aWV3Qm94PSIwIDAgNDUxIDQ1MSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAgNDUxIDQ1MTsiIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGc+DQoJPHBhdGggZD0iTTQ0Ny4wNSw0MjhsLTEwOS42LTEwOS42YzI5LjQtMzMuOCw0Ny4yLTc3LjksNDcuMi0xMjYuMUMzODQuNjUsODYuMiwyOTguMzUsMCwxOTIuMzUsMEM4Ni4yNSwwLDAuMDUsODYuMywwLjA1LDE5Mi4zDQoJCXM4Ni4zLDE5Mi4zLDE5Mi4zLDE5Mi4zYzQ4LjIsMCw5Mi4zLTE3LjgsMTI2LjEtNDcuMkw0MjguMDUsNDQ3YzIuNiwyLjYsNi4xLDQsOS41LDRzNi45LTEuMyw5LjUtNA0KCQlDNDUyLjI1LDQ0MS44LDQ1Mi4yNSw0MzMuMiw0NDcuMDUsNDI4eiBNMjYuOTUsMTkyLjNjMC05MS4yLDc0LjItMTY1LjMsMTY1LjMtMTY1LjNjOTEuMiwwLDE2NS4zLDc0LjIsMTY1LjMsMTY1LjMNCgkJcy03NC4xLDE2NS40LTE2NS4zLDE2NS40QzEwMS4xNSwzNTcuNywyNi45NSwyODMuNSwyNi45NSwxOTIuM3oiLz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjxnPg0KPC9nPg0KPGc+DQo8L2c+DQo8Zz4NCjwvZz4NCjwvc3ZnPg0K);
background-size: 90% 90%;
background-position: center center;
background-repeat: no-repeat;
opacity: 0.2;
margin-top: 3px;
margin-right: 20px;
}
.ct_open:hover {
opacity: 1;
}
</style>
<div class="but_ct" onclick="add_ct()">截圖</div>
<span style="font-size:14px; color:rgb(100, 100, 100)">(截圖快速鍵 「F8」</span>
<div id="ct_output"></div>
<div id="temp_ct_item" style="display:none;">
<div class="ct_item">
<img class="ct_img" src="{{ct_img}}">
<div>
<div class="ct_time">{{ct_time}}</div>
<a class="ct_download" download="{{ct_name}}" href="{{ct_img}}"></a>
<a class="ct_open" href="{{ct_img}}" target="_blank"></a>
<div class="ct_delete" onclick="ct_delete('{{nub}}')"></div>
</div>
</div>
</div>
</div>
`;
var dom_div = document.createElement('div');
dom_div.innerHTML = s_html;
//目前截圖的編號(用於刪除圖片)
window.ct_nub = 1;
//把截圖的按鈕,插入到標題上方
var dom_player = document.getElementsByClassName('anime-title')[0];
dom_player.parentNode.insertBefore(dom_div, dom_player);
//繪製圖片用的 canvas
var cc = document.createElement('canvas');
document.body.append(cc);
//截圖快速鍵
document.body.addEventListener("keydown", function (e) {
if (e.keyCode == 119) { //F8
add_ct();
}
});
/**
* 影片截圖
*/
function add_ct() {
//取得影片目前的畫面
var video = document.getElementById('ani_video_html5_api');
cc.width = video.videoWidth;
cc.height = video.videoHeight;
cc.setAttribute('style', 'width:0px; height:0px;');
cc.getContext('2d').drawImage(video, 0, 0, video.videoWidth, video.videoHeight);
let base64 = cc.toDataURL("image/jpeg", 0.95);
let imgsrc = URL.createObjectURL(dataURItoBlob(base64));// Blob url
let imgtime = document.querySelector('.vjs-current-time .vjs-current-time-display').innerHTML;//目前時間
let s_tit = document.querySelector('.anime_name h1').innerHTML;
s_tit = s_tit.replace(/[/]/g, ' ').replace(/[\\]/g, ' ').replace(/[:]/g, ':').replace(/[*]/g, ' ')
.replace(/["]/g, ' ').replace(/[?]/g, ' ').replace(/[<]/g, ' ').replace(/[>]/g, ' ').replace(/[|]/g, ' ')
.replace(/[\t]/g, ' ').replace(/[\n]/g, ' ').replace(/[\r]/g, ' ');//避免windows不支援的檔名
let s_time = imgtime.replace(/[:]/g, ':');
let imgname = s_tit + ' ' + s_time + '.jpg';//圖片檔名
let dom_ct_item = document.createElement('div');
dom_ct_item.setAttribute('class', 'ct_item ' + 'ct_nub_' + window.ct_nub);
let shtml = `
<img class="ct_img" src="{{ct_img}}">
<div>
<div class="ct_time">{{ct_time}}</div>
<a class="ct_download" download="{{ct_name}}" href="{{ct_img}}"></a>
<a class="ct_open" href="{{ct_img}}" target="_blank"></a>
<div class="ct_delete" onclick="ct_delete('{{nub}}')"></div>
</div>
`;
shtml = shtml.replace(/{{ct_img}}/g, imgsrc)
.replace(/{{ct_time}}/g, imgtime)
.replace(/{{ct_name}}/g, imgname)
.replace(/{{nub}}/g, window.ct_nub);
dom_ct_item.innerHTML = shtml;
document.getElementById('ct_output').append(dom_ct_item);
window.ct_nub += 1;
}
/**
* 刪除圖片
* @param nub
*/
function ct_delete(nub) {
let child = document.querySelector('.ct_nub_' + nub);
child.parentNode.removeChild(child);
}
/**
* Blob object 轉 Blob url
* @param dataURI
*/
function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], { type: mimeString });
}
window.add_ct = add_ct;
window.ct_delete = ct_delete;
window.dataURItoBlob = dataURItoBlob;
})();