blob: 33aab9b44c2705e10ff9980228ec1262dca45619 [file] [log] [blame]
<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>