Greasy Fork

Greasy Fork is available in English.

下書き君(画像)v1.6.1

ピクトセンスに画像をオーバーレイ表示して模写・下書きを支援!iPadでもズレずに使える!

当前为 2025-08-09 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         下書き君(画像)v1.6.1
// @namespace    http://tampermonkey.net/
// @version      1.6.1
// @description  ピクトセンスに画像をオーバーレイ表示して模写・下書きを支援!iPadでもズレずに使える!
// @author       虚言癖
// @match        https://pictsense.com/*
// @grant        none
// @license      MIT
// ==/UserScript==

(function () {
    'use strict';
  //UIの設定 操作パネルもろもろ
    const imageContainer = document.createElement("div");
    imageContainer.id = "imageOverlayUI";
    Object.assign(imageContainer.style, {
        position: "fixed",
        bottom: "10px",
        right: "10px",
        backgroundColor: "#222",
        padding: "6px",
        borderRadius: "6px",
        color: "#fff",
        fontFamily: "Arial,sans-serif",
        userSelect: "none",
        boxShadow: "0 0 6px #000",
        zIndex: 10000,
        fontSize: "12px",
        lineHeight: "1.4",
        cursor: "grab",
    });
    //UIのHTML 操作パネルの見た目いじりたいときはこのへんいじればいいよ。
    imageContainer.innerHTML = `
        <div style="font-weight:bold; margin-bottom:6px; cursor: grab;">🖼 下書き君(画像)</div>
        <input type="file" id="imageInput" accept="image/*" style="margin-bottom:4px; font-size: 11px; background-color: #222; color: white; border: none; padding: 2px;" />
        <label style="display:block; margin-top:4px;">サイズ</label>
        <input type="range" id="imageSize" min="10" max="200" value="100" style="width:100%; margin-bottom:4px; accent-color: #555;" />
        <label style="display:block;">透明度</label>
        <input type="range" id="imageOpacity" min="10" max="100" value="100" style="width:100%; margin-bottom:4px; accent-color: #555;" />
        <button id="lockBtn" style="width:100%; font-size:11px; margin-top:4px; background-color: #444; color: white; border: none; padding: 4px;">🔒 固定モード OFF</button>
        <button id="removeBtn" style="width:100%; font-size:11px; margin-top:4px; background-color: #844; color: white; border: none; padding: 4px;">画像を消す</button>
    `;

    document.body.appendChild(imageContainer);

    const imageInput = document.getElementById("imageInput");
    const imageSize = document.getElementById("imageSize");
    const imageOpacity = document.getElementById("imageOpacity");
    const lockBtn = document.getElementById("lockBtn");
    const removeBtn = document.getElementById("removeBtn");

    //出した画像の設定もろもろ
    const overlayImage = document.createElement("img");
    overlayImage.style.position = "fixed";
    overlayImage.style.top = "150px";
    overlayImage.style.left = "20px";
    overlayImage.style.zIndex = 9999;
    overlayImage.style.pointerEvents = "auto";
    overlayImage.style.opacity = 1;
    overlayImage.style.maxWidth = "none";
    overlayImage.style.maxHeight = "none";
    overlayImage.style.cursor = "move";
    overlayImage.style.transformOrigin = "top left";
    document.body.appendChild(overlayImage);

    let currentScale = 1;
    let locked = false;

    imageInput.addEventListener("change", (e) => {
        const file = e.target.files[0];
        if (!file) return;
        const reader = new FileReader();
        reader.onload = (event) => {
            overlayImage.src = event.target.result;
            overlayImage.style.display = "block";
        };
        reader.readAsDataURL(file);
    });

    //サイズを変えるスライダーで変える。
    imageSize.addEventListener("input", () => {
        currentScale = imageSize.value / 100;
        overlayImage.style.transform = `scale(${currentScale})`;
    });

    //透過度。スライダーでオーパシティをいじる。
    imageOpacity.addEventListener("input", () => {
        const opacity = imageOpacity.value / 100;
        overlayImage.style.opacity = opacity;
    });

  //画像を動かないようにするボタンドラッグを無効にする。
    lockBtn.addEventListener("click", () => {
        locked = !locked;
        overlayImage.style.pointerEvents = locked ? "none" : "auto";
        overlayImage.style.cursor = locked ? "default" : "move";
        lockBtn.textContent = locked ? "🔓 固定モード ON" : "🔒 固定モード OFF";
    });

    removeBtn.addEventListener("click", () => {
        overlayImage.src = "";
        overlayImage.style.display = "none";
    });

    let dragging = false;
    let offsetX = 0, offsetY = 0;

    overlayImage.addEventListener("mousedown", (e) => {
        if (locked) return;
        dragging = true;
        const rect = overlayImage.getBoundingClientRect();
        offsetX = (e.clientX - rect.left) / currentScale;
        offsetY = (e.clientY - rect.top) / currentScale;
        e.preventDefault();
    });

    document.addEventListener("mousemove", (e) => {
        if (!dragging || locked) return;
        overlayImage.style.left = `${e.clientX - offsetX * currentScale}px`;
        overlayImage.style.top = `${e.clientY - offsetY * currentScale}px`;
    });

    document.addEventListener("mouseup", () => {
        dragging = false;
    });
        //タッチ系。AIに任せた。
    overlayImage.addEventListener("touchstart", (e) => {
        if (locked) return;
        const touch = e.touches[0];
        const rect = overlayImage.getBoundingClientRect();
        const scale = window.visualViewport ? window.visualViewport.scale : 1;
        offsetX = (touch.clientX - rect.left) / (currentScale * scale);
        offsetY = (touch.clientY - rect.top) / (currentScale * scale);
        dragging = true;
        e.preventDefault();
    }, { passive: false });

    document.addEventListener("touchmove", (e) => {
        if (!dragging || locked) return;
        const touch = e.touches[0];
        const scale = window.visualViewport ? window.visualViewport.scale : 1;
        overlayImage.style.left = `${touch.clientX - offsetX * currentScale * scale}px`;
        overlayImage.style.top = `${touch.clientY - offsetY * currentScale * scale}px`;
    }, { passive: false });

    document.addEventListener("touchend", () => {
        dragging = false;
    }, { passive: false });

    let uiDragging = false;
    let uiOffsetX = 0, uiOffsetY = 0;

    imageContainer.addEventListener("mousedown", (e) => {
        if (["INPUT", "BUTTON", "LABEL"].includes(e.target.tagName)) return;
        uiDragging = true;
        const rect = imageContainer.getBoundingClientRect();
        uiOffsetX = e.clientX - rect.left;
        uiOffsetY = e.clientY - rect.top;
        imageContainer.style.cursor = "grabbing";
        e.preventDefault();
    });

    document.addEventListener("mousemove", (e) => {
        if (!uiDragging) return;
        imageContainer.style.left = `${e.clientX - uiOffsetX}px`;
        imageContainer.style.top = `${e.clientY - uiOffsetY}px`;
        imageContainer.style.bottom = "auto";
        imageContainer.style.right = "auto";
    });

    document.addEventListener("mouseup", () => {
        uiDragging = false;
        imageContainer.style.cursor = "grab";
    });

    imageContainer.addEventListener("touchstart", (e) => {
        if (["INPUT", "BUTTON", "LABEL"].includes(e.target.tagName)) return;
        const touch = e.touches[0];
        const rect = imageContainer.getBoundingClientRect();
        uiOffsetX = touch.clientX - rect.left;
        uiOffsetY = touch.clientY - rect.top;
        uiDragging = true;
        imageContainer.style.cursor = "grabbing";
        e.preventDefault();
    }, { passive: false });

    document.addEventListener("touchmove", (e) => {
        if (!uiDragging) return;
        const touch = e.touches[0];
        imageContainer.style.left = `${touch.clientX - uiOffsetX}px`;
        imageContainer.style.top = `${touch.clientY - uiOffsetY}px`;
        imageContainer.style.bottom = "auto";
        imageContainer.style.right = "auto";
    }, { passive: false });

    document.addEventListener("touchend", () => {
        uiDragging = false;
        imageContainer.style.cursor = "grab";
    }, { passive: false });
})();