-
{logos}
diff --git a/app/scripts/components/Header.jsx b/app/scripts/components/Header.jsx
index 06c281c..0caa4e1 100644
--- a/app/scripts/components/Header.jsx
+++ b/app/scripts/components/Header.jsx
@@ -1,5 +1,7 @@
var React = require('react/addons'),
- ScaleLog = require('../utils/scaleLog'),
+ lodash = require('lodash'),
+ Colors = require('../utils/Colors'),
+ ScaleLog = require('../utils/ScaleLog'),
config = require('../config');
var Header = React.createClass({
@@ -8,14 +10,16 @@ var Header = React.createClass({
propTypes: {
columns: React.PropTypes.number.isRequired,
logos: React.PropTypes.array.isRequired,
- onClickChangeColumns: React.PropTypes.func.isRequired
+ onClickChangeColumns: React.PropTypes.func.isRequired,
+ onClickTag: React.PropTypes.func.isRequired
},
componentWillMount () {
- let tags = {},
- sizer = {
+ let tags = {},
+ fScale = {
min: 1,
- max: 0
+ max: 0,
+ unit: 'rem'
};
if (config.features.tags) {
@@ -28,25 +32,26 @@ var Header = React.createClass({
});
});
- tags = this._sortObject(tags);
-
+ tags = this._sortObject(tags, 'value');
tags.forEach((t) => {
- if (t.value < sizer.min) {
- sizer.min = t.value;
+ if (t.value < fScale.min) {
+ fScale.min = t.value;
}
- if (t.value > sizer.max) {
- sizer.max = t.value;
+ if (t.value > fScale.max) {
+ fScale.max = t.value;
}
});
this.setState({
tags: tags,
- scale: new ScaleLog(sizer)
+ fontScale: new ScaleLog(fScale),
+ colorScale: new ScaleLog({ minSize: 12, min: fScale.min, maxSize: 70, max: fScale.max }),
+ color: new Colors('#ffced3')
});
}
},
- _sortObject (obj) {
+ _sortObject (obj, attr) {
var arr = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
@@ -56,12 +61,16 @@ var Header = React.createClass({
});
}
}
- /*arr.sort(function (a, b) {
- return b.value - a.value;
- });*/
- arr.sort(function (a, b) {
- return a.key.toLowerCase().localeCompare(b.key.toLowerCase());
- }); //use this to sort as strings
+ if (attr === 'value') {
+ arr.sort(function (a, b) {
+ return b.value - a.value;
+ });
+ }
+ else {
+ arr.sort(function (a, b) {
+ return a.key.toLowerCase().localeCompare(b.key.toLowerCase());
+ }); //use this to sort as strings
+ }
return arr;
},
@@ -69,14 +78,22 @@ var Header = React.createClass({
render () {
var props = this.props,
state = this.state,
- tags;
+ tags,
+ style;
if (config.features.tags) {
tags = (
- Columns
+
- - - 4 ? 'disabled' : ''} data-column="1" onClick={props.onClickChangeColumns}>+ + - + 4 ? 'disabled' : ''} data-column="1" + onClick={props.onClickChangeColumns}>+or use your keyboard
diff --git a/app/scripts/utils/Colors.js b/app/scripts/utils/Colors.js
new file mode 100644
index 0000000..b7270a6
--- /dev/null
+++ b/app/scripts/utils/Colors.js
@@ -0,0 +1,307 @@
+var _ = require('lodash');
+
+/*
+ Color
+ =====
+
+ SassMe - an Arc90 Lab Project
+
+ The MIT License (MIT)
+ Copyright © 2012 Arc90 | http://arc90.com
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
+ this software and associated documentation files (the “Software”), to deal in
+ the Software without restriction, including without limitation the rights to
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ the Software, and to permit persons to whom the Software is furnished to do so,
+ subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+ Authors:
+ --------
+
+ Jim Nielsen
+ Darren Newton
+ Robert Petro
+ Matt Quintanilla
+ Jesse Reiner
+
+ Color algorithms:
+ -----------------
+ RGB/HSL Algorithms adapted from: http://mjijackson.com/2008/02/rgb-to-hsl-and-
+ rgb-to-hsv-color-model-conversion-algorithms-in-javascript
+
+ Syntactically Awesome Stylesheets:
+ ----------------------------------
+ The overall structure of the SASS conversions is based on the Ruby
+ SASS project:
+ https://github.com/nex3/sass/blob/stable/lib/sass/script/color.rb
+ Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
+ */
+
+class Colors {
+ constructor (color) {
+ this.hex = color.charAt(0) === '#' ? color : '#' + color;
+
+ if (color != null) {
+ this.rgb = this.hex2rgb(this.hex);
+ }
+
+ if (this.rgb != null) {
+ this.hsl = this.rgb2hsl(this.rgb);
+ }
+
+ return this;
+ }
+
+ hex2rgb (color) {
+ if (color.charAt(0) === '#') {
+ color = color.substr(1);
+ }
+
+ return {
+ r: parseInt(color.charAt(0) + '' + color.charAt(1), 16),
+ g: parseInt(color.charAt(2) + '' + color.charAt(3), 16),
+ b: parseInt(color.charAt(4) + '' + color.charAt(5), 16)
+ };
+ }
+
+ rgb2hsl (rgb) {
+ var b, d, g, h, hsl, l, max, min, r, s, _ref;
+ _ref = [rgb.r, rgb.g, rgb.b];
+ r = _ref[0];
+ g = _ref[1];
+ b = _ref[2];
+
+ r /= 255;
+ g /= 255;
+ b /= 255;
+ max = Math.max(r, g, b);
+ min = Math.min(r, g, b);
+ d = max - min;
+ h = (function () {
+ switch (max) {
+ case min:
+ return 0;
+ case r:
+ return 60 * (g - b) / d;
+ case g:
+ return 60 * (b - r) / d + 120;
+ case b:
+ return 60 * (r - g) / d + 240;
+ }
+ }());
+ if (h < 0) {
+ h = 360 + h;
+ }
+ l = (max + min) / 2.0;
+ s = max === min ? 0 : l < 0.5 ? d / (2 * l) : d / (2 - 2 * l);
+ return {
+ h: Math.abs(+((h % 360).toFixed(5))),
+ s: +((s * 100).toFixed(5)),
+ l: +((l * 100).toFixed(5))
+ };
+ }
+
+ rgb2hex (rgb) {
+ return '#' + ((1 << 24) + (rgb.r << 16) + (rgb.g << 8) + rgb.b).toString(16).slice(1);
+ }
+
+ hue2rgb (p, q, t) {
+ if (t < 0) {
+ t += 1;
+ }
+ if (t > 1) {
+ t -= 1;
+ }
+ if (t < 1 / 6) {
+ return p + (q - p) * 6 * t;
+ }
+ if (t < 1 / 2) {
+ return q;
+ }
+ if (t < 2 / 3) {
+ return p + (q - p) * (2 / 3 - t) * 6;
+ }
+ return p;
+ }
+
+ hsl2rgb (hsl) {
+ var b, g, h, l, p, q, r, s, _ref;
+ _ref = [parseFloat(hsl.h).toFixed(5) / 360,
+ parseFloat(hsl.s).toFixed(5) / 100,
+ parseFloat(hsl.l).toFixed(5) / 100];
+ h = _ref[0];
+ s = _ref[1];
+ l = _ref[2];
+
+ if (s === 0) {
+ r = g = b = l;
+ }
+ else {
+ q = l < 0.5 ? l * (1 + s) : l + s - l * s;
+ p = 2 * l - q;
+ r = this.hue2rgb(p, q, h + 1 / 3);
+ g = this.hue2rgb(p, q, h);
+ b = this.hue2rgb(p, q, h - 1 / 3);
+ }
+ return {
+ r: Math.round(r * 255),
+ g: Math.round(g * 255),
+ b: Math.round(b * 255)
+ };
+ }
+
+ hsl2hex (hsl) {
+ return this.rgb2hex(this.hsl2rgb(hsl));
+ }
+
+ mod (attr) {
+ var hsl, out, rgb, type;
+ if ((_.intersection(_.keys(attr), ['h', 's', 'l']).length > 0) &&
+ (_.intersection(_.keys(attr), ['r', 'g', 'b']).length > 0)) {
+ return null;
+ }
+ if (_.intersection(_.keys(attr), ['r', 'g', 'b']).length > 0) {
+ type = 'rgb';
+ }
+ else if (_.intersection(_.keys(attr), ['h', 's', 'l']).length > 0) {
+ type = 'hsl';
+ }
+ else {
+ return null;
+ }
+ _.each(attr, function (val, key, list) {
+ if (val === null) {
+ return delete list[key];
+ }
+ });
+ switch (type) {
+ case 'rgb':
+ rgb = _.pick(attr, 'r', 'g', 'b');
+ if (_.isEmpty(rgb) === false) {
+ out = _.extend(_.clone(this.rgb), rgb);
+ }
+ else {
+ out = this.rgb;
+ }
+ break;
+ case 'hsl':
+ hsl = _.pick(attr, 'h', 's', 'l');
+ if (_.isEmpty(hsl) === false) {
+ out = _.extend(_.clone(this.hsl), hsl);
+ }
+ else {
+ out = this.hsl;
+ }
+ }
+ return out;
+ }
+
+ static constrain (attr, amount, limit, direction) {
+ var math, test, val;
+ math = [attr, direction, amount].join(' ');
+ val = eval(math);
+ test = (limit[1] >= val && val >= limit[0]);
+ if (test) {
+ val;
+
+ }
+ else {
+ if (val < limit[0]) {
+ val = limit[0];
+ }
+ if (val > limit[1]) {
+ val = limit[1];
+ }
+ }
+ return Math.abs(val);
+ }
+
+ static constrain_degrees (attr, amount) {
+ var val;
+ val = attr + amount;
+ if (val > 360) {
+ val -= 360;
+ }
+ if (val < 0) {
+ val += 360;
+ }
+ return Math.abs(val);
+ }
+
+ red () {
+ return this.rgb.r;
+ }
+
+ green () {
+ return this.rgb.g;
+ }
+
+ blue () {
+ return this.rgb.b;
+ }
+
+ hue () {
+ return +this.hsl.h;
+ }
+
+ saturation () {
+ return +this.hsl.s;
+ }
+
+ lightness () {
+ return +this.hsl.l;
+ }
+
+ lighten (percentage) {
+ var hsl;
+ hsl = this.mod({
+ l: this.constructor.constrain(this.lightness(), percentage, [0, 100], '+')
+ });
+ return this.rgb2hex(this.hsl2rgb(hsl));
+ }
+
+ darken (percentage) {
+ var hsl;
+ hsl = this.mod({
+ l: this.constructor.constrain(this.lightness(), percentage, [0, 100], '-')
+ });
+ return this.rgb2hex(this.hsl2rgb(hsl));
+ }
+
+ saturate (percentage) {
+ var hsl;
+ hsl = this.mod({
+ s: this.constructor.constrain(this.saturation(), percentage, [0, 100], '+')
+ });
+ return this.rgb2hex(this.hsl2rgb(hsl));
+ }
+
+ desaturate (percentage) {
+ var hsl;
+ hsl = this.mod({
+ s: this.constructor.constrain(this.saturation(), percentage, [0, 100], '-')
+ });
+ return this.rgb2hex(this.hsl2rgb(hsl));
+ }
+
+ adjust_hue (degrees) {
+ var hsl = this.mod({
+ h: this.constructor.constrain_degrees(this.hue(), degrees)
+ });
+
+ return this.rgb2hex(this.hsl2rgb(hsl));
+ }
+}
+
+module.exports = Colors;
diff --git a/app/scripts/utils/ScaleLog.js b/app/scripts/utils/ScaleLog.js
new file mode 100644
index 0000000..b3a9ed3
--- /dev/null
+++ b/app/scripts/utils/ScaleLog.js
@@ -0,0 +1,21 @@
+class ScaleLog {
+ constructor (options) {
+ options = options || {};
+ this.minSize = options.minSize || 1.2;
+ this.maxSize = options.maxSize || 5;
+ this.unit = options.unit || '';
+ this.min = (options.min || 1);
+ this.max = (options.max || 50);
+
+ this.scale = (this.max - this.min) / (this.maxSize - this.minSize);
+ }
+
+ value (qty) {
+ return (qty === this.min ? this.minSize : (qty / this.max) * (this.maxSize - this.minSize) + this.minSize).toFixed(2) + this.unit;
+ //Math.exp((position - this.minSize) * this.scale + this.min);
+ }
+}
+
+// Usage: new LogSlider({ min: 10, max: 100 });
+
+module.exports = ScaleLog;
diff --git a/app/scripts/utils/scaleLog.js b/app/scripts/utils/scaleLog.js
deleted file mode 100644
index ed1a49e..0000000
--- a/app/scripts/utils/scaleLog.js
+++ /dev/null
@@ -1,21 +0,0 @@
-class ScaleLog {
- constructor (options) {
- options = options || {};
- this.fontMin = options.fontMin || 1.2;
- this.fontMax = options.fontMax || 5;
- this.unit = options.unit || 'rem';
- this.min = (options.min || 1);
- this.max = (options.max || 50);
-
- this.scale = (this.max - this.min) / (this.fontMax - this.fontMin);
- }
-
- value (qty) {
- return (qty === this.min ? this.fontMin : (qty / this.max) * (this.fontMax - this.fontMin) + this.fontMin).toFixed(2) + this.unit;
- //Math.exp((position - this.fontMin) * this.scale + this.min);
- }
-}
-
-// Usage: new LogSlider({ min: 10, max: 100 });
-
-module.exports = ScaleLog;
diff --git a/app/styles/components/_header.scss b/app/styles/components/_header.scss
index f800122..cc384d8 100644
--- a/app/styles/components/_header.scss
+++ b/app/styles/components/_header.scss
@@ -100,6 +100,7 @@ header {
display: flex;
flex-flow: wrap;
justify-content: space-around;
+ margin-top: 2rem;
a {
background-color: $link-color;
diff --git a/package.json b/package.json
index d728440..46050c6 100644
--- a/package.json
+++ b/package.json
@@ -13,25 +13,25 @@
},
"devDependencies": {
"babelify": "^6.1",
- "browser-sync": "^2.7",
- "browserify": "^10.2",
+ "browser-sync": "^2.8",
+ "browserify": "^11.0",
"connect": "^3.4",
"connect-history-api-fallback": "^1.1",
"del": "^1.2",
- "eslint": "^0.23",
- "eslint-plugin-react": "^2.5",
+ "eslint": "^0.24",
+ "eslint-plugin-react": "^2.7",
"gulp": "^3.9",
"gulp-autoprefixer": "^2.3",
"gulp-cache": "^0.2",
"gulp-changed": "^1.2",
"gulp-compile-handlebars": "^0.5",
"gulp-cssmin": "^0.1",
- "gulp-eslint": "^0.14",
+ "gulp-eslint": "^0.15",
"gulp-filter": "^2.0",
- "gulp-flatten": "0.0.4",
+ "gulp-flatten": "^0.1",
"gulp-gh-pages": "^0.5",
"gulp-if": "^1.2",
- "gulp-imagemin": "^2.2",
+ "gulp-imagemin": "^2.3",
"gulp-load-plugins": "^0.10",
"gulp-plumber": "^1.0",
"gulp-rename": "^1.2",
@@ -41,11 +41,12 @@
"gulp-uglify": "^1.2",
"gulp-useref": "^1.2",
"gulp-util": "^3.0",
+ "lodash": "^3.10.0",
"merge-stream": "^0.1",
"run-sequence": "^1.1",
"vinyl-buffer": "^1.0",
"vinyl-source-stream": "^1.1",
- "watchify": "^3.2"
+ "watchify": "^3.3"
},
"engines": {
"node": ">=0.10.0"
{state.tags.map((d, i) => {
- return ({d.key + ' (' + d.value + ')'}
+ style = {
+ backgroundColor: state.color.hsl2hex({
+ h: state.color.hue(),
+ s: state.color.saturation(),
+ l: state.color.lightness() - +state.colorScale.value(d.value)
+ }),
+ fontSize: state.fontScale.value(d.value)
+ };
+ return ({d.key + ' (' + d.value + ')'}
);
})}
@@ -87,12 +104,15 @@ var Header = React.createClass({