Skip to content

Instantly share code, notes, and snippets.

@garex
Created March 15, 2014 10:49
Show Gist options
  • Save garex/9565057 to your computer and use it in GitHub Desktop.
Save garex/9565057 to your computer and use it in GitHub Desktop.
Tryin to play with imitation of Color Scheme designer which is buggy from start to end :)
describe('transformToLessOperations', function() {
eval('var transformToLessOperations = require("..").transformToLessOperations');
var cm = require("color-model");
var cm = require("../../nodejs-color-model");
eval('var AbstractModel = cm.AbstractModel');
eval('var HexRgb = cm.HexRgb');
eval('var Hsl = cm.Hsl');
eval('var Rgb = cm.Rgb');
/*
describe('extreme cases', function() {
it('should get base color when both colors are same', function() {
transformToLessOperations('#fe23ca', '#fe23ca').should.be.equal('#fe23ca; // #fe23ca');
transformToLessOperations('fff', '#ffffff').should.be.equal('#ffffff; // #ffffff');
});
it('should throw error when bad color values provided', function() {
(function(){
transformToLessOperations('ggg', 'ffffff');
}).should.throwError(/unknown/);
(function(){
transformToLessOperations('', '');
}).should.throwError(/unknown/);
});
});
describe('default cases', function() {
it('should get only positive spin when positive hue difference', function() {
transformToLessOperations('#fe23ca', '#fe23a5').should.be.equal('spin(#fe23ca, 10%); // #fe23ca');
transformToLessOperations('#abc', '#aab0cc').should.be.equal('spin(#aabbcc, 20%); // #aab0cc');
});
it('should get only negative spin when negative hue difference', function() {
transformToLessOperations('#fe23ca', '#fe23ef').should.be.equal('spin(#fe23ca, -10%); // #fe23ef');
transformToLessOperations('#abc', '#aac6cc').should.be.equal('spin(#aabbcc, -20%); // #aac6cc');
});
it('should get only saturate when positive saturation difference', function() {
transformToLessOperations('#fe23ca', '#ff22cb').should.be.equal('saturate(#fe23ca, 10%); // #ff22cb');
transformToLessOperations('#abc', '#9cbbda').should.be.equal('saturate(#aabbcc, 20%); // #9cbbda');
transformToLessOperations('#ddd', '#e7d3d3').should.be.equal('saturate(#dddddd, 30%); // #e7d3d3');
});
it('should get only desaturate when negative saturation difference', function() {
transformToLessOperations('#fe23ca', '#f32ec4').should.be.equal('desaturate(#fe23ca, 10%); // #f32ec4');
transformToLessOperations('#abc', '#b8bbbe').should.be.equal('desaturate(#aabbcc, 20%); // #b8bbbe');
});
it('should get only lighten when positive lightness difference', function() {
transformToLessOperations('#fe23ca', '#fe56d6').should.be.equal('lighten(#fe23ca, 10%); // #fe56d6');
transformToLessOperations('#abc', '#eaeef2').should.be.equal('lighten(#aabbcc, 20%); // #eaeef2');
transformToLessOperations('#ddd', '#ffffff').should.be.equal('lighten(#dddddd, 30%); // #ffffff');
});
it('should get only darken when negative lightness difference', function() {
transformToLessOperations('#fe23ca', '#ed01b5').should.be.equal('darken(#fe23ca, 10%); // #ed01b5');
transformToLessOperations('#abc', '#6a88a6').should.be.equal('darken(#aabbcc, 20%); // #6a88a6');
transformToLessOperations('#ddd', '#919191').should.be.equal('darken(#dddddd, 30%); // #919191');
});
it('should get all needed operations when all 3 components differs', function() {
transformToLessOperations('#fe23ca', '#ff55ba').should.be.equal('spin(saturate(lighten(#fe23ca, 10%), 10%), 10%); // #ff55ba');
transformToLessOperations('#abc', '#828c8e').should.be.equal('spin(desaturate(darken(#aabbcc, 20%), 20%), -20%); // #828c8e');
transformToLessOperations('#ddd', '#ebe9e9').should.be.equal('spin(saturate(lighten(#dddddd, 5%), 5%), 5%); // #ebe9e9');
});
});
*/
describe('advanced cases', function() {
it('should allow to imitate analogic color scheme from Color Scheme designer', function() {
var h2 = 27.2,
h3 = 326.1; //33,9
h2 = 30;
var scheme = [[
{"HSV" : {"H" : 0,"S" : 1, "V" : 1}, "RGB" : {"R" : 255,"G" : 0, "B" : 0}},
{"HSV" : {"H" : 0,"S" : 0.75, "V" : 0.75}, "RGB" : {"R" : 191,"G" : 48, "B" : 48}},
{"HSV" : {"H" : 0,"S" : 1, "V" : 0.65}, "RGB" : {"R" : 166,"G" : 0, "B" : 0}},
{"HSV" : {"H" : 0,"S" : 0.75, "V" : 1}, "RGB" : {"R" : 255,"G" : 64, "B" : 64}},
{"HSV" : {"H" : 0,"S" : 0.55, "V" : 1}, "RGB" : {"R" : 255,"G" : 115,"B" : 115}},
{"HSV" : {"H" : h2,"S" : 1, "V" : 1}, "RGB" : {"R" : 255,"G" : 116,"B" : 0}},
{"HSV" : {"H" : h2,"S" : 0.75, "V" : 0.75}, "RGB" : {"R" : 191,"G" : 113,"B" : 48}},
{"HSV" : {"H" : h2,"S" : 1, "V" : 0.65}, "RGB" : {"R" : 166,"G" : 75, "B" : 0}},
{"HSV" : {"H" : h2,"S" : 0.75, "V" : 1}, "RGB" : {"R" : 255,"G" : 150,"B" : 64}},
{"HSV" : {"H" : h2,"S" : 0.55, "V" : 1}, "RGB" : {"R" : 255,"G" : 178,"B" : 115}},
{"HSV" : {"H" : h3,"S" : 1, "V" : 0.8020222978826353}, "RGB" : {"R" : 205,"G" : 0, "B" : 116}},
{"HSV" : {"H" : h3,"S" : 0.75,"V" : 0.6015167234119765}, "RGB" : {"R" : 153,"G" : 38, "B" : 103}},
{"HSV" : {"H" : h3,"S" : 1, "V" : 0.521314493623713}, "RGB" : {"R" : 133,"G" : 0, "B" : 75}},
{"HSV" : {"H" : h3,"S" : 0.75,"V" : 0.9010111489413177}, "RGB" : {"R" : 230,"G" : 57, "B" : 155}},
{"HSV" : {"H" : h3,"S" : 0.55,"V" : 0.9010111489413177}, "RGB" : {"R" : 230,"G" : 103,"B" : 175}}
]];
function roundTo(val, to) {
if (undefined === to) {
to = 100000;
}
return Math.round(val * to) / to;
}
function floorTo(val, to) {
if (undefined === to) {
to = 100000;
}
return Math.floor(val * to) / to;
}
function ceilTo(val, to) {
if (undefined === to) {
to = 100000;
}
return Math.ceil(val * to) / to;
}
function _HSVtoRGB(h, s, v) {
var r, g, b, i, f, p, q, t;
if (h && s === undefined && v === undefined) {
s = h.s, v = h.v, h = h.h;
}
i = Math.floor(h * 6);
f = h * 6 - i;
p = v * (1 - s);
q = v * (1 - f * s);
t = v * (1 - (1 - f) * s);
console.log(i, f, p, q, t);
switch (i % 6) {
case 0: r = v, g = t, b = p; break;
case 1: r = q, g = v, b = p; break;
case 2: r = p, g = v, b = t; break;
case 3: r = p, g = q, b = v; break;
case 4: r = t, g = p, b = v; break;
case 5: r = v, g = p, b = q; break;
}
var rate = 255.999999997;
return {
R: Math.floor(r * rate),
G: Math.floor(g * rate),
B: Math.floor(b * rate)
};
};
function HSVtoRGB11(hue, saturation, value) {
var chroma = value * saturation,
huePart = hue / 60,
secondComponent = chroma * (1 - Math.abs(huePart % 2 - 1));
return {
R: 0,
G: 0,
B: 0
};
};
/**
* HSV to RGB color conversion
*
* H runs from 0 to 360 degrees
* S and V run from 0 to 100
*
* Ported from the excellent java algorithm by Eugene Vishnevsky at:
* http://www.cs.rit.edu/~ncs/color/t_convert.html
*/
function hsvToRgb(h, s, v) {
var r, g, b;
var i;
var f, p, q, t;
// Make sure our arguments stay in-range
h = Math.max(0, Math.min(360, h));
s = Math.max(0, Math.min(100, s));
v = Math.max(0, Math.min(100, v));
// We accept saturation and value arguments from 0 to 100 because that's
// how Photoshop represents those values. Internally, however, the
// saturation and value are calculated from a range of 0 to 1. We make
// That conversion here.
s /= 100;
v /= 100;
if(s == 0) {
// Achromatic (grey)
r = g = b = v;
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
h /= 60; // sector 0 to 5
i = Math.floor(h);
f = h - i; // factorial part of h
p = v * (1 - s);
q = v * (1 - s * f);
t = v * (1 - s * (1 - f));
switch(i) {
case 0:
r = v;
g = t;
b = p;
break;
case 1:
r = q;
g = v;
b = p;
break;
case 2:
r = p;
g = v;
b = t;
break;
case 3:
r = p;
g = q;
b = v;
break;
case 4:
r = t;
g = p;
b = v;
break;
default: // case 5:
r = v;
g = p;
b = q;
}
var rate = 255.999999997;
rate = 255;
return {
R: Math.round(r * rate),
G: Math.round(g * rate),
B: Math.round(b * rate)
};
};
function hsv2hsl(hue,sat,val){
var _li = (2 - sat) * val;
var _sa = sat * val;
_sa /= (_li <= 1) ? (_li) : 2 - (_li);
_li /= 2;
return [hue, _sa, _li];
return[ //[hue, saturation, lightness]
//Range should be between 0 - 1
hue, //Hue stays the same
//Saturation is very different between the two color spaces
//If (2-sat)*val < 1 set it to sat*val/((2-sat)*val)
//Otherwise sat*val/(2-(2-sat)*val)
//Conditional is not operating with hue, it is reassigned!
sat*val/((hue=(2-sat)*val)<1?hue:2-hue),
hue/2 //Lightness is (2-sat)*val/2
//See reassignment of hue above
]
};
for (var i = 0, iMax = scheme.length; i < iMax; i++) {
for (var preset = scheme[i], j = 0, jMax = preset.length; j < jMax; j++) {
var hsv = preset[j]['HSV'],
rgb = preset[j]['RGB'],
_hsl = hsv2hsl(hsv['H'], hsv['S'], hsv['V']),
hsl = new Hsl(_hsl[0], roundTo(_hsl[1]), roundTo(_hsl[2])),
_rgb = hsvToRgb(hsv['H'], hsv['S']*100, hsv['V']*100);
var diff = [];
for (var color in _rgb) {
if (_rgb[color] != rgb[color]) {
diff.push(color + ': ' + (parseInt(_rgb[color]) - parseInt(rgb[color])));
}
}
if (diff.length) {
console.log(hsv, ' // ' + diff.join(' '));
}
//console.log(hsl.toRgb().toString(), rgb, hsl.toString(), hsv);
}
}
return;
var primaryRgb = new HexRgb('#ff0000'),
less = [''],
format = ['%(operationsStart)s', '%(operationsBaseColor)s', '%(operationsEnd)s; // %(desiredColor)s'];
// @clr-primary-1: #ff0000; // #ff0000
less.push('@clr-primary-1: ' + transformToLessOperations(primaryRgb, primaryRgb));
format[1] = '@clr-primary-1';
formatStr = format.join('');
// @clr-primary-2: #bf3030; // #bf3030
less.push('@clr-primary-2: ' + transformToLessOperations(primaryRgb,
primaryRgb.toHsl().desaturate('40.5%').darken('3%').toRgb().toHexString(),
formatStr));
// @clr-primary-3: #a60000; // #a60000
less.push('@clr-primary-3: ' + transformToLessOperations(primaryRgb,
primaryRgb.toHsl().darken('17.4%').toRgb().toHexString(),
formatStr));
// @clr-secondary-a-1: #ff7400; // #ff7400
var secondaryA = primaryRgb.toHsl().spin(27 + 140/360).toRgb();
less.push('@clr-secondary-a-1: ' + transformToLessOperations(primaryRgb,
secondaryA.toHexString(),
formatStr));
format[1] = '@clr-secondary-a-1';
formatStr = format.join('');
// @clr-secondary-a-2: #bf7130; // #bf7130
less.push('@clr-secondary-a-2: ' + transformToLessOperations(primaryRgb,
secondaryA.toHsl().desaturate('40.5%').darken('3%').toRgb().toHexString(),
formatStr));
// @clr-secondary-a-3: #a64b00; // #a64b00
less.push('@clr-secondary-a-3: ' + transformToLessOperations(primaryRgb,
secondaryA.toHsl().darken('17.4%').toRgb().toHexString(),
formatStr));
format[1] = '@clr-primary-1';
formatStr = format.join('');
// @clr-secondary-b-1: #cd0074; // #cd0074
var secondaryB = primaryRgb.toHsl()
.spin(360 - 34)
.darken('9.9%')
.toRgb();
less.push('@clr-secondary-b-1: ' + transformToLessOperations(primaryRgb,
secondaryB.toHexString(),
formatStr));
format[1] = '@clr-secondary-b-1';
formatStr = format.join('');
// @clr-secondary-b-2: #992667; // #992667
less.push('@clr-secondary-b-2: ' + transformToLessOperations(primaryRgb,
secondaryB.toHsl()
.desaturate('40.5%')
.darken('3%')
.toRgb().toHexString(),
formatStr));
// @clr-secondary-b-3: #85004b; // #85004b
less.push('@clr-secondary-b-3: ' + transformToLessOperations(primaryRgb,
secondaryB.toHsl().darken('17.4%').toRgb().toHexString(),
formatStr));
console.log(less.join('\n '));
});
//it('should support hue adjustements of analogic color scheme from red to yellow base color');
});
/**
* @returns {AbstractModel}
*/
AbstractModel.prototype.increase = function (name, value) {
if ((typeof value == 'string') && '%' == value.substr(-1)) {
value = parseFloat(value) / 100;
}
return this.component(name, this.component(name) + value);
};
/**
* @returns {AbstractModel}
*/
AbstractModel.prototype.decrease = function (name, value) {
if ((typeof value == 'string') && '%' == value.substr(-1)) {
value = parseFloat(value) / 100;
}
this.component(name, this.component(name) - value);
return this;
};
/**
* @returns {Hsl}
*/
Hsl.prototype.saturate = function(value) {
return this.increase('saturation', value);
};
/**
* @returns {Hsl}
*/
Hsl.prototype.desaturate = function(value) {
return this.decrease('saturation', value);
};
/**
* @returns {Hsl}
*/
Hsl.prototype.lighten = function(value) {
return this.increase('lightness', value);
};
/**
* @returns {Hsl}
*/
Hsl.prototype.darken = function(value) {
return this.decrease('lightness', value);
};
/**
* @returns {Hsl}
*/
Hsl.prototype.spin = function(value) {
return this.increase('hue', value);
};
/**
* @returns {Hsl}
*/
Hsl.prototype.unspin = function(value) {
return this.decrease('hue', value);
};
Hsl.prototype.toString1 = function() {
var v = [
this._hue.get(),
this._saturation.get() * 100 + '%',
this._lightness.get() * 100 + '%'
];
return this._name + '(' + v.join(', ') + ')';
};
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment