您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
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)