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 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 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;
    }

})();