Is it possible to use javascript to determine what color is one shade darker than the current background? Maybe some hexadecimal addition/subtraction?
I have a menu that can be any color and if it wasn't too difficult it would be great if the submenu could be one shade darker. Does anyone know how to achieve this effect?
Something like this:
function shadeColor(color, shade) {
var colorInt = parseInt(color.substring(1),16);
var R = (colorInt & 0xFF0000) >> 16;
var G = (colorInt & 0x00FF00) >> 8;
var B = (colorInt & 0x0000FF) >> 0;
R = R + Math.floor((shade/255)*R);
G = G + Math.floor((shade/255)*G);
B = B + Math.floor((shade/255)*B);
var newColorInt = (R<<16) + (G<<8) + (B);
var newColorStr = "#"+newColorInt.toString(16);
return newColorStr;
}
Usage:
var newColor = shadeColor("#AA2222", -10);
alert(newColor); //Results in #a32020
Here is an example code to test it: http://pastebin.com/g6phySEv
as AB comments, 'shade' isn't very well defined. nonetheless, it might be easier to think of this in some other colour representation, such as 'V' in hsv.
you could either convert, decrease v and convert back, or figure out what decreasing v maps to in rgb hex
Related
I'm trying to convert a Javascript function to Python. Most of it was no problem but there's one statement I'm not sure how to convert:
color = +("0x" + color.slice(1).replace(color.length < 5 && /./g, '$&$&'))
The Python so far is:
color = +("0x" + color[:1].replace(
len(color) < 5 and /./g, '$&$&')
)
idk what +() or /./g are for. The complete JS function is:
function lightOrDark(color) {
// Variables for red, green, blue values
var r, g, b, hsp;
var threshold = 127.5
// Check the format of the color, HEX or RGB?
if (color.match(/^rgb/)) {
// If RGB --> store the red, green, blue values in separate variables
color = color.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
r = color[1];
g = color[2];
b = color[3];
} else {
// If hex --> Convert it to RGB: http://gist.github.com/983661
color = +("0x" + color.slice(1).replace(color.length < 5 && /./g, '$&$&'))
console.log(color)
r = color >> 16;
g = color >> 8 & 255;
b = color & 255;
}
// HSP (Highly Sensitive Poo) equation from http://alienryderflex.com/hsp.html
hsp = Math.sqrt(
0.299 * (r * r) +
0.587 * (g * g) +
0.114 * (b * b)
)
// Using the HSP value, determine whether the color is light or dark
return hsp > threshold;
}
The /./g is a regular expression and the +() coerces a string into a number (and the 0x makes it hexadecimal). In Python you'd use the re module and the int() builtin for that.
The replace duplicates the characters if the color is written in its short form. The Python equivalent is a re.sub(). You use a backslash instead of a dollar for back-references in Python's regex dialect. So \1 refers to the first matching group.
>>> import re
>>> color = "#123456"
>>> re.sub("(.)", r"\1\1" if len(color)<5 else r"\1", color[1:])
'123456'
>>> color = "#abc"
>>> re.sub("(.)", r"\1\1" if len(color)<5 else r"\1", color[1:])
'aabbcc'
So for a short string, this replaces each character with itself twice, but for a long string this replaces each character with itself once (no change).
Then you use a base of 16 to convert a hexadecimal string to an int:
>>> int('aabbcc', 16)
11189196
All together:
int(re.sub("(.)", r"\1\1" if len(color)<5 else r"\1", color[1:]), 16)
That's a fairly compact line of code. Let's deconstruct it.
First, +() is the same as Number() in this case it can also be alternatively implemented using parseInt().
Next /./g is just a regular expression. On its own it does not do anything. It is just a value like "hello" or 3. It is the first argument to replace().
So the line can be rewritten as:
let temp1 = color.slice(1); // In this case can also be rewritten as color.substr(1)
// It basically removes the first character
if (color.length < 5) {
temp1 = temp1.replace(/./g, '$&$&'); // This replaces each character with itself twice.
// For example "123" is replaced with "112233"
}
let temp2 = "0x" + temp1. // This adds "0x" to the previous string so that
// it will look like a hexadecimal number.
color = parseInt(temp2); // Convert string of hexadecimal number to a number.
I personally don't know Python but the above should be easy to rewrite in any language.
In case you're not comfortable with regular expressions you can rewrite the number doubling code using a loop. The following is an alternative implementation that does not use any fancy functions/methods at all:
// Remove first character (color.slice(1))
let temp1 = "";
for (let i=1; i<color.length; i++) { // copy every character except color[0]
temp1 = temp1 + color[i];
}
// Convert 3-letter color to 6-letter color, eg #69a to #6699aa
if (color.length < 5) {
let temp2 = "";
for (let i=0; i<3; i++) {
temp2 = temp2 + temp1[i] + temp1[i];
}
temp1 = temp2;
}
let temp3 = "0x" + temp1. // This adds "0x" to the previous string so that
// it will look like a hexadecimal number.
color = parseInt(temp3); // Convert string of hexadecimal number to a number.
Note that both versions of the code above does exactly the same thing as the line:
color = +("0x" + color.slice(1).replace(color.length < 5 && /./g, '$&$&'))
My code:
function calculate(sides) {
var sides = prompt("Triangle side lengths in cm
(number,number,number)"); //String will be size of 4
var nsides = sides.split(" "); //Splits content into array format
//Convert Array instances to integer values a,b,c
for(var loop=0;loop<=nsides.length;loop++) {
if(nsides[loop]!=",")
a = nsides[loop];
if(nsides[loop]!=",")
b = nsides[loop];
if(nsides[loop]!=",")
c= nsides[loop];
} //End for
//Area Calculation
var s = (a+b+c)*0.5 ; //represents the semiperimeter
var area = Math.sqrt(s*(s-a)*s(s-b)*(s-c)) //area calculation
//Result
sides = alert("The triangle's area is " + area + " square cm");
} //End function
//Main calculate(length);
I'm looking to set side a, b, and c to integers; however in order to do that I have to go through the array (I first converted it to an array from a string)
I'm going to add in some standard validation later; as of now I can't seem to place the values from the string entered into 3 separate integers being a b and c.
Other than that, is there a better way i can go about this?
Thanks.
Maybe I misunderstand your question, but is this what you're looking for?
var sides = prompt("Triangle side lengths in cm (number,number,number)");
var nsides = sides.split(",");
var a = +nsides[0];
var b = +nsides[1];
var c = +nsides[2];
//Area Calculation
//...
Note the use of + to force the strings from the array into numbers.
function calculate() {
var sides = prompt("Triangle side lengths in cm (number,number,number)"),
nsides = sides.split(","),
a = parseFloat(nsides[0]),
b = parseFloat(nsides[1]),
c = parseFloat(nsides[2]),
s = (a + b + c) / 2,
area = Math.sqrt(s * (s - a) * (s - b) * (s - c));
alert("The triangle's area is " + area + " square cm");
return area; // return the area
}
First of all I removed your parameter, it was totally unnecessary and was overwritten by the declaration of sides in the first line. Then I changed the split to , so it follows your instructions. Then you need to parse the string to integers using parseInt and specifiying the radix 10, then you can go on with your calculations. Just a last thing, you wrote Math.sqrt(s*(s-a)*s(s-b)*(s-c)), see that s(s-b) causes an exception because you are using a number to be called as a function.
I have color code like 0xff3a9bda, 0xff73bbf3. I really don't know about this color type as I know that these are NOT RGB, aRGB, HSB, or HEX.
As I am working on web application, my problem is, I can get color code with JavaScript in RGB and HTML color code for any color and I want to convert this color to above specified color type code.
Could anybody please give me an idea or soluton for this?
Are you sure this isn't RGBA ?
0xff3a9bda would be rgba(255,58,155,0.85) (RGBA) or rgba(58,155,218,1) (ARGB)
You can do the conversion like this:
var c = 0xff3a9bda;
var r = (c & (0xff << 24)) >>> 24;
var g = (c & (0xff << 16)) >>> 16;
var b = (c & (0xff << 8)) >>> 8;
var a = (c & 0xff) / 0xff;
var rgba = 'rgba(' + [r,g,b,a].join(',') + ')';
Or like this:
var c = 0xff3a9bda;
var a = ((c & (0xff << 24)) >>> 24) / 0xff;
var r = (c & (0xff << 16)) >>> 16;
var g = (c & (0xff << 8)) >>> 8;
var b = c & 0xff;
var rgba = 'rgba(' + [r,g,b,a].join(',') + ')';
Try here: http://jsfiddle.net/gX6ds/1/
Convert #RRGGBB to this format:
var rgb = 'AABBCC';
var c = 0xff000000 + parseInt(rgb, 16);
alert('0x' + c.toString(16));
Convert R, G, B values to this format:
var R = 0xAA, G = 0xBB, B = 0xCC;
var c = 0xff000000 + (R << 16) + (G << 8) + B;
alert('0x' + c.toString(16));
There's no need to overcomplicate the matter. You've got a 32-bit color value there, which almost certainly means you have 4 color components (R, G, B, A) at 8 bits per component. If the format is not ARGB then it is probably RGBA, but that will be up to you to figure out. It is certainly simple enough to do so via trial and error.
In any case once you know which bits represent which color components, all you need to do is extract out R, G, and B (see arnaud576875's answer) and then concatenate them together like #<R><G><B> to get your HTML color code.
Then you take your A component and set it as the opacity of whatever element you want to apply this color to. As in:
#coloredElem {
color: #<R><G><B>;
opacity: <A / 255.0>;
}
I found the following awesome script to create a random color with javascript.
var randColor = '#'+(Math.random()*0xFFFFFF<<0).toString(16);
only problem I have with this script is that it's not garanteed that it returns a normal 7digit hex string.
sometimes it's just 6 digits long like #e1d19.
is there a way to kind of force a 7 digit hex value?
thank you for your help.
edit: this is my actual problem:
function randColor() {
var randColor = '#'+(Math.random()*0xFFFFFF<<0).toString(16);
return randColor;
}
for (var i=0; i<100; i++) {
$("#colorpicker").append("<div class='color' title="+randColor()+" style='background:"+randColor()+"'></div>");
}
I'm creating little divs with a random color, when I click on them I grab their title attribute and I'm coloring the background of my body.
however currently my code ends in
<div style="background:rgb(176, 249, 252);" title="#8bc47d" class="color"></div>
so when I grab the title attribute the color I'm giving my body is a different one than the little div shows.
You could just pad it yourself:
function randomColor() {
var rc = (~~(Math.random() * 0xFFFFFF)).toString(16);
return '#' + new Array(7 - rc.length).join('0') + rc;
}
This trick:
new Array(n).join(char)
is a way to get n - 1 copies of "char" in a string. I subtracted the raw length of the value from 7 instead of 6 so that when the string is 5 characters long I get one zero, when 4 I get two, etc.
edit — of course (as mentioned in other answers) you can get pad zeros like this too:
return '#' + "000000".slice(rc.length) + rc;
I'd have to do one of those silly jsperf things to see which is faster :-)
var randColor = '#'+(0xFFFFFFFF-Math.random()*0xFFFFFFFF).toString(16).substr(0, 6);
Here's my (low tech) attempt:
var randColor = (Math.random()*0xFFFFFF<<0).toString(16);
while( randColor.length < 6 ) {
randColor = '0' + randColor;
}
randColor = '#' + randColor;
I think your best bet is to make 3 sets of 2-digit hex numbers (one for each R, G, and B). Then, simply pad-left each with a 0 to ensure they are all two digits. Maybe something like this untested code I am providing for reference :)
//I am GUESSING that this is how you get a 2-digit hex value ranging 0-255
var r = PadDigits(Math.random()*0xFF<<0).toString(16),2);
var g = PadDigits(Math.random()*0xFF<<0).toString(16),2);
var b = PadDigits(Math.random()*0xFF<<0).toString(16),2);
var randColor = '#'+r+g+b;
function PadDigits(n, totalDigits)
{
n = n.toString();
var pd = '';
if (totalDigits > n.length)
{
for (i=0; i < (totalDigits-n.length); i++)
{
pd += '0';
}
}
return pd + n.toString();
}
You want it to be six digits, not seven, but the resulting string should be seven characters long including the hash. Nitpicking, I know, but still. How about this:
var color = (Math.random() * 0xFFFFFF << 0).toString(16);
"#" + String(color + "000000").slice(0, 6);
If you want to pad in the beginning instead, this should do it:
var color = (Math.random() * 0xFFFFFF << 0).toString(16);
"#" + String("000000" + color).slice(-6);
To clarify, this will pad the whole string, not separate channels. I'm thinking that since you're not randomizing per channel, there's really only the red or blue channel you're looking to pad (probably red, i.e., the second snippet).
Your second problem is that you're calling randColor twice, giving you two different colors. You'll want to store the generated color in a variable and use the variable twice instead.
for (var i=0; i<100; i++) {
var color = randColor();
$("#colorpicker").append("<div class='color' title=" + color + " style='background:" + color + "'></div>");
}
Nobody posted it and this is the shortest code i got to get a random color.
'#'+Math.random().toString(16).slice(-6)
It will get a random float number 0.437920...
Convert it to Hexadecimal, you'll get something like that 0.7c13b41830e33
Take the 6 last character which will provide you a random color #
Easy to understand, short and efficient.
Whilst looking for a "B-V color index to temperature conversion formula"
I found this javascript:
var C1 = 3.979145;
var C2 = -0.654499;
var C3 = 1.74069;
var C4 = -4.608815;
var C5 = 6.7926;
var C6 = -5.39691;
var C7 = 2.19297;
var C8 = -.359496;
bmv = parseFloat(BV);
with (Math) {
logt=
C1
+C2*bmv
+C3*pow(bmv,2)
+C4*pow(bmv,3)
+C5*pow(bmv,4)
+C6*pow(bmv,5)
+C7*pow(bmv,6)
+C8*pow(bmv,7);
t=pow(10,logt);
}
Which is supposed to convert B-V color index to temperature.
Does anyone understand how this is working and if the output value is an approximation for temperature in celcius or kelvin?
Is it something to do with products of logarithms?
The B-V index is basically a function that transforms the difference between the intensity of the light passing through a 'blue' resp. a 'visible' filter into a temperature.
This function can be approached as 109th degree polynomial, where the polynomial is basically C1*bv0 + C2*bv1 + ... + C8*bv7.
Since we're talking stellar temperatures, the output will be in Kelvin.
Note that a Horner algorithm for polynomial functions is often more precise...
I think temperatures are in Kelvin because its very common for astronomers to use Kelvin rather than Celcius.
Look here.
And,
if logbaseX = Y then X = baseY
log10(t)= C1 +C2*bmv +C3*pow(bmv,2) +C4*pow(bmv,3)
+C5*pow(bmv,4) +C6*pow(bmv,5) +C7*pow(bmv,6)
+C8*pow(bmv,7);
t = pow(10,log10(t));
Also, this formula is very much related to Taylor Series.
// Horners algorithm for polynomials
function Horner(a,n,x)
{
var result = a[n];
var i = n - 1;
while( i >= 0)
{
result = result*x + a[i];
i-=1;
}
return result;
}
In your case,
Array Cs = {C1,C2,C3,C4,C5,C6,C7,C8};
var temperature = Horner(Cs,8,bmv);