| <!-- 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> |