Pixel Art Zoom

CACHE BUST UPDATE: Add-on that allows the user to scroll images so they can view pixel art in browser

当前为 2018-03-03 提交的版本,查看 最新版本

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// ==UserScript==
// @name         Pixel Art Zoom
// @namespace    http://tampermonkey.net/
// @version      0.2
// @description  CACHE BUST UPDATE: Add-on that allows the user to scroll images so they can view pixel art in browser
// @author       You
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function () {
    'use strict';
    // Add-on that allows the user to scroll images so they can view pixel art in browser
    var classes = {
        Pixelated: "pixelated-25CVD21ZZ"
    };
    var mouseDown = false;
    var target = undefined;
    var imgContainer = undefined;
    var originalWidth = 0;
    var originalHeight = 0;
    var originalX = 0;
    var originalY = 0;
    var zoom = 1;
    addCSSClasses();
    // Setup event handling for mouse+keyboard
    document.addEventListener("mousedown", function (e) {
        // Only active if the  ctlr key ispressed while clicking an img
        var targetElem = e.target.tagName;
        if ((e.ctrlKey && e.shiftKey) && targetElem === "IMG") {
            mouseDown = true;
            e.preventDefault();
            e.stopPropagation();
            createImgContainer(e);
            zoom += 1;
            resizeImg();
        }
    });
    document.addEventListener("mouseup", function (e) {
        if (mouseDown) {
            e.preventDefault();
            e.stopPropagation();
            mouseDown = false;
        }
    });
    document.addEventListener("wheel", function (e) {
        // check if user has scrolled the mouse wheel(while holding ctrl) over the zoomable image.
        if (e.ctrlKey && imgContainer && e.target.hasAttribute("data-open")) {
            e.preventDefault();
            e.stopPropagation();
            if (e.deltaY < 0) {
                zoom = Math.max(1, zoom - 1);
            }
            else if (e.deltaY > 0) {
                zoom = Math.min(10, zoom + 1);
            }
            resizeImg();
        }
    });
    function addCSSClasses() {
        var head = document.head;
        var newCss = document.createElement("style");
        newCss.type = "text/css";
        newCss.innerHTML = "\n." + classes.Pixelated + "{\n  image-rendering: -webkit-optimize-contrast; \n  image-rendering: -webkit-crisp-edges; \n  image-rendering: -moz-crisp-edges; \n  image-rendering: -o-crisp-edges; \n  image-rendering: pixelated; \n  -ms-interpolation-mode: nearest-neighbor; \n  position:absolute;\n  z-index: 1000000;\n  box-shadow: 0 19px 38px rgba(0, 0, 0, 0.6), 0 15px 12px rgba(0, 0, 0, 0.46);\n  background: #BBBC94;\n}\n";
        head.appendChild(newCss);
    }
    function resizeImg() {
        if (target === undefined || imgContainer === undefined)
            throw new Error("target or imageContainer were undefined");
        // set new image dimensions based on zoom level;
        var targetWidth = zoom * originalWidth;
        var targetHeight = zoom * originalHeight;
        target.style.width = targetWidth + "px";
        target.style.height = targetHeight + "px";
        // try to position the image nicely so it fits on screen without user needing to scroll.
        // Tries to center, but if that isn't possible, then just position at top-left corner
        if (originalX + targetWidth > window.scrollX + window.innerWidth) {
            imgContainer.style.left = window.scrollX + Math.max(0, Math.floor((window.innerWidth - targetWidth) / 2)) + "px";
        }
        else {
            imgContainer.style.left = Math.max(window.scrollX, originalX - (targetWidth - originalWidth) / 2) + "px";
        }
        if (originalY + targetHeight > window.scrollY + window.innerHeight) {
            imgContainer.style.top = window.scrollY + Math.max(0, Math.floor((window.innerHeight - targetHeight) / 2)) + "px";
        }
        else {
            imgContainer.style.top = Math.max(window.scrollY, originalY - (targetHeight - originalHeight) / 2) + "px";
        }
    }
    function createImgContainer(e) {
        if (imgContainer !== undefined)
            return; // avoid creating duplicates
        target = e.target;
        // create container for image that is absolutely positioned
        imgContainer = document.createElement("div");
        var offset = cumulativeOffset();
        imgContainer.style.top = offset.top + "px";
        imgContainer.style.left = offset.left + "px";
        imgContainer.className = classes.Pixelated; // sets rendering mode to crisp pixels.
        // created a copy of the image we want to scroll since we need to modify its properties for zooming.
        target = target.cloneNode(true);
        target.removeAttribute("style"); // remove any cruft that modifies the size, padding, etc.
        target.removeAttribute("class"); // same
        target.removeAttribute("height"); // same
        target.removeAttribute("width"); // same
        // Add a custom attribute so we can differentiate between events on the zoomable image and others
        target.setAttribute("data-open", "active");
        /// save some of the original image's properties
        originalWidth = target.width;
        originalHeight = target.height;
        originalX = offset.left;
        originalY = offset.top;
        // And now add the container and image to the DOM
        imgContainer.appendChild(target);
        // It doesn't matter that we insert it as the first element, but is easier for debugging.
        document.body.insertBefore(imgContainer, document.body.firstElementChild);
        // Focus the image and add event to clean up when user clicks away from image
        target.setAttribute("tabindex", "0"); // Needed so the image can be focused.
        target.addEventListener("blur", function () {
            destroyImgContainer();
        }, true);
        target.focus(); // Can only be called AFTER the img is added to the DOM
        /** Find the position of an element relative to the top-left corner of document */
        function cumulativeOffset() {
            var bbox = target.getBoundingClientRect();
            // damn margin
            var style = window.getComputedStyle(target);
            var marginLeft = parseInt(style.marginLeft.replace(" px", ""), 10);
            var marginTop = parseInt(style.marginTop.replace(" px", ""), 10);
            return {
                left: bbox.left + window.scrollX - marginLeft,
                top: bbox.top + window.scrollY - marginTop
            };
        }
    }
    function destroyImgContainer() {
        if (imgContainer === undefined)
            return;
        document.body.removeChild(imgContainer);
        // reset to initial state
        target = undefined;
        imgContainer = undefined;
        zoom = 1;
    }

})();