Skip to content

Instantly share code, notes, and snippets.

@pastuh
Last active February 10, 2019 19:40
Show Gist options
  • Save pastuh/385dc70adc9cf3c514c1d899bea3553a to your computer and use it in GitHub Desktop.
Save pastuh/385dc70adc9cf3c514c1d899bea3553a to your computer and use it in GitHub Desktop.
Playful Palette - Color mixing
(function(){
//DOM Library V0.0.1
var fn = {};
$js.libraryAdd('hasClass', function(a, b){
var c = (a.getAttribute('class') || '').split(/\s+/g);
for(var d in c){
if(c[d] == b){
return true;
}
}
return false;
}, 'static');
$js.libraryAdd('addClass', function(a, b){
if(this.hasClass(a, b) == false){
var c = (a.getAttribute('class') || '').split(/\s+/g);
c.push(b);
a.setAttribute('class', c.join(' '));
}
return false;
}, 'static');
$js.libraryAdd('removeClass', function(a, b){
if(this.hasClass(a, b) == true){
var c = (a.getAttribute('class') || '').split(/\s+/g),
d = new Array();
for(var e in c){
if(c[e] != b){
d.push(c[e]);
}
}
a.setAttribute('class', d.join(' '));
}
return false;
}, 'static');
$js.libraryAdd('matches', function(a, b){
if(a.nodeType != 1){
console.log('ok', a.nodeType);
return false;
}else if(!b){
return true;
}
var c = b.split(/[,\s]+/g);
for(var d = 0; d < c.length; d += 1){
var e = c[d];
if(e.substring(0, 1) == '#'){
throw 'not supported:' + e;
}else if(e.substring(0, 1) == '.'){
if(this.hasClass(a, e.substring(1))){
return true;
}
}else{
if(a.tagName.toUpperCase() == e.toUpperCase()){
return true;
}
}
}
return false;
}, 'static');
$js.libraryAdd('html', function(a){
var b = this.parser.parseFromString('<div xmlns="http://www.w3.org/1999/xhtml">'+a+'</div>','text/xml').firstChild,
c = [];
while(b.firstChild){
c.push(b.firstChild);
b.removeChild(b.firstChild);
}
c.__proto__ = fn;
return c;
}, 'static');
$js.libraryAdd('pxToNum', function(a){
if(!a || typeof a != 'string' || a.length <= 2 || a.charAt(a.length - 2) != 'p' || a.charAt(a.length - 1) != 'x'){
return 0;
}
return +a.substring(0, a.length - 2);
}, 'static');
fn.attr = function(a){
if(arguments.length == 1){
if(typeof a == 'string'){
return this.getAttribute(a);
}
for(var b in a){
this.setAttribute(b, a[b]);
}
}else if(arguments.length == 2){
this.setAttribute(a, arguments[1]);
}
return this;
}
fn.prop = function(a){
if(arguments.length == 1){
if(typeof a == 'string'){
return this[a];
}
for(var b in a){
this[b] = a[b];
}
}else if(arguments.length == 2){
this[a] = arguments[1];
}
return this;
}
fn.css = function(a){
if(arguments.length == 1){
if(typeof a == 'string'){
return this.style[a];
}
for(var b in a){
this.style[b] = a[b];
}
}else if(arguments.length == 2){
this.style[a] = arguments[1];
}
return this;
}
fn.val = function(){
if(arguments.length == 0){
return this.value || '';
}else if(arguments.length == 1){
this.value = arguments[0];
}
return this;
}
fn.on = function(a, b){
var c = a.split(/\s+/g);
for(var d = 0; d < c.length; d += 1){
this.addEventListener(c[d], b);
}
return this;
}
fn.off = function(a, b){
var c = a.split(/\s+/g);
for(var d = 0; d < c.length; d += 1){
this.removeEventListener(c[d], b);
}
return this;
}
fn.offset = function(){
var a = {left:0, top:0},
b = null;
for(var c = this; c.parentNode != null; c = c.parentNode){
if(c.offsetParent != null){
b = c; break;
}
}
if(b != null){
for(var c = b; c.offsetParent != null; c = c.offsetParent){
a.left += c.offsetLeft;
a.top += c.offsetTop;
}
}
for(var c = this; c.parentNode != null && c != document.body; c = c.parentNode){
a.left -= c.scrollLeft;
a.top -= c.scrollTop;
}
return a;
}
fn.append = function(a){
if(typeof a == 'string'){
a = $js.html(a);
}
for(var b = 0; b < a.length; b += 1){
this.appendChild(a[b]);
}
return this;
}
fn.prepend = function(a){
if(typeof a == 'string'){
a = $js.html(a);
}
for(var b = 0; b < a.length; b += 1){
if(this.firstChild){
this.insertBefore(a[b], this.firstChild);
}else{
this.appendChild(a[b]);
}
}
return this;
}
fn.insertBefore = function(a){
var b = a[0];
b.parentNode.insertBefore(this, b);
return this;
}
fn.insertAfter = function(a){
var b = a[0];
if(b.nextSibling){
b.parentNode.insertBefore(this, b.nextSibling);
}else{
b.parentNode.appendChild(this);
}
return this;
}
fn.remove = function(){
if(this.parentNode){
this.parentNode.removeChild(this);
}
return this;
}
fn.detach = function(){
if(this.parentNode){
this.parentNode.removeChild(this);
}
return this;
}
fn.parent = function(){
return DOM(this.parentNode);
}
fn.closest = function(a){
for(var b = this; b != null; b = b.parentNode){
if($js.matches(b, a)){
return $DOM(b);
}
}
return DOM();
}
fn.children = function(a){
var b = [],
c = this.childNodes;
for(var d = 0; d < c.length; d += 1){
if($js.matches(c.item(d), a)){
b.push(c.item(d));
}
}
b.__proto__ = fn;
return b;
}
fn.index = function(a){
return Array.prototype.indexOf.call(DOM(this).parent().children(a), this);
}
fn.find = function(a){
var b = [],
c = this.querySelectorAll(a);
for(var d = 0; d < c.length; d += 1){
b.push(c.item(d));
}
b.__proto__ = fn;
return b;
}
fn.clone = function(){return DOM(this.cloneNode(true));}
fn.focus = function(){this.focus(); return this;}
fn.select = function(){this.select(); return this;}
fn.submit = function(){this.submit(); return this;}
fn.scrollLeft = function(){
if(arguments.length == 0){
return this.scrollLeft;
}
this.scrollLeft = arguments[0];
return this;
}
fn.scrollTop = function(){
if(arguments.length == 0){
return this.scrollTop;
}
this.scrollTop = arguments[0];
return this;
}
fn.html = function(){
if(arguments.length == 0){
return this.innerHTML;
}
this.innerHTML = arguments[0];
return this;
}
fn.text = function(){
if(typeof this.textContent != 'undefined'){
if(arguments.length == 0){
return this.textContent;
}
this.textContent = arguments[0];
return this;
}else{
if(arguments.length == 0){
return this.innerText;
}
this.innerText = arguments[0];
return this;
}
}
fn.outerWidth = function(a){
var b = this.offsetWidth;
if(a){
var c = window.getComputedStyle(this, null);
return b + $js.pxToNum(c.marginLeft) + $js.pxToNum(c.marginRight);
}
return b;
}
fn.innerWidth = function(){
var a = window.getComputedStyle(this, null);
return this.offsetWidth - $js.pxToNum(a.borderLeftWidth) - $js.pxToNum(a.borderRightWidth);
}
fn.width = function(){
if(this == window){
return this.innerWidth;
}
var a = window.getComputedStyle(this, null);
return this.offsetWidth - $js.pxToNum(a.borderLeftWidth) - $js.pxToNum(a.borderRightWidth) - $js.pxToNum(a.paddingLeft) - $js.pxToNum(a.paddingRight);
}
fn.outerHeight = function(a){
var b = this.offsetHeight;
if(a){
var c = window.getComputedStyle(this, null);
return b + $js.pxToNum(c.marginTop) + $js.pxToNum(c.marginBottom);
}
return b;
}
fn.innerHeight = function(){
var a = window.getComputedStyle(this, null);
return this.offsetHeight - $js.pxToNum(a.borderTopWidth) - $js.pxToNum(a.borderBottomWidth);
}
fn.height = function(){
if(this == window){
return this.innerHeight;
}
var a = window.getComputedStyle(this, null);
return this.offsetHeight - $js.pxToNum(a.borderTopWidth) - $js.pxToNum(a.borderBottomWidth) - $js().pxToNum(a.paddingTop) - $js.pxToNum(a.paddingBottom);
}
fn.getSize = function(){
var a = (this.width || this.innerWidth || this.clientWidth),
b = (this.height || this.innerHeight || this.clientHeight);
return {width: a, height: b}
}
fn.addClass = function(a){
$js.addClass(this, a);
return this;
}
fn.removeClass = function(a){
$js.removeClass(this, a);
return this;
}
fn.hasClass = function(a){
return $js.hasClass(this, a);
}
fn.getPath = function(){
var a = String(this.tagName).toLocaleLowerCase();
if(this.id){
a += '#'+this.id;
}else if(this.classList.length > 0){
for(var b = 0; b<this.classList.length; b++){
a += '.'+this.classList[b];
}
}
return a;
}
fn.getAllPath = function(){
var a = [], b = this.parentNode;
a.push(DOM(this).getPath());
while(b){
if(!b.tagName || b.tagName == 'BODY' || b.tagName == 'HTML'){break;}
var c = String(b.tagName).toLocaleLowerCase();
if(b.id){
c += '#'+b.id;
b=b.parentNode;
}else if(b.classList && b.classList.length > 0){
for(var d = 0; d<b.classList.length; d++){
c += '.'+b.classList[d];
}
}
a.unshift(c);
b=b.parentNode;
}
return a.join(" > ");
}
$js.each(fn, function(a, b){
fn[a] = function(){
var c = null;
for(var d = 0; d < this.length; d += 1){
var e = this[d],
g = b.apply(e, arguments);
if(e !== g){
if(g != null && g.__proto__ == fn){
if(c == null){c = [];}
c = c.concat(g);
}else{
return g;
}
}
}
if(c != null){
c.__proto__ = fn;
return c;
}
return this;
};
});
fn = $js.extend(fn, {
each : function(a){
for(var b = 0; b < this.length; b += 1){
a.call(this[b], b);
}
return this;
},
getDom : function(){
return this.length > 0? this[0] : null;
},
first : function(){
return DOM(this.length > 0? this[0] : null);
},
last : function(){
return DOM(this.length > 0? this[this.length - 1] : null);
}
});
$js.libraryAdd('DOM', function(a){
if(typeof a == 'string'){
if(a.charAt(0) == '<'){
return $js.html(a);
}else{
var b = document.querySelectorAll(a),
c = [];
for(var d = 0; d < b.length; d += 1){
c.push(b.item(d));
}
c.__proto__ = fn;
return c;
}
}else if(typeof a == 'object' && a != null){
if(a.__proto__ == fn){
return a;
}else{
var c = [];
c.push(a);
c.__proto__ = fn;
return c;
}
}else{
var c = [];
c.__proto__ = fn;
return c;
}
});
}());
<div id="thisCan"></div>
window.$js = (function(){
var init = {};
init.libraryAdd = function(name, calback, type){
var fun, method;
if(type === 'static'){
fun = init[name] = calback;
}else{
fun = window[name] = calback;
}
method = function(fun){
fun.extend = function(a, b){
if(a instanceof Object){
for(var c in a){
this.extend(c, a[c]);
}
return this;
}else if(typeof a == 'string' && typeof b == 'function'){
var c = fun.prototype[a] = b;
return method(c);
}
}
return fun;
}
return method(fun);
}
init.libraryAdd('extend', function(a, b){
for(var c in b){
if(typeof a[c] == 'object' || a[c] instanceof Array){
a[c] = this.extend(a[c], b[c]);
}else{
a[c] = b[c];
}
}
return a;
}, 'static');
init.libraryAdd('each', function(a, b){
if(typeof a.splice == 'function'){
for(var c = 0; c < a.length; c += 1){
b(c, a[c]);
}
}else{
for(var d in a){
b(d, a[d]);
}
}
}, 'static');
init.libraryAdd('grep', function(a, b){
var c = [];
for(var d = 0; d < a.length; d += 1){
var e = a[d];
if(b(e)){c.push(e);}
}
return c;
}, 'static');
init.libraryAdd('parser', (function(){return new window.DOMParser()}()), 'static');
return init;
}());
(function () {
function bubble(x, y, color, r) {
this.x = x;
this.y = y;
this.color = Array.isArray(color) ? color : [Math.round(Math.random() * 255), Math.round(Math.random() * 255), Math.round(Math.random() * 255)];
this.r = typeof r == "number" ? r : 300;
}
bubble.prototype.move = function (x, y) {
this.x = x;
this.y = y;
return this;
};
bubble.prototype.ray = function (r) {
this.r = r;
return this;
};
bubble.prototype.containThisPosition = function (x, y) {
return this.x - this.r < x && this.x + this.r > x && this.y - this.y < y && this.y + this.r > y;
}
function blend() {
this.paints = [];
}
blend.prototype.add = function (color) {
var a = new bubble(10, 10, color);
this.paints.push(a);
return a;
}
function getFragColor(x, y, blend) {
blend = !blend.paints || !(blend.paints instanceof Array) ? [] : blend.paints;
if (blend.length == 0) { return [255, 255, 255]; }
var b2 = 0.44, b3 = b2 * b2, b4 = b3 * b2, f = 0, p = 1, c = [0, 0, 0];
for (var i = 0; i < blend.length; i++) {
if (!blend[i].containThisPosition(x, y)) { continue; }
var bub = blend[i], r = bub.r,
dx = (bub.x - x), dy = (bub.y - y),
d2 = (dx * dx + dy * dy) / r / r;
if (d2 <= b2) {
var d4 = d2 * d2, d5 = 1 - (4 * d4 * d2 / b4 - 17 * d4 / b3 + 22 * d2 / b2) / 9;
c[0] = (c[0] + bub.color[0] * d5);
c[1] = (c[1] + bub.color[1] * d5);
c[2] = (c[2] + bub.color[2] * d5);
f += d5;
}
}
var max = 0.5, border = 0.02;
if (f < max) {
return [255, 255, 255];
} else {
p = f < (max + border) ? Math.min(Math.max(((f - max) / (border)), 0), 1) : 1;
c[0] = Math.round((1 - p) * 255 + p * (c[0] / f));
c[1] = Math.round((1 - p) * 255 + p * (c[1] / f));
c[2] = Math.round((1 - p) * 255 + p * (c[2] / f));
return c;
}
}
var pp = window.Palette = function () {
this.paints = new blend();
}
pp.prototype.addPaint = function (c) {
var a = this.paints.add(c);
return a;
}
pp.prototype.getPick = function (x, y) {
return getFragColor(x, y, this.paints);
}
pp.prototype.render = function (w, h) {
var p = this.paints, x = 0, y = 0, img = document.createElement('canvas').getContext('2d').createImageData(w, h), d = img.data;
for (var i = 0; i < d.length; i += 4) {
var x = (i / 4) % w;
y = x == 0 ? y + 1 : y;
var c = getFragColor(x, y, p);
d[i] = c[0]; d[i + 1] = c[1]; d[i + 2] = c[2]; d[i + 3] = 255;
}
return img;
}
pp.prototype.selectPaint = function (x, y) {
var p = this.paints.paints,
dist = function (a, b, r) {
var r = typeof r == "number" ? r : 50,
diff = function (a, b) { if (a > b) { return (a - b); } else { return (b - a); } },
dx = diff(a.x, b.x),
dy = diff(a.y, b.y);
return (dx * dx + dy * dy) / r / r;
};
p.sort(function (a, b) {
var pt = { x: x, y: y };
return dist(pt, a, a.r) - dist(pt, b, b.r);
});
if (dist({ x: x, y: y }, p[0], p[0].r) <= 0.25) {
return p[0];
}
return false;
}
}());

Playful Palette - Color mixing

Playful Palette is a color selection interface for digital painting similar to oil and watercolor palettes. The palette contains a set of color blobs that combine to create gradients and color palettes. They can be manipulated directly to explore arrangements and harmonies.

A Pen by pastuh on CodePen.

License.

(function () {
var can_ = DOM('<canvas></canvas>');
DOM("#thisCan").prepend(can_);
can_.css({
"border": "1px solid #f3f3f3"
});
var can = can_.getDom(),
ctx = can.getContext('2d'),
width = can.width = 800,
height = can.height = 480,
pp = new Palette();
var yellowColor = function () {
return [238, 217, 3]; //Cadmium Yellow Lemon ( Talens Rembrandt Extra Fine Artist' Oil colors )
};
var redColor = function () {
return [185, 5, 32]; //C.P. Cadmium Red Medium ( Golden Heavy Body Acrylics )
};
var blueColor = function () {
return [0, 85, 152]; //Cerulean Blue, Chromium ( Golden Heavy Body Acrylics )
};
var blackColor = function () {
return [40, 39, 42]; //Ivory Black ( Talens Rembrandt Extra Fine Artist' Oil colors )
};
var whiteColor = function () {
return [251, 241, 244]; //Titanium White ( Talens Rembrandt Extra Fine Artist' Oil colors )
};
pp.addPaint(yellowColor()).move(100, 100).ray(250);
pp.addPaint(redColor()).move(250, 100).ray(250);
pp.addPaint(blueColor()).move(170, 240).ray(250);
pp.addPaint(blackColor()).move(600, 100).ray(300);
pp.addPaint(whiteColor()).move(600, 240).ray(300);
pp.addPaint(yellowColor()).move(500, 420).ray(150);
pp.addPaint(redColor()).move(580, 420).ray(150);
pp.addPaint(blueColor()).move(660, 420).ray(150);
function update() {
var imageData = pp.render(width, height);
ctx.putImageData(imageData, 0, 0);
}
update();
var isMove = false,
objSelect = null;
can_.on('mousemove', function (a) {
if (isMove == true && objSelect.move) {
objSelect.move(a.offsetX, a.offsetY);
update();
}
});
can_.on('mousedown', function (a) {
objSelect = pp.selectPaint(a.offsetX, a.offsetY);
isMove = true;
});
can_.on('mouseup', function (a) {
objSelect = null;
isMove = false;
});
can_.on('mouseout', function (a) {
objSelect = null;
isMove = false;
});
}());
<script src="https://rawgit.com/ismael1361/-JS/master/library/%24JS.js"></script>
<script src="https://rawgit.com/ismael1361/-JS/master/library/%24JS.DOM.js"></script>
<script src="https://rawgit.com/ismael1361/-JS/master/playfulPalette/playfulPalette.js"></script>
body{
background: #efeee7;
user-select: none;
font-family: Arial, Helvetica, sans-serif;
color: #263238;
text-align: center;
margin-top:25px;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment