Greasy Fork is available in English.

Custom-Cursor | 自定义鼠标

custom cursor in page / 自定义鼠标

// ==UserScript==
// @name         Custom-Cursor | 自定义鼠标
// @namespace    http://tampermonkey.net/
// @version      1.0.2
// @description  custom cursor in page / 自定义鼠标
// @license      MIT
// @email        lindaoqiang98@gmail.com
// @author       DQLean
// @match        *://*/*
// @icon         http://tampermonkey.net/favicon.ico
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// ==/UserScript==

(function () {
  'use strict';

    /*
 * ATTENTION: The "eval" devtool has been used (maybe by default in mode: "development").
 * This devtool is neither made for production nor for readable output files.
 * It uses "eval()" calls to create a separate source file in the browser devtools.
 * If you are trying to read the output file, select a different devtool (https://webpack.js.org/configuration/devtool/)
 * or disable the default devtool with "devtool: false".
 * If you are looking for production-ready output files, see mode: "production" (https://webpack.js.org/configuration/mode/).
 */
/******/ (() => { // webpackBootstrap
/******/ 	"use strict";
/******/ 	var __webpack_modules__ = ({

/***/ "./data.js":
/*!*****************!*\
  !*** ./data.js ***!
  \*****************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

          eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"default\": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\r\n    \"n-resize\": {\r\n        list: [],\r\n        index: 0,\r\n    },\r\n    \"s-resize\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"wait\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"nw-resize\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"se-resize\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"sw-resize\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"ne-resize\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"help\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"e-resize\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"w-resize\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"pointer\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"move\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"not-allowed\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"default\": {\r\n        \"list\": [],\r\n        \"index\": 2\r\n    },\r\n    \"copy\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"crosshair\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n    \"text\": {\r\n        list: [],\r\n        index: -1,\r\n    },\r\n});\n\n//# sourceURL=webpack:///./data.js?");

          /***/
}),

/***/ "./i18n.js":
/*!*****************!*\
  !*** ./i18n.js ***!
  \*****************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

          eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */   \"En\": () => (/* binding */ En),\n/* harmony export */   \"Zh\": () => (/* binding */ Zh),\n/* harmony export */   \"t\": () => (/* binding */ t)\n/* harmony export */ });\nconst lang = window.language || navigator.language || navigator.userLanguage;\r\n\r\nconst t = (val) => {\r\n    if (lang.startsWith(\"zh\")) {\r\n        return Zh[val] || val\r\n    }\r\n    if (lang.startsWith(\"en\")) {\r\n        return En[val] || val\r\n    }\r\n    return val\r\n}\r\n\r\nconst En = {\r\n    \"default\": \"Default\",\r\n    \"pointer\": \"Pointer\",\r\n    \"crosshair\": \"Crosshair\",\r\n    \"move\": \"Move\",\r\n    \"e-resize\": \"East Resize\",\r\n    \"ne-resize\": \"North East Resize\",\r\n    \"nw-resize\": \"North West Resize\",\r\n    \"n-resize\": \"North Resize\",\r\n    \"se-resize\": \"South East Resize\",\r\n    \"sw-resize\": \"South West Resize\",\r\n    \"s-resize\": \"South Resize\",\r\n    \"w-resize\": \"West Resize\",\r\n    \"text\": \"Text\",\r\n    \"wait\": \"Wait\",\r\n    \"help\": \"Help\",\r\n    \"copy\": \"Copy\",\r\n    \"not-allowed\": \"Not Allowed\",\r\n\r\n    \"imageUploadLimit128\": \"Image upload limit is 128KB!\",\r\n    \"imageUploadLimit64\": \"Image upload limit is 64KB!\",\r\n    \"imageUploadLimit32\": \"Image upload limit is 32KB!\",\r\n    \"imageUploadLimit16\": \"Image upload limit is 16KB!\",\r\n    \"imageUploadLimit8\": \"Image upload limit is 8KB!\",\r\n\r\n    \"imageLink\": \"Image Link\",\r\n    \"pleaseClickToSelectCenter\": \"Please click to select center point (as mouse origin). Support keyboard direction key fine-tuning.\",\r\n    \"imageTypeLimit\": \"Image must be .png or .cur format!\",\r\n\r\n    \"confirm\": \"Confirm\",\r\n\r\n    \"clickToUploadImage\": \"Click to upload image\",\r\n\r\n    \"pleaseInputImageName\": \"Please input name\",\r\n\r\n    \"setting\": \"Setting\",\r\n\r\n    \"clear\": \"Clear Data\",\r\n}\r\n\r\nconst Zh = {\r\n    \"default\": \"默认\",\r\n    \"pointer\": \"指针\",\r\n    \"crosshair\": \"十字线\",\r\n    \"move\": \"移动\",\r\n    \"e-resize\": \"向左调整\",\r\n    \"ne-resize\": \"向左上调整\",\r\n    \"nw-resize\": \"向右上调整\",\r\n    \"n-resize\": \"向上调整\",\r\n    \"se-resize\": \"向左下调整\",\r\n    \"sw-resize\": \"向右下调整\",\r\n    \"s-resize\": \"向下调整\",\r\n    \"w-resize\": \"向右调整\",\r\n    \"text\": \"文本\",\r\n    \"wait\": \"等待\",\r\n    \"help\": \"帮助\",\r\n    \"copy\": \"复制\",\r\n    \"not-allowed\": \"禁用\",\r\n\r\n    \"imageUploadLimit128\": \"图片上传限制为128KB!\",\r\n    \"imageUploadLimit64\": \"图片上传限制为64KB!\",\r\n    \"imageUploadLimit32\": \"图片上传限制为32KB!\",\r\n    \"imageUploadLimit16\": \"图片上传限制为16KB!\",\r\n    \"imageUploadLimit8\": \"图片上传限制为8KB!\",\r\n\r\n    \"imageLink\": \"图片链接\",\r\n    \"pleaseClickToSelectCenter\": \"请点击选择中心点(作为鼠标原点),支持键盘方向键微调。\",\r\n    \"imageTypeLimit\": \"图片必须为.png或者.cur格式!\",\r\n\r\n    \"confirm\": \"确认\",\r\n\r\n    \"clickToUploadImage\": \"点击上传图片\",\r\n\r\n    \"pleaseInputImageName\": \"请输入名称\",\r\n\r\n    \"setting\": \"设置\",\r\n\r\n    \"clear\": \"清除数据\",\r\n}\n\n//# sourceURL=webpack:///./i18n.js?");

          /***/
}),

/***/ "./index.js":
/*!******************!*\
  !*** ./index.js ***!
  \******************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

          eval("__webpack_require__.r(__webpack_exports__);\n/* harmony import */ var _data_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./data.js */ \"./data.js\");\n/* harmony import */ var _i18n_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./i18n.js */ \"./i18n.js\");\n\r\n\r\n\r\n\r\nconst cursors = (() => {\r\n    try {\r\n        return GM_getValue(\"cursorData\", _data_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"])\r\n    } catch {\r\n        return _data_js__WEBPACK_IMPORTED_MODULE_0__[\"default\"] || {}\r\n    }\r\n})()\r\n\r\ntry {\r\n    GM_registerMenuCommand((0,_i18n_js__WEBPACK_IMPORTED_MODULE_1__.t)(\"setting\"), createMenu)\r\n}catch{}\r\n\r\nconst cursorKeys = [\r\n    \"default\", \"crosshair\", \"pointer\", \"move\",\r\n    \"e-resize\", \"ne-resize\", \"nw-resize\", \"n-resize\", \"se-resize\", \"sw-resize\", \"s-resize\", \"w-resize\",\r\n    \"text\", \"wait\", \"help\", \"copy\", \"not-allowed\"\r\n]\r\n\r\nconst excludeTags = [\r\n    \"script\", \"meta\", \"head\", \"title\", \"link\", \"style\"\r\n]\r\n\r\nlet isMenuShow = false\r\n\r\nwindow.addEventListener(\"keydown\", (e) => {\r\n    const { key } = e\r\n    if (key === \"F9\") {\r\n        createMenu()\r\n    }\r\n})\r\n\r\nlet closeBtnID = \"\"\r\n\r\nfunction getImageBase64(url, size = 32) {\r\n    return new Promise((resolve, reject) => {\r\n        const img = new Image()\r\n        img.onload = () => {\r\n            const canvas = document.createElement(\"canvas\")\r\n            if (img.width > img.height) {\r\n                canvas.width = size\r\n                canvas.height = size * img.height / img.width\r\n            } else {\r\n                canvas.width = size * img.width / img.height\r\n                canvas.height = size\r\n            }\r\n            const ctx = canvas.getContext(\"2d\")\r\n            ctx.drawImage(img, 0, 0, canvas.width, canvas.height)\r\n            const dataURL = canvas.toDataURL()\r\n            resolve(dataURL)\r\n        }\r\n        img.src = url\r\n    })\r\n}\r\n\r\n/**\r\n * @param {HTMLElement} el \r\n */\r\nasync function renderChild(el) {\r\n    const name = el.nodeName.toLocaleLowerCase()\r\n    const type = el.nodeType\r\n    if (!excludeTags.includes(name) && el instanceof Element) {\r\n        let cursorVal = getComputedStyle(el).getPropertyValue(\"cursor\").toLowerCase()\r\n        const originalCursor = el.getAttribute(\"original-cursor\")\r\n        if (originalCursor) cursorVal = originalCursor\r\n        try {\r\n            if (cursorVal === \"\" || cursorVal === \"auto\") {\r\n                if (cursors.default) {\r\n                    const cursor = cursors.default\r\n                    if (cursor.index != void 0 && cursor.index >= 0 && cursor.index < cursor.list.length) {\r\n                        const source = cursor.list[cursor.index].source || \"\"\r\n                        const center = cursor.list[cursor.index].center || [0, 0]\r\n                        if (!originalCursor) el.setAttribute(\"original-cursor\", cursorVal)\r\n                        el.style.cursor = `url(${source\r\n                            }) ${center[0]} ${center[1]}, auto`\r\n                    }\r\n                }\r\n            } else {\r\n                for (let key of cursorKeys) {\r\n                    const _key = key.toLowerCase()\r\n                    if (cursorVal === _key) {\r\n                        if (cursors[_key]) {\r\n                            const cursor = cursors[_key]\r\n                            if (cursor.index != void 0 && cursor.index >= 0 && cursor.index < cursor.list.length) {\r\n                                const source = cursor.list[cursor.index].source || \"\"\r\n                                const center = cursor.list[cursor.index].center || [0, 0]\r\n                                if (!originalCursor) el.setAttribute(\"original-cursor\", cursorVal)\r\n                                el.style.cursor = `url(${source\r\n                                    }) ${center[0]} ${center[1]}, auto`\r\n                            }\r\n                        }\r\n                        break\r\n                    }\r\n                }\r\n            }\r\n        } catch (err) {\r\n            console.error(\"『custom-cursor』\", err)\r\n        }\r\n    }\r\n    if (el.childNodes) {\r\n        for (const child of el.childNodes) {\r\n            await renderChild(child)\r\n        }\r\n    }\r\n}\r\n\r\nrenderChild(document)\r\n\r\n/**\r\n * @param {HTMLElement} el \r\n */\r\nasync function removeRender(el) {\r\n    const name = el.nodeName.toLocaleLowerCase()\r\n    const type = el.nodeType\r\n    if (!excludeTags.includes(name) && el instanceof Element) {\r\n        const cursor = getComputedStyle(el).getPropertyValue(\"cursor\").toLowerCase()\r\n        const originalCursor = el.getAttribute(\"original-cursor\")\r\n        if (cursor.startsWith(\"url\")) {\r\n            el.style.cursor = originalCursor || \"\"\r\n        }\r\n    }\r\n    if (el.childNodes) {\r\n        for (const child of el.childNodes) {\r\n            await removeRender(child)\r\n        }\r\n    }\r\n}\r\n\r\nasync function reRenderPage() {\r\n    await removeRender(document)\r\n    await renderChild(document)\r\n}\r\n\r\nfunction createCloseBtn() {\r\n    if (!closeBtnID) {\r\n        closeBtnID = \"cursor-\" + Date.now() + (\"\" + Math.random()).replace(\".\", \"\")\r\n        const styleEl = document.createElement(\"style\")\r\n        styleEl.appendChild(document.createTextNode(`\r\n        .${closeBtnID} {\r\n            position: absolute !important;\r\n            right: 0 !important;\r\n            top: 0 !important;\r\n            overflow: hidden !important;\r\n            border: none !important;\r\n            padding: 0 !important;\r\n            width: 2em !important; height: 2em !important;\r\n            border-radius: 50% !important;\r\n            background: transparent !important;\r\n            color: #1da1f2 !important;\r\n            font: inherit !important;\r\n            font-size: 16px !important;\r\n            text-indent: 100% !important;\r\n            cursor: pointer !important;\r\n        }\r\n        \r\n        .${closeBtnID}:hover {\r\n            background: rgba(29, 161, 142, .1)\r\n        }\r\n        \r\n        .${closeBtnID}:before, .${closeBtnID}:after {\r\n            position: absolute !important;\r\n            top: 15% !important; left: calc(50% - .0625em) !important;\r\n            width: .125em !important; height: 70% !important;\r\n            border-radius: .125em !important;\r\n            transform: rotate(45deg) !important;\r\n            background: currentcolor !important;\r\n            content: ''\r\n        }\r\n        \r\n        .${closeBtnID}:after { transform: rotate(-45deg) !important; }\r\n        `))\r\n        document.head.appendChild(styleEl)\r\n    }\r\n\r\n    const closeBtn = document.createElement(\"button\")\r\n    closeBtn.className = closeBtnID\r\n    return closeBtn\r\n}\r\n\r\nasync function createMenu() {\r\n    if (isMenuShow) return\r\n    isMenuShow = true\r\n    const createSelectBox = (cursorKey, cursorOpt, callback) => {\r\n        const box = document.createElement(\"div\")\r\n        box.style.cssText = `\r\n        display: inline-flex !important;\r\n        justify-content: center !important;\r\n        align-items: center !important;\r\n        background-color: #464879 !important;\r\n        color: #fff !important;\r\n        padding-left: 8px !important;\r\n        border-radius: 4px !important;\r\n        overflow: hidden !important;\r\n        margin: 4px 2px !important;\r\n        `\r\n\r\n        const select = document.createElement(\"select\")\r\n        select.style.cssText = `\r\n        cursor: pointer !important;\r\n        display: inline-block !important;\r\n        position: relative !important;\r\n        font-size: 16px !important;\r\n        color: #fff !important;\r\n        width: 240px !important;\r\n        height: 40px !important;\r\n        padding-left: 8px !important;\r\n        background-color: #5D7DB3 !important;\r\n        outline: none !important;\r\n        border: none !important;\r\n        margin-left: 4px !important;\r\n        word-break: break-all !important;\r\n        text-overflow: clip !important;\r\n        `\r\n\r\n        const { list, index } = cursorOpt\r\n        if (Array.isArray(list) && list.length > 0) {\r\n            for (let option of list) {\r\n                const op = document.createElement(\"option\")\r\n                op.value = option.source\r\n                op.innerText = option.name\r\n                select.appendChild(op)\r\n            }\r\n            if (index >= 0 && index < list.length) {\r\n                select.value = list[index].source\r\n            }\r\n        }\r\n\r\n        select.onchange = (e) => {\r\n            const val = e.target.value\r\n            if (Array.isArray(list)) {\r\n                const index = list.findIndex(item => item.source === val)\r\n                callback(index)\r\n            } else {\r\n                callback(-1)\r\n            }\r\n        }\r\n\r\n        const label = document.createElement(\"label\")\r\n        label.innerText = (0,_i18n_js__WEBPACK_IMPORTED_MODULE_1__.t)(cursorKey)\r\n        label.style.cssText = `\r\n        width: 84px !important;\r\n        text-overflow: clip !important;\r\n        text-align: center !important;\r\n        cursor: ${cursorKey} !important;\r\n        `\r\n        label.title = (0,_i18n_js__WEBPACK_IMPORTED_MODULE_1__.t)(\"clickToUploadImage\")\r\n        label.onclick = (e) => {\r\n            createImageReader(cursorKey, ({ source, name, center }) => {\r\n                const op = document.createElement(\"option\")\r\n                op.value = source\r\n                op.innerText = name\r\n                select.appendChild(op)\r\n                reRenderPage()\r\n            })\r\n        }\r\n\r\n        box.appendChild(label)\r\n        box.appendChild(select)\r\n\r\n        return box\r\n    }\r\n\r\n    const container = document.createElement(\"div\")\r\n    container.style.cssText = `\r\n    display: inline !important;\r\n    // flex-direction: column !important;\r\n    // justify-content: center !important;\r\n    // align-items: flex-start !important;\r\n    width: 725px !important;\r\n    position: fixed !important;\r\n    top: 50% !important;\r\n    left: 50% !important;\r\n    transform: translate(-50%, -50%) !important;\r\n    background-color: #B6CAD7 !important;\r\n    padding: 32px 16px 16px 16px !important;\r\n    border-radius: 6px !important;\r\n    font-size: 14px !important;\r\n    z-index: 99999 !important;\r\n    `\r\n\r\n    const clearBtn = document.createElement(\"button\")\r\n    clearBtn.innerText = (0,_i18n_js__WEBPACK_IMPORTED_MODULE_1__.t)(\"clear\")\r\n    clearBtn.style.cssText = `\r\n    cursor: pointer !important;\r\n    display: block !important;\r\n    position: relative !important;\r\n    font-size: 14px !important;\r\n    color: #fff !important;\r\n    width: 160px !important;\r\n    height: 28px !important;\r\n    padding-left: 8px !important;\r\n    background-color: #c72121 !important;\r\n    outline: none !important;\r\n    border: none !important;\r\n    margin: auto !important;\r\n    word-break: break-all !important;\r\n    text-overflow: clip !important;\r\n    `\r\n    clearBtn.onclick = () => {\r\n        for (let key in cursors) {\r\n            cursors[key] = {\r\n                list: [],\r\n                index: -1,\r\n            }\r\n        }\r\n        reRenderPage()\r\n        try { GM_setValue(\"cursorData\", cursors) } catch { }\r\n        isMenuShow = false\r\n        document.body.removeChild(container)\r\n    }\r\n\r\n    const closeBtn = createCloseBtn()\r\n\r\n    container.appendChild(closeBtn)\r\n\r\n    for (let key of cursorKeys) {\r\n        if (!cursors[key]) continue\r\n        container.appendChild(createSelectBox(key, cursors[key], (index) => {\r\n            cursors[key].index = index\r\n            reRenderPage()\r\n            try { GM_setValue(\"cursorData\", cursors) } catch { }\r\n            // window.location.reload()\r\n        }))\r\n    }\r\n\r\n    container.appendChild(clearBtn)\r\n\r\n    document.body.appendChild(container)\r\n    closeBtn.onclick = () => {\r\n        isMenuShow = false\r\n        document.body.removeChild(container)\r\n    }\r\n    renderChild(container)\r\n}\r\n\r\nasync function createImageReader(cursorKey, callback = () => { }) {\r\n    const box = document.createElement(\"div\")\r\n    box.style.cssText = `\r\n    padding-top: 16px !important;\r\n    position: fixed !important;\r\n    top: 50% !important;\r\n    left: 50% !important;\r\n    transform: translate(-50%, -50%) !important;\r\n    min-height: 200px !important;\r\n    background-color: #B6CAD7 !important;\r\n    display: flex !important;\r\n    flex-direction: column !important;\r\n    align-items: center !important;\r\n    z-index: 99999 !important;\r\n    `\r\n\r\n    const uploadArea = document.createElement(\"div\")\r\n    uploadArea.innerText = \"Drag To Upload\"\r\n    uploadArea.style.cssText = `\r\n    margin: 16px !important;\r\n    width: 400px !important;\r\n    height: 300px !important;\r\n    font-size: 20px !important;\r\n    text-align: center !important;\r\n    line-height: 300px !important;\r\n    border: 2px dashed #fff !important;\r\n    background-color: #5D7DB3 !important;\r\n    cursor: grab !important;\r\n    `\r\n\r\n    const linkInput = document.createElement(\"input\")\r\n    linkInput.type = \"text\"\r\n    linkInput.placeholder = (0,_i18n_js__WEBPACK_IMPORTED_MODULE_1__.t)(\"imageLink\") + \" [ENTER]\"\r\n    linkInput.style.cssText = `\r\n    margin: 16px !important;\r\n    width: 400px !important;\r\n    height: 40px !important;\r\n    font-size: 20px !important;\r\n    text-align: center !important;\r\n    line-height: 40px !important;\r\n    border: 2px dashed #fff !important;\r\n    background-color: #5D7DB3 !important;\r\n    cursor: text !important;\r\n    `\r\n\r\n    const closeBtn = createCloseBtn()\r\n\r\n    const showImage = async (file) => {\r\n        if (!file) return\r\n\r\n        let image = new Image()\r\n        if (typeof file === \"string\") {\r\n            image.src = file\r\n        } else if (file instanceof Image) {\r\n            image.src = file.src\r\n        } else {\r\n            image.src = await getImageBase64(URL.createObjectURL(file))\r\n        }\r\n\r\n        image.onload = (e) => {\r\n            box.removeChild(uploadArea)\r\n            box.removeChild(linkInput)\r\n            const tipBox = document.createElement(\"div\")\r\n            tipBox.style.cssText = `\r\ntext-align: center !important;\r\nfont-size: 16px !important;\r\nmargin: 5px !important;\r\nline-height: 16px !important;\r\nuser-select: none !important;       \r\n`\r\n            tipBox.innerText = (0,_i18n_js__WEBPACK_IMPORTED_MODULE_1__.t)(\"pleaseClickToSelectCenter\")\r\n            box.appendChild(tipBox)\r\n\r\n            const canvas = document.createElement(\"canvas\")\r\n            let w = image.naturalWidth\r\n            let h = image.naturalHeight\r\n            let mw = window.innerWidth - 80\r\n            let mh = window.innerHeight - 80\r\n            while (w >= mw || h >= mh) {\r\n                w = w * 0.7\r\n                h = h * 0.7\r\n            }\r\n            canvas.width = w\r\n            canvas.height = h\r\n            canvas.style.cssText = `\r\nmargin: 5px 16px !important;\r\nwidth: ${w}px !important;\r\nheight: ${h}px !important;\r\n`\r\n            const ctx = canvas.getContext(\"2d\")\r\n            ctx.drawImage(image, 0, 0, canvas.width, canvas.height)\r\n            box.appendChild(canvas)\r\n            const textLine = document.createElement(\"div\")\r\n            textLine.style.cssText = `\r\ntext-align: center !important;\r\nfont-size: 14px !important;\r\ncolor: #fff !important;\r\nmargin: 5px !important;\r\nline-height: 16px !important;\r\nuser-select: none !important;\r\n`\r\n            textLine.innerText = `X: 0 | Y: 0`\r\n            box.appendChild(textLine)\r\n\r\n            const nameInput = document.createElement(\"input\")\r\n            nameInput.type = \"text\"\r\n            nameInput.placeholder = (0,_i18n_js__WEBPACK_IMPORTED_MODULE_1__.t)(\"pleaseInputImageName\")\r\n            nameInput.style.cssText = `\r\nmargin: 0px 16px !important;\r\nwidth: 80% !important;\r\nheight: 20px !important;\r\nfont-size: 14px !important;\r\ntext-align: center !important;\r\nborder: none !important;\r\nbackground-color: #e1e1e1 !important;\r\ncursor: text !important;\r\n            `\r\n            box.appendChild(nameInput)\r\n\r\n            const ratioSelect = document.createElement(\"select\")\r\n            ratioSelect.style.cssText = `\r\nmargin: 5px 16px !important;\r\nwidth: 80% !important;\r\nheight: 20px !important;\r\nfont-size: 14px !important;\r\ntext-align: center !important;\r\nborder: none !important;\r\nbackground-color: #e1e1e1 !important;\r\ncursor: pointer !important;\r\n`\r\n            const ratioList = [\r\n                { name: \"8x8\", value: 8 },\r\n                { name: \"16x16\", value: 16 },\r\n                { name: \"32x32\", value: 32 },\r\n                { name: \"64x64\", value: 64 },\r\n                { name: \"128x128\", value: 128 },\r\n                // { name: \"256x256\", value: 256 },\r\n                // { name: \"512x512\", value: 512 },\r\n            ]\r\n            for (let ratio of ratioList) {\r\n                const op = document.createElement(\"option\")\r\n                op.value = ratio.value\r\n                op.innerText = ratio.name\r\n                ratioSelect.appendChild(op)\r\n            }\r\n            ratioSelect.value = 32\r\n            ratioSelect.onchange = async (e) => {\r\n                if (typeof file === \"string\" || file instanceof Image) return\r\n                const val = Number(e.target.value) || 32\r\n                const _image = new Image()\r\n                _image.src = await getImageBase64(URL.createObjectURL(file), val)\r\n                _image.onload = () => {\r\n                    canvas.width = _image.naturalWidth\r\n                    canvas.height = _image.naturalHeight\r\n                    canvas.style.cssText = `\r\nmargin: 5px 16px !important;\r\nwidth: ${_image.naturalWidth}px !important;\r\nheight: ${_image.naturalHeight}px !important;\r\n`\r\n                    ctx.drawImage(_image, 0, 0, canvas.width, canvas.height)\r\n                    textLine.innerText = `X: 0 | Y: 0`\r\n                }\r\n                image = _image\r\n            }\r\n            box.appendChild(ratioSelect)\r\n\r\n            const btnBox = document.createElement(\"div\")\r\n            btnBox.style.cssText = `\r\ntext-align: center !important;\r\nfont-size: 14px !important;\r\ncolor: #6d6d6d !important;\r\nmargin: 5px 16px !important;\r\nline-height: 16px !important;\r\nuser-select: none !important;\r\ncursor: pointer !important;\r\nfont-weight: bold !important;\r\n`\r\n            btnBox.innerText = (0,_i18n_js__WEBPACK_IMPORTED_MODULE_1__.t)(\"confirm\")\r\n\r\n            box.appendChild(btnBox)\r\n\r\n            const center = [0, 0]\r\n\r\n            canvas.onclick = (e) => {\r\n                const x = e.offsetX\r\n                const y = e.offsetY\r\n                center[0] = x\r\n                center[1] = y\r\n                textLine.innerText = `X: ${x} | Y: ${y}`\r\n                ctx.clearRect(0, 0, canvas.width, canvas.height)\r\n                ctx.drawImage(image, 0, 0, canvas.width, canvas.height)\r\n                ctx.fillStyle = \"#ff0000\"\r\n                ctx.fillRect(x - 5, y - 5, 10, 10)\r\n            }\r\n            // 监听上下左右键\r\n            document.onkeydown = (e) => {\r\n                // e.preventDefault()\r\n                const drawPoint = () => {\r\n                    textLine.innerText = `X: ${center[0]} | Y: ${center[1]}`\r\n                    ctx.clearRect(0, 0, canvas.width, canvas.height)\r\n                    ctx.drawImage(image, 0, 0, canvas.width, canvas.height)\r\n                    ctx.fillStyle = \"#ff0000\"\r\n                    ctx.fillRect(center[0] - 5, center[1] - 5, 10, 10)\r\n                }\r\n                const { key } = e\r\n                if (key === \"ArrowUp\") {\r\n                    center[1] -= 1\r\n                    drawPoint()\r\n                } else if (key === \"ArrowDown\") {\r\n                    center[1] += 1\r\n                    drawPoint()\r\n                } else if (key === \"ArrowLeft\") {\r\n                    center[0] -= 1\r\n                    drawPoint()\r\n                } else if (key === \"ArrowRight\") {\r\n                    center[0] += 1\r\n                    drawPoint()\r\n                }\r\n            }\r\n\r\n            btnBox.onclick = (e) => {\r\n                cursors[cursorKey].list.push({\r\n                    source: image.src,\r\n                    name: nameInput.value || \"自定义\",\r\n                    center: center,\r\n                })\r\n                cursors[cursorKey].index = cursors[cursorKey].list.length - 1\r\n                document.body.removeChild(box)\r\n                document.onkeydown = null\r\n                try { GM_setValue(\"cursorData\", cursors) } catch { }\r\n                callback({\r\n                    source: image.src,\r\n                    name: nameInput.value || \"自定义\",\r\n                    center: center,\r\n                })\r\n            }\r\n\r\n            renderChild(box)\r\n        }\r\n    }\r\n\r\n    uploadArea.addEventListener('dragover', (e) => e.preventDefault())\r\n    uploadArea.addEventListener('drop', (e) => {\r\n        e.preventDefault()\r\n        const { dataTransfer: { files = {} } = {} } = e || {}\r\n        console.log('dropped: ', files)\r\n\r\n        showImage(files[0])\r\n    })\r\n    uploadArea.addEventListener('click', (e) => {\r\n        const input = document.createElement(\"input\")\r\n        input.type = \"file\"\r\n        input.accept = \"image/*\"\r\n        input.onchange = (e) => {\r\n            const file = e.target.files[0]\r\n            // limit size to 128KB\r\n            // if (file.size > 128 * 1024) {\r\n            //     alert(t(\"imageUploadLimit128\"))\r\n            //     return\r\n            // }\r\n            showImage(file)\r\n        }\r\n        input.click()\r\n    })\r\n\r\n    linkInput.addEventListener('paste', (e) => {\r\n        const data = e.clipboardData || window.clipboardData\r\n        const text = data.getData('text')\r\n        const image = new Image()\r\n        image.src = text\r\n        image.onload = (e) => {\r\n            showImage(image)\r\n        }\r\n        image.onerror = (e) => {\r\n            alert(\"Image load failed!\")\r\n            linkInput.value = \"\"\r\n        }\r\n    })\r\n\r\n\r\n\r\n    box.appendChild(closeBtn)\r\n    box.appendChild(uploadArea)\r\n    box.appendChild(linkInput)\r\n\r\n    document.body.appendChild(box)\r\n    closeBtn.onclick = () => { document.body.removeChild(box) }\r\n    renderChild(box)\r\n}\n\n//# sourceURL=webpack:///./index.js?");

          /***/
})

      /******/
});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
        /******/
}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
        /******/
};
/******/
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
      /******/
}
/******/
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for (var key in definition) {
/******/ 				if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
            /******/
}
          /******/
}
        /******/
};
      /******/
})();
/******/
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
      /******/
})();
/******/
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
          /******/
}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
        /******/
};
      /******/
})();
/******/
/************************************************************************/
/******/
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	// This entry module can't be inlined because the eval devtool is used.
/******/ 	var __webpack_exports__ = __webpack_require__("./index.js");
    /******/
    /******/
})()
    ;
})();