UNPKG

@kidoki/vue-mosaic

Version:

Vue module, which is used to convert html content into mosaic.

144 lines (106 loc) 3.67 kB
(function (window, undefined) { 'use strict'; var TWO_PI = Math.PI * 2 var QUARTER_PI = Math.PI * 0.25 function isArray(obj) { return Object.prototype.toString.call(obj) === "[object Array]" } function isObject(obj) { return Object.prototype.toString.call(obj) === "[object Object]" } var console = window.console var canvas = document.createElement('canvas') var isCanvasSupported = canvas.getContext && canvas.getContext('2d') if (!isCanvasSupported) { return } function ClosePixelation(img, options) { this.img = img var canvas = this.canvas = document.createElement('canvas') this.ctx = canvas.getContext('2d') canvas.className = img.className canvas.id = img.id this.render(options) img.parentNode.replaceChild(canvas, img) } ClosePixelation.prototype.render = function (options) { this.options = options var w = this.width = this.canvas.width = this.img.width var h = this.height = this.canvas.height = this.img.height this.ctx.drawImage(this.img, 0, 0) try { this.imgData = this.ctx.getImageData(0, 0, w, h).data } catch (error) { if (console) { console.error(error) } return } this.ctx.clearRect(0, 0, w, h) for (var i = 0, len = options.length; i < len; i++) { this.renderClosePixels(options[i]) } } ClosePixelation.prototype.renderClosePixels = function (opts) { var w = this.width var h = this.height var ctx = this.ctx var imgData = this.imgData var res = opts.resolution || 16 var size = opts.size || res var alpha = opts.alpha || 1 var offset = opts.offset || 0 var offsetX = 0 var offsetY = 0 var cols = w / res + 1 var rows = h / res + 1 var halfSize = size / 2 var diamondSize = size / Math.SQRT2 var halfDiamondSize = diamondSize / 2 if (isObject(offset)) { offsetX = offset.x || 0 offsetY = offset.y || 0 } else if (isArray(offset)) { offsetX = offset[0] || 0 offsetY = offset[1] || 0 } else { offsetX = offsetY = offset } var row, col, x, y, pixelY, pixelX, pixelIndex, red, green, blue, pixelAlpha for (row = 0; row < rows; row++) { y = (row - 0.5) * res + offsetY pixelY = Math.max(Math.min(y, h - 1), 0) for (col = 0; col < cols; col++) { x = (col - 0.5) * res + offsetX pixelX = Math.max(Math.min(x, w - 1), 0) pixelIndex = (pixelX + pixelY * w) * 4 red = imgData[pixelIndex + 0] green = imgData[pixelIndex + 1] blue = imgData[pixelIndex + 2] pixelAlpha = alpha * (imgData[pixelIndex + 3] / 255) ctx.fillStyle = 'rgba(' + red + ',' + green + ',' + blue + ',' + pixelAlpha + ')' switch (opts.shape) { case 'circle': ctx.beginPath() ctx.arc(x, y, halfSize, 0, TWO_PI, true) ctx.fill() ctx.closePath() break case 'diamond': ctx.save() ctx.translate(x, y) ctx.rotate(QUARTER_PI) ctx.fillRect(-halfDiamondSize, -halfDiamondSize, diamondSize, diamondSize) ctx.restore() break default: ctx.fillRect(x - halfSize, y - halfSize, size, size) } } } } HTMLImageElement.prototype.closePixelate = function (options) { return new ClosePixelation(this, options) } window.ClosePixelation = ClosePixelation })(window);