您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Allows you to draw directly on webpages when you press Shift+Alt+D
当前为
// ==UserScript== // @name Draw on Page // @version 1.1 // @description Allows you to draw directly on webpages when you press Shift+Alt+D // @author someRandomGuy2 // @match *://*/* // @grant none // @license Apache-2.0 // @namespace https://greasyfork.org/users/117222 // ==/UserScript== (function() { 'use strict'; let container; let drawingCanvas; let contextMenuContainer; let contextMenu; let enabled = false; let color = "#ff0000"; const brushes = { pen: function(X, startX, startY, endX, endY, pressure) { X.fillStyle = color; const movementX = endX - startX; const movementY = endY - startY; const step = 2; const distance = Math.sqrt(movementX * movementX + movementY * movementY); const size = 4 * pressure; const halfSize = size / 2; const distanceStep = Math.max(0.2, halfSize); for (let i = 0; i < distance; i += distanceStep) { const x = startX * (1 - i / distance) + endX * (i / distance); const y = startY * (1 - i / distance) + endY * (i / distance); X.fillRect(x - halfSize, y - halfSize, size, size); } X.fillRect(endX - halfSize, endY - halfSize, size, size); }, eraser: function(X, startX, startY, endX, endY, pressure) { const movementX = endX - startX; const movementY = endY - startY; const step = 2; const distance = Math.sqrt(movementX * movementX + movementY * movementY); const size = 50 * pressure; const halfSize = size / 2; const distanceStep = Math.max(0.2, halfSize); for (let i = 0; i < distance; i += distanceStep) { const x = startX * (1 - i / distance) + endX * (i / distance); const y = startY * (1 - i / distance) + endY * (i / distance); X.clearRect(x - halfSize, y - halfSize, size, size); } X.clearRect(endX - halfSize, endY - halfSize, size, size); }, }; function toggleDrawable() { initIfNotAlready(); if (enabled) { enabled = false; container.classList.add("tm-drawing-canvas-fallthrough"); } else { enabled = true; container.classList.remove("tm-drawing-canvas-fallthrough"); } } function initIfNotAlready() { if (container) { return; } container = document.createElement("div"); container.classList.add("tm-drawing-canvas-container"); drawingCanvas = document.createElement("canvas"); drawingCanvas.classList.add("tm-drawing-canvas"); container.appendChild(drawingCanvas); drawingCanvas.width = innerWidth; drawingCanvas.height = innerHeight; contextMenuContainer = document.createElement("div"); contextMenuContainer.classList.add("tm-drawing-canvas-context-menu-container"); contextMenu = document.createElement("div"); contextMenuContainer.appendChild(contextMenu); contextMenu.classList.add("tm-drawing-canvas-context-menu"); const clearCanvasOption = document.createElement("div"); clearCanvasOption.innerText = "Clear canvas"; contextMenu.appendChild(clearCanvasOption); const saveCanvasOption = document.createElement("div"); saveCanvasOption.innerText = "Save canvas"; contextMenu.appendChild(saveCanvasOption); const changeColor = document.createElement("div"); const colorPicker = document.createElement("input"); colorPicker.type = "color"; colorPicker.value = color; changeColor.appendChild(colorPicker); contextMenu.appendChild(changeColor); const dropShadowToggle = document.createElement("div"); dropShadowToggle.innerText = "Toggle drop shadow"; contextMenu.appendChild(dropShadowToggle); const X = drawingCanvas.getContext("2d"); let mouseDown = false; drawingCanvas.addEventListener("pointerdown", function() { mouseDown = true; }); drawingCanvas.addEventListener("pointerup", function() { mouseDown = false; }); drawingCanvas.addEventListener("pointermove", function(event) { if (!mouseDown) { return; } const brush = event.shiftKey ? brushes.eraser : brushes.pen; const scaleX = drawingCanvas.width / innerWidth; const scaleY = drawingCanvas.height / innerHeight; const startX = (event.x - event.movementX) * scaleX; const startY = (event.y - event.movementY) * scaleY; const endX = event.x * scaleX; const endY = event.y * scaleY; brush(X, startX, startY, endX, endY, event.pressure); }); let hasMouseUpSinceContextMenu = true; drawingCanvas.addEventListener("contextmenu", function(event) { contextMenu.style.top = event.clientY + "px"; contextMenu.style.left = event.clientX + "px"; container.appendChild(contextMenuContainer); hasMouseUpSinceContextMenu = false; event.preventDefault(); }); function addContextMenuItemClickListener(elm, func) { elm.addEventListener("click", func); elm.addEventListener("mouseup", ev => !hasMouseUpSinceContextMenu && func(ev, true)); } function closeContextMenu() { container.removeChild(contextMenuContainer); } addContextMenuItemClickListener(contextMenuContainer, function(event, mouseupShortcutClick) { if (mouseupShortcutClick) { if (event.target != contextMenuContainer && event.target != contextMenu) { closeContextMenu(); } } else { closeContextMenu(); } }); addContextMenuItemClickListener(clearCanvasOption, function() { // clear canvas X.clearRect(0, 0, drawingCanvas.width, drawingCanvas.height); drawingCanvas.width = innerWidth; drawingCanvas.height = innerHeight; }); addContextMenuItemClickListener(saveCanvasOption, function() { drawingCanvas.toBlob(blob => open(URL.createObjectURL(blob))) }); addContextMenuItemClickListener(dropShadowToggle, function() { drawingCanvas.classList.toggle("no-drop-shadow"); }); addContextMenuItemClickListener(changeColor, function(event, mouseupShortcutClick) { if (event.target == changeColor || mouseupShortcutClick) { colorPicker.click(); } event.stopPropagation(); }); colorPicker.addEventListener("change", function() { color = colorPicker.value; closeContextMenu(); }); drawingCanvas.addEventListener("touchmove", function(event) { }); const style = document.createElement("style"); style.innerHTML = ` .tm-drawing-canvas-container { z-index: 99999; position: fixed; top: 0; left: 0; width: 100vw; height: 100vh; font-size: 14px; font-family: sans; line-height: 1.15; color: #000; } .tm-drawing-canvas-container.tm-drawing-canvas-fallthrough { pointer-events: none; } .tm-drawing-canvas { position: aboslute; top: 0; left: 0; width: 100%; height: 100%; cursor: crosshair; filter: drop-shadow(0px 0px 8px background); } .tm-drawing-canvas.no-drop-shadow { filter: none; } .tm-drawing-canvas-context-menu-container { position: fixed; top: 0; left: 0; width: 100%; height: 100%; } .tm-drawing-canvas-context-menu { position: absolute; display: inline-block; background-color: #fff; padding-top: 4px; padding-bottom: 4px; margin-top: 1px; border: 1px solid #00000040; box-shadow: #00000038 0px 1px 16px, #0000002e 0px 1px 8px; } .tm-drawing-canvas-context-menu div { padding: 4px; cursor: pointer; } .tm-drawing-canvas-context-menu div:hover { background-color: #ccc; } `; document.head.appendChild(style); document.body.appendChild(container); } addEventListener("keydown", function(event) { if (event.code == "KeyD" && event.altKey && event.shiftKey) { toggleDrawable(); } }); })();