mirror of
https://github.com/nanoy42/coope
synced 2024-11-24 04:13:13 +00:00
Random colors and fixes
This commit is contained in:
parent
edd724cee3
commit
3cc7966bbc
3 changed files with 524 additions and 12 deletions
519
staticfiles/randomColor.js
Normal file
519
staticfiles/randomColor.js
Normal file
|
@ -0,0 +1,519 @@
|
|||
// randomColor by David Merfield under the CC0 license
|
||||
// https://github.com/davidmerfield/randomColor/
|
||||
|
||||
;(function(root, factory) {
|
||||
|
||||
// Support CommonJS
|
||||
if (typeof exports === 'object') {
|
||||
var randomColor = factory();
|
||||
|
||||
// Support NodeJS & Component, which allow module.exports to be a function
|
||||
if (typeof module === 'object' && module && module.exports) {
|
||||
exports = module.exports = randomColor;
|
||||
}
|
||||
|
||||
// Support CommonJS 1.1.1 spec
|
||||
exports.randomColor = randomColor;
|
||||
|
||||
// Support AMD
|
||||
} else if (typeof define === 'function' && define.amd) {
|
||||
define([], factory);
|
||||
|
||||
// Support vanilla script loading
|
||||
} else {
|
||||
root.randomColor = factory();
|
||||
}
|
||||
|
||||
}(this, function() {
|
||||
|
||||
// Seed to get repeatable colors
|
||||
var seed = null;
|
||||
|
||||
// Shared color dictionary
|
||||
var colorDictionary = {};
|
||||
|
||||
// Populate the color dictionary
|
||||
loadColorBounds();
|
||||
|
||||
// check if a range is taken
|
||||
var colorRanges = [];
|
||||
|
||||
var randomColor = function (options) {
|
||||
|
||||
options = options || {};
|
||||
|
||||
// Check if there is a seed and ensure it's an
|
||||
// integer. Otherwise, reset the seed value.
|
||||
if (options.seed !== undefined && options.seed !== null && options.seed === parseInt(options.seed, 10)) {
|
||||
seed = options.seed;
|
||||
|
||||
// A string was passed as a seed
|
||||
} else if (typeof options.seed === 'string') {
|
||||
seed = stringToInteger(options.seed);
|
||||
|
||||
// Something was passed as a seed but it wasn't an integer or string
|
||||
} else if (options.seed !== undefined && options.seed !== null) {
|
||||
throw new TypeError('The seed value must be an integer or string');
|
||||
|
||||
// No seed, reset the value outside.
|
||||
} else {
|
||||
seed = null;
|
||||
}
|
||||
|
||||
var H,S,B;
|
||||
|
||||
// Check if we need to generate multiple colors
|
||||
if (options.count !== null && options.count !== undefined) {
|
||||
|
||||
var totalColors = options.count,
|
||||
colors = [];
|
||||
// Value false at index i means the range i is not taken yet.
|
||||
for (var i = 0; i < options.count; i++) {
|
||||
colorRanges.push(false)
|
||||
}
|
||||
options.count = null;
|
||||
|
||||
while (totalColors > colors.length) {
|
||||
|
||||
// Since we're generating multiple colors,
|
||||
// incremement the seed. Otherwise we'd just
|
||||
// generate the same color each time...
|
||||
if (seed && options.seed) options.seed += 1;
|
||||
|
||||
colors.push(randomColor(options));
|
||||
}
|
||||
|
||||
options.count = totalColors;
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
// First we pick a hue (H)
|
||||
H = pickHue(options);
|
||||
|
||||
// Then use H to determine saturation (S)
|
||||
S = pickSaturation(H, options);
|
||||
|
||||
// Then use S and H to determine brightness (B).
|
||||
B = pickBrightness(H, S, options);
|
||||
|
||||
// Then we return the HSB color in the desired format
|
||||
return setFormat([H,S,B], options);
|
||||
};
|
||||
|
||||
function pickHue(options) {
|
||||
if (colorRanges.length > 0) {
|
||||
var hueRange = getRealHueRange(options.hue)
|
||||
|
||||
var hue = randomWithin(hueRange)
|
||||
|
||||
//Each of colorRanges.length ranges has a length equal approximatelly one step
|
||||
var step = (hueRange[1] - hueRange[0]) / colorRanges.length
|
||||
|
||||
var j = parseInt((hue - hueRange[0]) / step)
|
||||
|
||||
//Check if the range j is taken
|
||||
if (colorRanges[j] === true) {
|
||||
j = (j + 2) % colorRanges.length
|
||||
}
|
||||
else {
|
||||
colorRanges[j] = true
|
||||
}
|
||||
|
||||
var min = (hueRange[0] + j * step) % 359,
|
||||
max = (hueRange[0] + (j + 1) * step) % 359;
|
||||
|
||||
hueRange = [min, max]
|
||||
|
||||
hue = randomWithin(hueRange)
|
||||
|
||||
if (hue < 0) {hue = 360 + hue;}
|
||||
return hue
|
||||
}
|
||||
else {
|
||||
var hueRange = getHueRange(options.hue)
|
||||
|
||||
hue = randomWithin(hueRange);
|
||||
// Instead of storing red as two seperate ranges,
|
||||
// we group them, using negative numbers
|
||||
if (hue < 0) {
|
||||
hue = 360 + hue;
|
||||
}
|
||||
|
||||
return hue;
|
||||
}
|
||||
}
|
||||
|
||||
function pickSaturation (hue, options) {
|
||||
|
||||
if (options.hue === 'monochrome') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (options.luminosity === 'random') {
|
||||
return randomWithin([0,100]);
|
||||
}
|
||||
|
||||
var saturationRange = getSaturationRange(hue);
|
||||
|
||||
var sMin = saturationRange[0],
|
||||
sMax = saturationRange[1];
|
||||
|
||||
switch (options.luminosity) {
|
||||
|
||||
case 'bright':
|
||||
sMin = 55;
|
||||
break;
|
||||
|
||||
case 'dark':
|
||||
sMin = sMax - 10;
|
||||
break;
|
||||
|
||||
case 'light':
|
||||
sMax = 55;
|
||||
break;
|
||||
}
|
||||
|
||||
return randomWithin([sMin, sMax]);
|
||||
|
||||
}
|
||||
|
||||
function pickBrightness (H, S, options) {
|
||||
|
||||
var bMin = getMinimumBrightness(H, S),
|
||||
bMax = 100;
|
||||
|
||||
switch (options.luminosity) {
|
||||
|
||||
case 'dark':
|
||||
bMax = bMin + 20;
|
||||
break;
|
||||
|
||||
case 'light':
|
||||
bMin = (bMax + bMin)/2;
|
||||
break;
|
||||
|
||||
case 'random':
|
||||
bMin = 0;
|
||||
bMax = 100;
|
||||
break;
|
||||
}
|
||||
|
||||
return randomWithin([bMin, bMax]);
|
||||
}
|
||||
|
||||
function setFormat (hsv, options) {
|
||||
|
||||
switch (options.format) {
|
||||
|
||||
case 'hsvArray':
|
||||
return hsv;
|
||||
|
||||
case 'hslArray':
|
||||
return HSVtoHSL(hsv);
|
||||
|
||||
case 'hsl':
|
||||
var hsl = HSVtoHSL(hsv);
|
||||
return 'hsl('+hsl[0]+', '+hsl[1]+'%, '+hsl[2]+'%)';
|
||||
|
||||
case 'hsla':
|
||||
var hslColor = HSVtoHSL(hsv);
|
||||
var alpha = options.alpha || Math.random();
|
||||
return 'hsla('+hslColor[0]+', '+hslColor[1]+'%, '+hslColor[2]+'%, ' + alpha + ')';
|
||||
|
||||
case 'rgbArray':
|
||||
return HSVtoRGB(hsv);
|
||||
|
||||
case 'rgb':
|
||||
var rgb = HSVtoRGB(hsv);
|
||||
return 'rgb(' + rgb.join(', ') + ')';
|
||||
|
||||
case 'rgba':
|
||||
var rgbColor = HSVtoRGB(hsv);
|
||||
var alpha = options.alpha || Math.random();
|
||||
return 'rgba(' + rgbColor.join(', ') + ', ' + alpha + ')';
|
||||
|
||||
default:
|
||||
return HSVtoHex(hsv);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getMinimumBrightness(H, S) {
|
||||
|
||||
var lowerBounds = getColorInfo(H).lowerBounds;
|
||||
|
||||
for (var i = 0; i < lowerBounds.length - 1; i++) {
|
||||
|
||||
var s1 = lowerBounds[i][0],
|
||||
v1 = lowerBounds[i][1];
|
||||
|
||||
var s2 = lowerBounds[i+1][0],
|
||||
v2 = lowerBounds[i+1][1];
|
||||
|
||||
if (S >= s1 && S <= s2) {
|
||||
|
||||
var m = (v2 - v1)/(s2 - s1),
|
||||
b = v1 - m*s1;
|
||||
|
||||
return m*S + b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
function getHueRange (colorInput) {
|
||||
|
||||
if (typeof parseInt(colorInput) === 'number') {
|
||||
|
||||
var number = parseInt(colorInput);
|
||||
|
||||
if (number < 360 && number > 0) {
|
||||
return [number, number];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (typeof colorInput === 'string') {
|
||||
|
||||
if (colorDictionary[colorInput]) {
|
||||
var color = colorDictionary[colorInput];
|
||||
if (color.hueRange) {return color.hueRange;}
|
||||
} else if (colorInput.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)) {
|
||||
var hue = HexToHSB(colorInput)[0];
|
||||
return [ hue, hue ];
|
||||
}
|
||||
}
|
||||
|
||||
return [0,360];
|
||||
|
||||
}
|
||||
|
||||
function getSaturationRange (hue) {
|
||||
return getColorInfo(hue).saturationRange;
|
||||
}
|
||||
|
||||
function getColorInfo (hue) {
|
||||
|
||||
// Maps red colors to make picking hue easier
|
||||
if (hue >= 334 && hue <= 360) {
|
||||
hue-= 360;
|
||||
}
|
||||
|
||||
for (var colorName in colorDictionary) {
|
||||
var color = colorDictionary[colorName];
|
||||
if (color.hueRange &&
|
||||
hue >= color.hueRange[0] &&
|
||||
hue <= color.hueRange[1]) {
|
||||
return colorDictionary[colorName];
|
||||
}
|
||||
} return 'Color not found';
|
||||
}
|
||||
|
||||
function randomWithin (range) {
|
||||
if (seed === null) {
|
||||
//generate random evenly destinct number from : https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
|
||||
var golden_ratio = 0.618033988749895
|
||||
var r=Math.random()
|
||||
r += golden_ratio
|
||||
r %= 1
|
||||
return Math.floor(range[0] + r*(range[1] + 1 - range[0]));
|
||||
} else {
|
||||
//Seeded random algorithm from http://indiegamr.com/generate-repeatable-random-numbers-in-js/
|
||||
var max = range[1] || 1;
|
||||
var min = range[0] || 0;
|
||||
seed = (seed * 9301 + 49297) % 233280;
|
||||
var rnd = seed / 233280.0;
|
||||
return Math.floor(min + rnd * (max - min));
|
||||
}
|
||||
}
|
||||
|
||||
function HSVtoHex (hsv){
|
||||
|
||||
var rgb = HSVtoRGB(hsv);
|
||||
|
||||
function componentToHex(c) {
|
||||
var hex = c.toString(16);
|
||||
return hex.length == 1 ? '0' + hex : hex;
|
||||
}
|
||||
|
||||
var hex = '#' + componentToHex(rgb[0]) + componentToHex(rgb[1]) + componentToHex(rgb[2]);
|
||||
|
||||
return hex;
|
||||
|
||||
}
|
||||
|
||||
function defineColor (name, hueRange, lowerBounds) {
|
||||
|
||||
var sMin = lowerBounds[0][0],
|
||||
sMax = lowerBounds[lowerBounds.length - 1][0],
|
||||
|
||||
bMin = lowerBounds[lowerBounds.length - 1][1],
|
||||
bMax = lowerBounds[0][1];
|
||||
|
||||
colorDictionary[name] = {
|
||||
hueRange: hueRange,
|
||||
lowerBounds: lowerBounds,
|
||||
saturationRange: [sMin, sMax],
|
||||
brightnessRange: [bMin, bMax]
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
function loadColorBounds () {
|
||||
|
||||
defineColor(
|
||||
'monochrome',
|
||||
null,
|
||||
[[0,0],[100,0]]
|
||||
);
|
||||
|
||||
defineColor(
|
||||
'red',
|
||||
[-26,18],
|
||||
[[20,100],[30,92],[40,89],[50,85],[60,78],[70,70],[80,60],[90,55],[100,50]]
|
||||
);
|
||||
|
||||
defineColor(
|
||||
'orange',
|
||||
[19,46],
|
||||
[[20,100],[30,93],[40,88],[50,86],[60,85],[70,70],[100,70]]
|
||||
);
|
||||
|
||||
defineColor(
|
||||
'yellow',
|
||||
[47,62],
|
||||
[[25,100],[40,94],[50,89],[60,86],[70,84],[80,82],[90,80],[100,75]]
|
||||
);
|
||||
|
||||
defineColor(
|
||||
'green',
|
||||
[63,178],
|
||||
[[30,100],[40,90],[50,85],[60,81],[70,74],[80,64],[90,50],[100,40]]
|
||||
);
|
||||
|
||||
defineColor(
|
||||
'blue',
|
||||
[179, 257],
|
||||
[[20,100],[30,86],[40,80],[50,74],[60,60],[70,52],[80,44],[90,39],[100,35]]
|
||||
);
|
||||
|
||||
defineColor(
|
||||
'purple',
|
||||
[258, 282],
|
||||
[[20,100],[30,87],[40,79],[50,70],[60,65],[70,59],[80,52],[90,45],[100,42]]
|
||||
);
|
||||
|
||||
defineColor(
|
||||
'pink',
|
||||
[283, 334],
|
||||
[[20,100],[30,90],[40,86],[60,84],[80,80],[90,75],[100,73]]
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
function HSVtoRGB (hsv) {
|
||||
|
||||
// this doesn't work for the values of 0 and 360
|
||||
// here's the hacky fix
|
||||
var h = hsv[0];
|
||||
if (h === 0) {h = 1;}
|
||||
if (h === 360) {h = 359;}
|
||||
|
||||
// Rebase the h,s,v values
|
||||
h = h/360;
|
||||
var s = hsv[1]/100,
|
||||
v = hsv[2]/100;
|
||||
|
||||
var h_i = Math.floor(h*6),
|
||||
f = h * 6 - h_i,
|
||||
p = v * (1 - s),
|
||||
q = v * (1 - f*s),
|
||||
t = v * (1 - (1 - f)*s),
|
||||
r = 256,
|
||||
g = 256,
|
||||
b = 256;
|
||||
|
||||
switch(h_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;
|
||||
case 5: r = v; g = p; b = q; break;
|
||||
}
|
||||
|
||||
var result = [Math.floor(r*255), Math.floor(g*255), Math.floor(b*255)];
|
||||
return result;
|
||||
}
|
||||
|
||||
function HexToHSB (hex) {
|
||||
hex = hex.replace(/^#/, '');
|
||||
hex = hex.length === 3 ? hex.replace(/(.)/g, '$1$1') : hex;
|
||||
|
||||
var red = parseInt(hex.substr(0, 2), 16) / 255,
|
||||
green = parseInt(hex.substr(2, 2), 16) / 255,
|
||||
blue = parseInt(hex.substr(4, 2), 16) / 255;
|
||||
|
||||
var cMax = Math.max(red, green, blue),
|
||||
delta = cMax - Math.min(red, green, blue),
|
||||
saturation = cMax ? (delta / cMax) : 0;
|
||||
|
||||
switch (cMax) {
|
||||
case red: return [ 60 * (((green - blue) / delta) % 6) || 0, saturation, cMax ];
|
||||
case green: return [ 60 * (((blue - red) / delta) + 2) || 0, saturation, cMax ];
|
||||
case blue: return [ 60 * (((red - green) / delta) + 4) || 0, saturation, cMax ];
|
||||
}
|
||||
}
|
||||
|
||||
function HSVtoHSL (hsv) {
|
||||
var h = hsv[0],
|
||||
s = hsv[1]/100,
|
||||
v = hsv[2]/100,
|
||||
k = (2-s)*v;
|
||||
|
||||
return [
|
||||
h,
|
||||
Math.round(s*v / (k<1 ? k : 2-k) * 10000) / 100,
|
||||
k/2 * 100
|
||||
];
|
||||
}
|
||||
|
||||
function stringToInteger (string) {
|
||||
var total = 0
|
||||
for (var i = 0; i !== string.length; i++) {
|
||||
if (total >= Number.MAX_SAFE_INTEGER) break;
|
||||
total += string.charCodeAt(i)
|
||||
}
|
||||
return total
|
||||
}
|
||||
|
||||
// get The range of given hue when options.count!=0
|
||||
function getRealHueRange(colorHue)
|
||||
{ if (!isNaN(colorHue)) {
|
||||
var number = parseInt(colorHue);
|
||||
|
||||
if (number < 360 && number > 0) {
|
||||
return getColorInfo(colorHue).hueRange
|
||||
}
|
||||
}
|
||||
else if (typeof colorHue === 'string') {
|
||||
|
||||
if (colorDictionary[colorHue]) {
|
||||
var color = colorDictionary[colorHue];
|
||||
|
||||
if (color.hueRange) {
|
||||
return color.hueRange
|
||||
}
|
||||
} else if (colorHue.match(/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i)) {
|
||||
var hue = HexToHSB(colorHue)[0]
|
||||
return getColorInfo(hue).hueRange
|
||||
}
|
||||
}
|
||||
|
||||
return [0,360]
|
||||
}
|
||||
return randomColor;
|
||||
}));
|
|
@ -76,17 +76,10 @@
|
|||
<section class="row uniform">
|
||||
<canvas id="myChart" width="2000px" height="2000px"></canvas>
|
||||
<script src="{% static 'chart.min.js' %}"></script>
|
||||
<script src="{% static 'randomColor.js' %}"></script>
|
||||
<script>
|
||||
var ctx = document.getElementById("myChart").getContext('2d');
|
||||
baseColor = Math.round(Math.random()*255) + "," + Math.round(Math.random()*255) + "," + Math.round(Math.random()*255);
|
||||
console.log(baseColor)
|
||||
$.get("http://www.thecolorapi.com/scheme?rgb=" + baseColor + "&mode=analogic&count={{products | length}}", function( data ) {
|
||||
colors = data.colors
|
||||
var bgColor = []
|
||||
for(var i = 0; i < colors.length; i++){
|
||||
color = colors[i]
|
||||
bgColor.push("rgb(" + color.rgb.r + "," + color.rgb.g + "," + color.rgb.b + ")")
|
||||
}
|
||||
var bgColor = randomColor({count: {{products|length}}});
|
||||
var myChart = new Chart(ctx, {
|
||||
type: 'pie',
|
||||
data: {
|
||||
|
@ -107,7 +100,6 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
}, "json" );
|
||||
</script>
|
||||
</section>
|
||||
</section>
|
||||
|
|
|
@ -17,6 +17,7 @@ from django.utils import timezone
|
|||
from django.conf import settings
|
||||
from django.contrib.sites.shortcuts import get_current_site
|
||||
from django.utils.encoding import force_bytes
|
||||
from django.db.models import Sum
|
||||
|
||||
import simplejson as json
|
||||
from datetime import datetime, timedelta
|
||||
|
@ -163,7 +164,7 @@ def profile(request, pk):
|
|||
"quantities": quantities,
|
||||
"lastConsumptions": lastConsumptions,
|
||||
"lastMenus": lastMenus,
|
||||
"banishments": banishments
|
||||
"banishments": banishments,
|
||||
})
|
||||
|
||||
@active_required
|
||||
|
|
Loading…
Reference in a new issue