download pdf or print any sheets!
当前为
// ==UserScript==
// @name Musescore Downloader
// @version 1.0
// @description download pdf or print any sheets!
// @author Charlie
// @match https://musescore.com/*
// @namespace https://greasyfork.org/users/890174
// ==/UserScript==
setTimeout(() => {
"use strict"
async function download(autoPrint) {
const Window = window.open()
const id = location.pathname.match(/\/[^\/]*$/)[0].slice(1)
const length = document.getElementsByClassName("BmIOX").length
Window.document.write(`
<!DOCTYPE html>
<head>
<title>${document.getElementsByTagName('h1')[0].innerText}</title>
<style>
body {
margin: 0;
display: flex;
min-height: 100vh;
flex-direction: column;
place-items: center;
justify-content: center;
color: rgb(49, 63, 78);
background-color: rgb(237, 242, 247);
transform-origin: top;
transition: background-color ease .3s;
will-change: background-color;
overflow-x: scroll;
}
svg {
width: 100vw;
height: auto;
display: block;
margin: auto;
}
.card {
display: flex;
text-align: center;
place-items: center;
font-size: 1.2em;
width: 320px;
box-shadow: 10px 10px 8px rgba(0, 0, 0, 0.07);
padding: 1.5em 2em;
background-color: rgb(255, 255, 255);
border-radius: 8px;
transition: all ease-out .3s;
animation: card-intro .8s ease-out;
overflow: hidden;
white-space: nowrap;
}
@keyframes card-intro {
from {
box-shadow: 10px 10px 2px rgba(0, 0, 0, 0.03);
width: 0;
opacity: 0.6;
}
to {
box-shadow: 10px 10px 8px rgba(0, 0, 0, 0.07);
width: 320px;
opacity: 1;
}
}
.card-icon {
display: flex;
flex-direction: column;
place-items: center;
margin-right: 3em;
font-weight: bold;
}
.card-text {
flex: 1;
}
b {
color: rgb(49, 140, 252);
}
.spinner, .spinner * { box-sizing: border-box; }
.spinner {
height: 40px;
width: 40px;
top: calc( -10px * 2 / 3);
margin-left: calc(10px / 3);
margin-bottom: calc(10px / 3);
}
.spinner .sq {
height: 10px;
width: 10px;
top: calc( -10px * 2 / 3);
margin-right: calc(10px / 3);
margin-top: calc(10px / 3);
background: rgb(49, 140, 252);
float: left;
position: relative;
opacity: 0;
animation: spinner 6s infinite;
}
.spinner .sq:nth-child(1) { animation-delay: calc(300ms * 6); }
.spinner .sq:nth-child(2) { animation-delay: calc(300ms * 7); }
.spinner .sq:nth-child(3) { animation-delay: calc(300ms * 8); }
.spinner .sq:nth-child(4) { animation-delay: calc(300ms * 3); }
.spinner .sq:nth-child(5) { animation-delay: calc(300ms * 4); }
.spinner .sq:nth-child(6) { animation-delay: calc(300ms * 5); }
.spinner .sq:nth-child(7) { animation-delay: calc(300ms * 0); }
.spinner .sq:nth-child(8) { animation-delay: calc(300ms * 1); }
.spinner .sq:nth-child(9) { animation-delay: calc(300ms * 2); }
.spinner .clear { clear: both; }
@keyframes spinner {
0% { opacity: 0; }
5% { opacity: 1; top: 0; }
50.9% { opacity: 1; top: 0; }
55.9% { opacity: 0; top: inherit; }
}
@media print {
@page {
margin: 0;
}
button {
display: none;
}
svg {
width: 21cm;
height: 29.7cm;
}
}
.btn-group {
position: fixed;
left: 32px;
top: 24px;
}
button {
font-size: 1.4em;
font-weight: bold;
box-shadow: 1px 2px 8px rgba(0, 0, 0, 0.1);
padding: .4em 1.6em;
margin-right: 1.2em;
background-color: rgb(255, 255, 255);
color: rgb(49, 63, 78);
border-radius: 4px;
cursor: pointer;
outline: 1.5px solid rgb(49, 63, 78);
border: none;
transition: all ease-out .2s;
}
button:hover {
background-color: rgb(235, 235, 235);
}
button:active {
outline-color: black;
transform: scale(0.97);
}
</style>
</head>
<body>
<div class="card">
<div class="card-icon">
<div class="spinner">
<div class="sq"></div>
<div class="sq"></div>
<div class="sq"></div>
<div class="sq clear"></div>
<div class="sq"></div>
<div class="sq"></div>
<div class="sq clear"></div>
<div class="sq"></div>
<div class="sq"></div>
</div>
<div class="card-icon-text">下载中</div>
</div>
<div class="card-text">
第 <b id="download-status">0</b> 页,共 <b>${length}</b> 页
</div>
</div>
</body>`)
let dataString = ""
for (let i = 0; i < length; i++) {
let url = await fetch(`https://musescore.com/api/jmuse?id=${id}&type=img&v2=1&index=${i}`, {
headers: {
authorization: "8c022bdef45341074ce876ae57a48f64b86cdcf5"
}
}).then(e => e.json())
.then(e => e.info.url)
dataString += await fetch(url).then(e => e.text())
Window.document.getElementById("download-status").innerText = i + 1
}
setTimeout(() => {
Window.document.getElementsByClassName("card-icon-text")[0].innerText = "完成!"
setTimeout(() => {
Window.document.body.style.background = "white"
Window.document.body.innerHTML = dataString + `<div class="btn-group"><button onclick="print()">打印</button>`
const svgs = [...Window.document.getElementsByTagName("svg")]
svgs.forEach((e) => e.setAttribute("viewBox", `0 0 ${e.width.baseVal.value} ${e.height.baseVal.value}`))
Window.scrollTo(0, 0)
if(autoPrint) Window.print()
}, 400)
}, 800)
}
const btns = [...document.getElementsByTagName("button")]
btns.filter(el => {
const val = el.attributes.getNamedItem("name")?.value
return val == "download" || val == "print"
}).forEach(el => {
const type = el.attributes.getNamedItem("name").value
const fakeEl = el.cloneNode(true)
fakeEl.style.border = "2px #0dbc79 solid"
if(type == "download") fakeEl.style.background = "#0dbc79"
fakeEl.onclick = () => download(type == 'print')
el.parentNode.replaceChild(fakeEl, el)
})
}, 500)