<script type="text/javascript" charset="utf-8"> /** * A reusable HTML Import to enable zooming on images. * * To use, simply include this HTML Import and add the class 'zoom' to any * images you want zoomable. * * <link rel='import' type='text/html' href='/res/imp/zoom.html'> * * <img src="http://..." class="zoom"/> * * Any number of images on a page can be zoomable. * * If you want to display the rgb colors of the pixel at the center of the * zoom then add an id of 'zoomHex' to any element that supports * textContent, such as a div, p, span, etc. * * <p id=zoomHex></p> * * Note that HTML Imports need to be polyfilled in the near term. */ (function () { function onLoad() { var PIXELS = 20; // The number of pixels in width and height in a zoom. var clientX = 0; var clientY = 0; var lastClientX = 0; var lastClientY = 0; var ctx = null; // The 2D canvas context of the zoom. var currentImage = null; // The img node we are zooming for, otherwise null. var hex = document.getElementById('zoomHex'); var canvasCopy = null; function zoomMove(e) { clientX = e.clientX; clientY = e.clientY; } function zoomMouseDown(e) { e.preventDefault(); // Only do zooming on the primary mouse button. if (e.button != 0) { return } currentImage = e.target; clientX = e.clientX; clientY = e.clientY; lastClientX = clientX-1; lastClientY = clientY-1; document.body.style.cursor = 'crosshair'; canvas = document.createElement('canvas'); canvas.width = 1024; canvas.height = 1024; canvas.classList.add('zoomCanvas'); ctx = canvas.getContext('2d'); ctx.imageSmoothingEnabled = false; this.parentNode.insertBefore(canvas, this); // Copy the image over to a canvas so we can read RGBA values for each point. if (hex) { canvasCopy = document.createElement('canvas'); canvasCopy.width = currentImage.width; canvasCopy.height = currentImage.height; canvasCopy.id = 'zoomCopy'; canvasCopy.getContext('2d').drawImage(currentImage, 0, 0, currentImage.width, currentImage.height); this.parentNode.insertBefore(canvasCopy, this); } document.body.addEventListener('pointermove', zoomMove, true); document.body.addEventListener('pointerup', zoomFinished); document.body.addEventListener('pointerleave', zoomFinished); // Kick off the drawing. setTimeout(drawZoom, 1); } function hexify(i) { var s = i.toString(16).toUpperCase(); // Pad out to two hex digits if necessary. if (s.length < 2) { s = '0' + s; } return s; } function drawZoom() { if (currentImage) { // Only draw if the mouse has moved from the last time we drew. if (lastClientX != clientX || lastClientY != clientY) { ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); var x = clientX - currentImage.x; var y = clientY - currentImage.y; var dx = Math.floor(ctx.canvas.width/PIXELS); var dy = Math.floor(ctx.canvas.height/PIXELS); ctx.lineWidth = 1; ctx.strokeStyle = '#000'; // Draw out each pixel as a rect on the target canvas, as this works around // FireFox doing a blur as it copies from one canvas to another. var colors = canvasCopy.getContext('2d').getImageData(x, y, PIXELS, PIXELS).data; for (var i=0; i<PIXELS; i++) { for (var j=0; j<PIXELS; j++) { var offset = (j*PIXELS+i)*4; // Offset into the colors array. ctx.fillStyle = 'rgba(' + colors[offset] + ', ' + colors[offset+1] + ', ' + colors[offset+2] + ', ' + colors[offset+3]/255.0 + ')'; ctx.fillRect(i*dx, j*dy, dx-1, dy-1); // Box and label one selected pixel with its rgba values. if (hex && i==PIXELS/2 && j == PIXELS/2) { ctx.strokeRect(i*dx, j*dy, dx-1, dy-1); hex.textContent = 'rgba(' + colors[offset] + ', ' + colors[offset+1] + ', ' + colors[offset+2] + ', ' + colors[offset+3] + ') ' + hexify(colors[offset]) + hexify(colors[offset+1]) + hexify(colors[offset+2]) + hexify(colors[offset+3]); } } } lastClientX = clientX; lastClientY = clientY; } setTimeout(drawZoom, 1000/30); } } function zoomFinished() { currentImage = null; if (hex) { hex.textContent = ''; } document.body.style.cursor = 'default'; ctx.canvas.parentNode.removeChild(ctx.canvas); canvasCopy.parentNode.removeChild(canvasCopy); document.body.removeEventListener('pointermove', zoomMove, true); document.body.removeEventListener('pointerup', zoomFinished); document.body.removeEventListener('pointerleave', zoomFinished); } var zoomables = document.body.querySelectorAll('.zoom'); for (var i=0; i<zoomables.length; i++) { zoomables[i].addEventListener('pointerdown', zoomMouseDown); } } // If loaded via HTML Imports then DOMContentLoaded will be long done. if (document.readyState != "loading") { onLoad(); } else { this.addEventListener('DOMContentLoaded', onLoad); } })(); </script> <style type="text/css" media="screen"> .zoom { cursor: crosshair; } .zoomCanvas { position: absolute; width: vmin; height: vmin; top: 3em; right: 1em; z-index: -1; } #zoomCopy { display: none; } #zoomHex { text-shadow: 1px 1px #eee; } </style>