Skip to content

Instantly share code, notes, and snippets.

@pixelass
Created April 11, 2016 11:21
Show Gist options
  • Save pixelass/b63286ed96c898cd9d009cb0640a2c9b to your computer and use it in GitHub Desktop.
Save pixelass/b63286ed96c898cd9d009cb0640a2c9b to your computer and use it in GitHub Desktop.
new Pixel();
"use strict";
// requestAnimationFrame() shim by Paul Irish
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
window.requestAnimFrame = function () {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function ( /* function */callback, /* DOMElement */element) {
window.setTimeout(callback, 1000 / 60);
};
}();
/**
* Behaves the same as setInterval except uses requestAnimationFrame() where possible for better performance
* @param {function} fn The callback function
* @param {int} delay The delay in milliseconds
*/
window.requestInterval = function (fn, delay) {
if (!window.requestAnimationFrame && !window.webkitRequestAnimationFrame && !(window.mozRequestAnimationFrame && window.mozCancelRequestAnimationFrame) && // Firefox 5 ships without cancel support
!window.oRequestAnimationFrame && !window.msRequestAnimationFrame) return window.setInterval(fn, delay);
var start = new Date().getTime(),
handle = new Object();
function loop() {
var current = new Date().getTime(),
delta = current - start;
if (delta >= delay) {
fn.call();
start = new Date().getTime();
}
handle.value = requestAnimFrame(loop);
};
handle.value = requestAnimFrame(loop);
return handle;
};
/**
* Behaves the same as clearInterval except uses cancelRequestAnimationFrame() where possible for better performance
* @param {int|object} fn The callback function
*/
window.clearRequestInterval = function (handle) {
window.cancelAnimationFrame ? window.cancelAnimationFrame(handle.value) : window.webkitCancelAnimationFrame ? window.webkitCancelAnimationFrame(handle.value) : window.webkitCancelRequestAnimationFrame ? window.webkitCancelRequestAnimationFrame(handle.value) : /* Support for legacy API */
window.mozCancelRequestAnimationFrame ? window.mozCancelRequestAnimationFrame(handle.value) : window.oCancelRequestAnimationFrame ? window.oCancelRequestAnimationFrame(handle.value) : window.msCancelRequestAnimationFrame ? window.msCancelRequestAnimationFrame(handle.value) : clearInterval(handle);
};
class Pixel {
constructor(props,target){
this.props = props;
this.target = target;
this.createReader();
this.createInput();
this.generateType = props.type || 'canvas';
this.downScale = props.scale || 32;
this.pixelSize = (props.pixel || 1);
this.pixelShape = (props.shape || 'square');
this.src(props.src);
}
createReader(){
this.Reader = document.createElement('canvas');
this.reader = this.Reader.getContext('2d');
}
updateReader(){
if (!this.loaded) return;
this.Reader.height = this.height;
this.Reader.width = this.width;
this.reader.drawImage(this.Input,0,0,this.width,this.height);
this.getColorArray();
this.draw();
}
draw(){
let drawing = this.generateByType(this.generateType);
this.target.innerHTML = '';
this.target.appendChild(drawing);
}
onLoad(e){
this.loaded = true;
this.setSize();
this.updateReader();
}
createInput(){
this.Input = document.createElement('img');
this.Input.crossOrigin = 'Anonymous';
this.Input.onload = this.onLoad.bind(this);
}
src(src){
this.loaded = false;
this.Input.src = src;
}
pixel(size){
this.pixelSize = size;
this.updateReader();
}
type(type){
this.generateType = type;
this.updateReader();
}
scale(scale){
this.downScale = scale;
this.setSize();
this.updateReader();
}
shape(shape){
this.pixelShape = shape;
this.updateReader();
}
resize(scale, pixel) {
this.downScale = scale;
this.pixelSize = pixel;
this.setSize();
this.updateReader();
}
setSize(){
this.height = this.Input.height/this.Input.width*this.downScale;
this.width = this.downScale;
this.Input.height = this.height;
this.Input.width = this.width;
}
getColorArray(){
let data = [];
if (this.Reader.height > 0) {
data = this.reader.getImageData(0,0,this.width,this.height).data;
}
let colorArray = [];
for (let i = 0; i < data.length; i += 4) {
let r = data[i];
let g = data[i + 1];
let b = data[i + 2];
let a = data[i + 3]/255;
let rgba = [r,g,b,a].join(',');
if (a === 0) {
colorArray.push('transparent');
} else {
colorArray.push(`rgba(${rgba})`);
}
}
this.colorArray = colorArray;
this.generateByType(this.generateType);
}
drawCanvas(){
let C = document.createElement('canvas');
let $ = C.getContext('2d');
C.height = this.height*this.pixelSize;
C.width = this.width*this.pixelSize;
let n = -1;
for (let i = 0; i < this.colorArray.length; i++ ) {
$.fillStyle = this.colorArray[i];
let x = i%this.width;
if (x === 0) {
++n;
}
if (this.colorArray[i] !== 'transparent') {
let y = n;
if (this.pixelShape === 'circle') {
$.beginPath();
$.arc((x + .5)*this.pixelSize, (y + .5)*this.pixelSize, this.pixelSize/2, 0, 2 * Math.PI);
$.closePath();
$.fill();
} else {
$.fillRect(x*this.pixelSize,y*this.pixelSize,this.pixelSize,this.pixelSize);
}
}
}
return C;
}
drawSVG(){
let xmlns = 'http://www.w3.org/2000/svg';
let SVG = document.createElementNS(xmlns,'svg');
SVG.setAttributeNS (null, 'viewBox', `0 0 ${[this.width, this.height].join(' ')}`);
SVG.setAttributeNS (null, 'height', this.height*this.pixelSize);
SVG.setAttributeNS (null, 'width', this.width*this.pixelSize);
let n = -1;
for (let i = 0; i < this.colorArray.length; i++ ) {
let x = i%this.width;
if (x === 0) {
++n;
}
if (this.colorArray[i] !== 'transparent') {
let y = n;
if (this.pixelShape === 'circle') {
let circle = document.createElementNS(xmlns,'circle');
circle.setAttributeNS (null, 'fill', this.colorArray[i]);
circle.setAttributeNS (null, 'cx', (x + .5));
circle.setAttributeNS (null, 'cy', (y + .5));
circle.setAttributeNS (null, 'r', .5);
SVG.appendChild(circle);
} else {
let rect = document.createElementNS(xmlns,'rect');
rect.setAttributeNS (null, 'fill', this.colorArray[i]);
rect.setAttributeNS (null, 'x', x);
rect.setAttributeNS (null, 'y', y);
rect.setAttributeNS (null, 'width', 1);
rect.setAttributeNS (null, 'height', 1);
SVG.appendChild(rect);
}
}
}
return SVG;
}
drawShadow(){
let shadow = [];
let S = document.createElement('div');
S.style.margin = `${-1*this.pixelSize}px ${this.width*this.pixelSize}px ${this.height*this.pixelSize}px ${-1*this.pixelSize}px`;
S.style.width = `${this.pixelSize}px`;
S.style.height = `${this.pixelSize}px`;
if (this.pixelShape === 'circle') {
S.style.borderRadius = '100%';
}
let n = 0;
for (let i = 0; i < this.colorArray.length; i++ ) {
let x = (i%this.width + 1)*this.pixelSize;
if (i%this.width === 0) {
++n;
}
if (this.colorArray[i] !== 'transparent') {
let y = n*this.pixelSize;
shadow.push(`${x}px ${y}px 0 ${this.colorArray[i]}`)
}
}
S.style.boxShadow = shadow.join(',').replace(/"/g,'');
return S;
}
drawIMG(){
let C = this.drawCanvas();
let I = document.createElement('img');
let dataURL = C.toDataURL('image/png');;
I.src = dataURL;
return I;
}
generateByType(type){
if (type === 'canvas') {
return this.drawCanvas();
} else if (type === 'svg') {
return this.drawSVG();
} else if (type === 'img') {
return this.drawIMG();
} else if (type === 'shadow') {
return this.drawShadow();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment