您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
An automatic and free score downloader for musescore
// ==UserScript== // @name Musescore Free PDF Downloader // @namespace http://tampermonkey.net/ // @version 1.0 // @author malatia // @match https://musescore.com/*/* // @icon https://www.google.com/s2/favicons?sz=64&domain=musescore.com // @grant GM_addStyle // @require https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/pdf-lib/1.16.0/pdf-lib.min.js // @description An automatic and free score downloader for musescore // @license MIT // ==/UserScript== // Idea from MuseScore Download By flancast90 let DEBUG = true GM_addStyle(`.glowbutton { --glow-color: rgb(176, 252, 255); --glow-spread-color: rgba(123, 251, 255, 0.781); --enhanced-glow-color: rgb(206, 255, 255); --btn-color: rgb(61, 127, 136); border: 0.25em solid var(--glow-color); padding: 1em 1em; color: var(--glow-color); font-size: 15px; font-weight: bold; background-color: var(--btn-color); border-radius: 1em; outline: none; box-shadow: 0 0 1em 0.25em var(--glow-color), 0 0 4em 1em var(--glow-spread-color), inset 0 0 0.75em 0.25em var(--glow-color); text-shadow: 0 0 0.5em var(--glow-color); position: relative; transition: all 0.3s; } .glowbutton::after { pointer-events: none; content: ""; position: absolute; top: 120%; left: 0; height: 100%; width: 100%; background-color: var(--glow-spread-color); filter: blur(2em); opacity: 0.7; transform: perspective(1.5em) rotateX(35deg) scale(1, 0.6); } .glowbutton:hover { color: var(--btn-color); background-color: var(--glow-color); box-shadow: 0 0 1em 0.25em var(--glow-color), 0 0 4em 2em var(--glow-spread-color), inset 0 0 0.75em 0.25em var(--glow-color); } .glowbutton:active { box-shadow: 0 0 0.6em 0.25em var(--glow-color), 0 0 2.5em 2em var(--glow-spread-color), inset 0 0 0.5em 0.25em var(--glow-color); } `) async function img_to_canvas_to_bytes(img) { return new Promise((resolve, reject) => { // Création d'un canvas pour dessiner l'image const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); // Chargement de l'image dans le canvas img.crossOrigin = 'Anonymous'; // Permet d'accéder à l'image cross-origin img.onload = () => { canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); // Conversion du contenu du canvas en données PNG const pngBytes = canvas.toDataURL('image/png').split(',')[1]; resolve(pngBytes); }; img.onerror = () => { reject(new Error('Échec du chargement de l\'image.')); }; img.src = img.src; // Déclenche le chargement de l'image }); } async function fetchAndAssemblePDF(urls) { // Création d'un nouveau document PDF const pdfDoc = await PDFLib.PDFDocument.create(); // Tableau pour stocker les documents PNG générés const pngDocs = []; // Parcours de chaque URL de fichier img console.log("Avant boucle urls") for (const url of urls) { console.log("url = " + url) // Récupération du fichier img à partir de l'URL const response = await fetch(url); console.log(response) const imgText = await response.text(); if (url.includes(".svg")) { const img = new Image(); const imgLoaded = new Promise((resolve, reject) => { img.onload = resolve; img.onerror = reject; }); // Création d'un blob à partir du texte SVG const svgBlob = new Blob([imgText], { type: 'image/svg+xml' }); // Création d'une image à partir du blob SVG img.src = URL.createObjectURL(svgBlob); // Attente du chargement complet de l'image try { // Attendre le chargement complet de l'image await imgLoaded; console.log("Image SVG chargée avec succès"); } catch (error) { console.error("Erreur lors du chargement de l'image SVG:", error); continue; // Passe à l'itération suivante dans la boucle } // Création d'un canvas pour dessiner l'image SVG const canvas = document.createElement('canvas'); canvas.width = img.width; canvas.height = img.height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0); // Conversion du canvas en format PNG const pngBytes = canvas.toDataURL('image/png').split(',')[1]; // Incorporation du PNG dans le document PDF const pngDoc = await pdfDoc.embedPng(pngBytes); pngDocs.push(pngDoc); // Ajout du document PNG au tableau } else if (url.includes(".png")) { console.log("Dans la partie PNG"); const img = new Image(); const imgLoaded = new Promise((resolve, reject) => { img.onload = resolve; img.onerror = reject; }); // Chargement de l'image à partir de l'URL img.src = url; // Promesse basée sur le chargement complet de l'image try { // Attendre le chargement complet de l'image await imgLoaded; console.log("Image PNG chargée avec succès"); } catch (error) { console.error("Erreur lors du chargement de l'image PNG:", error); continue; // Passe à l'itération suivante dans la boucle } const pngBytes = await img_to_canvas_to_bytes(img) // Incorporation de l'image PNG dans le document PDF const pngDoc = await pdfDoc.embedPng(pngBytes); pngDocs.push(pngDoc); } } // Parcours des documents PNG pour les ajouter au document PDF for (const pngDoc of pngDocs) { const page = pdfDoc.addPage([pngDoc.width, pngDoc.height]); page.drawImage(pngDoc, { x: 0, y: 0, width: pngDoc.width, height: pngDoc.height, }); } // Enregistrement du document PDF const pdfBytes = await pdfDoc.save(); // Téléchargement du PDF const blob = new Blob([pdfBytes], { type: 'application/pdf' }); const link = document.createElement('a'); link.href = window.URL.createObjectURL(blob); let title = document.title.replace(" ", "_") + ".pdf" link.download = title; link.click(); } let scrolled = 0; let urls = []; let height; let scrollHeight; let scrollContainer $(document).ready(async function () { setTimeout(() => { // ICI ON PARLE DU CONTENANT AVEC SCROLL scrollContainer = parseInt(document.getElementById('jmuse-scroller-component').scrollHeight); // ICI ON PARLE DES IMAGES height = parseInt(document.getElementsByClassName('KfFlO')[0].height); scrollHeight = (scrollContainer - (scrollContainer % height)); // On cherche le bouton downlad de base pour le remplacer par le nôtre const btns = [...document.getElementsByTagName("button")] btns.filter(el => { const val = el.attributes.getNamedItem("name")?.value return val == "download" }).forEach(el => { const type = el.attributes.getNamedItem("name").value const fakeEl = el.cloneNode(true) // fakeEl.style.border = "2px #0dbc79 solid" fakeEl.value = "Download Free PDF" fakeEl.classList.add("glowbutton") // fakeEl.style.webkitBoxShadow = "0px 0px 127px 65px rgba(45,255,196,0.8);" // fakeEl.style.mozBoxShadow = "0px 0px 127px 65px rgba(45,255,196,0.8);;" // fakeEl.style.BoxShadow = "0px 0px 127px 65px rgba(45,255,196,0.8);" fakeEl.class = fakeEl.onclick = download_pdf el.parentNode.replaceChild(fakeEl, el) }) }, 2000) // function get_lazy_imgs() { // // Fonction récursive pour récupérer les images // while (scrolled < scrollHeight) { // // Attendre un peu avant de récupérer les images // setTimeout(() => { // // Faire défiler la fenêtre // console.log("Scrolled : " + scrolled) // console.log("scrollHeight : " + scrollHeight) // scrollContainer.scrollTop = scrolled; // scrolled += height; // if (DEBUG) console.log("Get_lazy") // // Récupérer les images // let images = document.getElementsByClassName('KfFlO'); // if (images.length > 0) { // urls.push(images[images.length - 1].src); // } // }, 1000); // } // } function get_lazy_imgs() { console.log("Début get_lazy_images"); return new Promise((resolve, reject) => { // Fonction récursive pour récupérer les images function fetchImages() { scrollContainer = document.getElementById('jmuse-scroller-component'); scrollHeight = scrollContainer.scrollHeight; if (scrolled < scrollHeight) { // Faire défiler la fenêtre scrollContainer.scrollTop = scrolled; scrolled += height; // Attendre un peu avant de récupérer les images setTimeout(() => { // Récupérer les images const images = document.getElementsByClassName('KfFlO'); if (images.length > 0) { // Ajouter les URLs des images au tableau urls.push(images[images.length - 1].src); } // Rappel récursif jusqu'à ce que le scroll atteigne la fin fetchImages(); }, 1000); } else { // Résoudre la promesse avec les URLs des images resolve(urls); console.log("Fin get_lazy_images"); } } // Début de la récupération des images fetchImages(); }); } async function download_pdf() { console.log("Avant get_lazy_images"); await get_lazy_imgs(); // Attendre la récupération de toutes les URLs d'images console.log("Après get_lazy_images"); console.log("Avant fetchAndAssemble"); await fetchAndAssemblePDF(urls); // Utiliser les URLs pour générer le PDF console.log("Après fetchAndAssemble"); scrolled = 0; // Réinitialiser le défilement } });
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址