blob: 3b01fef8fae64019b83bc5cd64b05dc2d3406cfa [file] [log] [blame]
<!-- The <zoom-sk> custom element declaration.
The zoom-sk element presents a zoomed in view of a source img element.
Attributes:
source - The id of an img element to present a zoom for.
x, y - The point to center the zoom on. The units are in the natural size
of the source image.
pixels - The number of pixels to display in the horizontal direction.
Events:
zoom-point - This event is generated whenever the zoom moves. The detail
of the event contains the values for the color:
{
x: 100,
y: 100,
r: 0xff,
g: 0xef,
b: 0xd5,
a: 0xff,
rgb: "rbg(255, 239, 213, 1.0)",
hex: "#ffefd5ff",
}
zoom-loaded - This event is generated whenever the zoom has finished
updating the zoomed view after an image load.
Methods:
getImageData() - Returns the image data of the image wrapped by this zoom-sk element.
getPixelColor(x,y) - Returns the color of the pixel as an array in RGBA format.
-->
<link rel="import" href="/res/imp/bower_components/iron-resizable-behavior/iron-resizable-behavior.html">
<dom-module id="zoom-sk">
<style type="text/css" media="screen">
#copy {
display: none;
}
#zoom {
margin: 0;
padding: 0;
}
:host {
padding: 0;
}
</style>
<template>
<canvas id=zoom width=10 height=10></canvas>
<canvas id=copy width=10 height=10></canvas>
</template>
<script>
Polymer({
is: 'zoom-sk',
behaviors: [
// Listen for resize events and change the size of the #zoom canvas accordingly.
Polymer.IronResizableBehavior
],
listeners: {
'iron-resize': '_onIronResize'
},
attached: function() {
this.async(this.notifyResize, 1);
},
properties: {
source: {
type: String,
value: "",
},
x: {
type: Number,
value: 0,
reflectToAttribute: true,
observer: "_drawZoom",
},
y: {
type: Number,
value: 0,
reflectToAttribute: true,
observer: "_drawZoom",
},
pixels: {
type: Number,
value: 10,
reflectToAttribute: true,
observer: "_pixelResize",
},
},
ready: function () {
// Grab the img we are zooming from.
this._img = $$$('#' + this.source, this._findParent());
this._img.addEventListener('load', function() {
this._onIronResize();
this._cloneImage();
this.dispatchEvent(new CustomEvent('zoom-loaded', { bubbles: true }));
}.bind(this));
this._cloneImage();
// The canvas context we are drawing the zoomed pixels on.
this.ctx = this.$.zoom.getContext('2d');
},
getImageData: function() {
var c = this.$.copy;
return c.getContext('2d').getImageData(0, 0, c.width, c.height);
},
getPixelColor: function(x,y) {
return this.$.copy.getContext('2d').getImageData(x, y, 1, 1).data;
},
_findParent: function() {
var p = this.parentNode;
while (p.parentNode != null) {
p = p.parentNode;
}
return p
},
_onIronResize: function() {
this.$.zoom.width = this.parentElement.clientWidth;
this.$.zoom.height = this.parentElement.clientWidth;
this._pixelResize();
},
_pixelResize: function() {
this.pixelSize = Math.floor(this.$.zoom.width/this.pixels);
this._drawZoom();
},
_cloneImage: function() {
this.$.copy.width = this._img.naturalWidth;
this.$.copy.height = this._img.naturalHeight;
this.$.copy.getContext('2d').drawImage(this._img, 0, 0, this._img.naturalWidth, this._img.naturalHeight);
this._drawZoom();
},
_drawZoom: function () {
if (!this.ctx) {
return
}
this.ctx.clearRect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
var dx = this.pixelSize;
var dy = this.pixelSize;
this.ctx.lineWidth = 1;
this.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 = this.$.copy.getContext('2d').getImageData(this.x - this.pixels/ 2, this.y - this.pixels / 2, this.pixels, this.pixels).data;
for (var x = 0; x < this.pixels; x++) {
for (var y = 0; y < this.pixels; y++) {
var offset = (y * this.pixels + x) * 4;
// Offset into the colors array.
var colorRGB = sk.colorRGB(colors, offset, true);
var colorRGBStyle = sk.colorRGB(colors, offset, false);
this.set("ctx.fillStyle", colorRGBStyle);
this.ctx.fillRect(x * dx, y * dy, dx - 1, dy - 1);
// Box one selected pixel with its rgba values.
if (x == this.pixels / 2 && y == this.pixels / 2) {
this.ctx.strokeRect(x * dx - 0.5, y * dy - 0.5, dx, dy);
var detail = {
x: this.x,
y: this.y,
r: colors[offset+0],
g: colors[offset+1],
b: colors[offset+2],
a: colors[offset+3],
rgb: colorRGB,
hex: sk.colorHex(colors, offset),
};
var evt = new CustomEvent('zoom-point', {
detail: detail,
bubbles: true
});
this.dispatchEvent(evt);
}
}
}
},
});
</script>
</dom-module>