My requirement is I have to style a div dynamically with 3 colors.
I have done it with random colors applying this code
function randomColors() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 4; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
I have to repeat 3 Colors only, and that is going to be in a loop dynamically ! How can i do that?
I want only these 3 colors #09c5f9, #05f6d5, #a42cff dynamically set.
for(i=1; i <= pmap; i++){
$("#thumbnail"+i).css("background-color",randomColors());
}
I can think of two ways to do it.
1) The easiest if you're using jQuery (and In my opinion the correct way to do it) is to declare three classes and swap them using jQuery.
The CSS:
.teal{
background-color: #09c5f9;
}
.emerald{
background-color: #05f6d5;
}
.purple{
background-color: #a42cff;
}
and the javascript:
$("#some-element").removeClass("teal emerald").addClass("purple");
$("#some-element").removeClass("teal purple").addClass("emerald");
$("#some-element").removeClass("purple emerald").addClass("teal");
2) This way uses bare-metal JS and also uses the same programming style you used in the original post.
var colors = ["#09c5f9", "#05f6d5", "#a42cff"];
function getColor(colorNumber){
return colors[colorNumber];
}
Hope this helps.
function randomColors() {
var letters = '0123456789ABCDEF'.split('');
var color = '#';
for (var i = 0; i < 3; i++ ) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
you can see Demo, in which background-color of div will set randomly.
Demo
you can take hint from there.
Related
I have a function that returns a random color. I push these colors into an array. I don't want the colors to be repeated in the array. So I did this:
$scope.getRandomColor = function getRandomColor(arrayToCheckIfAlreadyContains) {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
//check if array contains the generated color
if(arrayToCheckIfAlreadyContains.indexOf(color) >= 0){
let nonRepeatColor = $scope.getRandomColor(arrayToCheckIfAlreadyContains);
console.log("color repeated", color, arrayToCheckIfAlreadyContains);
return nonRepeatColor;
}
return color;
}
But I don't know if this is efficient or will even work for sure. Also, it would be great if the colors are distinguishable. Sometimes I get colors that are almost same. How do I make sure that doesn't happen.
hsl can help you produce distinguishable colors. Try this.
function makeColor(colorNum, colors){
if (colors < 1) colors = 1;
// defaults to one color - avoid divide by zero
return colorNum * (360 / colors) % 360;
}
// This could be length of your array.
var totalDIVs = 20;
var totalColors = totalDIVs;
for (var i = 0; i < totalDIVs; i++){
var element = document.createElement('div');
document.body.appendChild(element);
var color = "hsl( " + makeColor(i, totalColors) + ", 100%, 50% )";
element.style.backgroundColor = color;
element.innerHTML = color;
}
You might consider using hsl instead of hex notation - pick a number between 0 and 359 for the initial color, then select the other colors such that they're equidistant. For example:
function getColors(num) {
const initialColor = Math.floor(Math.random() * 360);
const increment = 360 / num;
const hsls = [];
for (let i = 0; i < num; i++) {
hsls.push(Math.round((initialColor + (i * increment)) % 360));
}
return hsls;
}
function displayNew() {
container.innerHTML = '';
const hsls = getColors(input.value);
hsls.forEach((hsl) => {
const div = container.appendChild(document.createElement('div'));
div.style.backgroundColor = 'hsl(' + hsl + ', 100%, 50%)';
});
}
#container > div {
height: 30px;
}
<input id="input" onkeyup="displayNew()" type="number">
<div id="container"></div>
From your code I don't quite understand what you are doing if the color is already in the array: do you want to pick another random color until you find one color that is not in the array?
Anyways, since your second goal (distinguishable colors), I guess you need some extra work: every time you pick a random color, you need to check its similarity against ALL the colors in the array!
Something like the following:
getRandomColor = function getRandomColor(arrayToCheckIfAlreadyContains) {
let colorFound = true;
let letters = '0123456789ABCDEF';
do {
colorFound = true;
var randomColor = '#';
for (var i = 0; i < 6; i++) {
randomColor += letters[Math.floor(Math.random() * 16)];
}
arrayToCheckIfAlreadyContains.some(color => {
if (distanceBetweenColor(color, randomColor) < TRESHOLD) {
/* Branch taken when randomColor is too similar
* to an already existing color. */
colorFound = false;
return true;
}
return false;
});
} while (!colorFound);
}
Now, how implementing distanceBetweenColor()? You should use Delta-E algorithm: I suggest you to read this answer in SO: https://stackoverflow.com/a/15189004/6070423
EDIT: Notice the use of some instead of forEach: doing this, you stop the iteration as soon as you find a color that is too similar.
Basically I have JavaScript that will pick between two colors to change the classes colors but it is changing them to different colors of each other. So the .navbar will be purple when the .alert is in blue I need it to pick a color but make sure they are both the same color.
var colors = ['#2196F3','#8A229C'];
var boxes = document.querySelectorAll('.navbar-default, .alert-info');
for (i = 0; i < boxes.length; i++) {
// Pick a random color from the array 'colors'.
boxes[i].style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
}
Take the Math.random function out of the loop & get the random number only once
var colors = ['#2196F3', '#8A229C'];
var boxes = document.querySelectorAll('.navbar-default, .alert-info');
// random number will be generated only once
var getColor =Math.floor(Math.random() * colors.length)
for (i = 0; i < boxes.length; i++) {
boxes[i].style.backgroundColor = colors[getColor];
}
I've created a simple list from 0 to 10,000, where each li has a style type of upper-roman, a random background color as well as a child abbr to display hexadecimal string of the color.
When running the program I the list style changes from upper-roman to decimal after index 4000.
Can anyone explain to me what's happening here?
NOTE: Running the test takes a few seconds.
$(document).ready(readyHandler);
function readyHandler()
{
var $list = $("#MyList");
for (let i = 0; i < 10000; i++)
{
$list.append("<li><abbr title=\"\">Auto Insert " + i + "</abbr></li>");
}
colors = [];
for (let i = 0; i < $list.children().length; i++)
{
colors.push(getRandomColor());
}
$list.children().each(listItemsHandler);
}
function listItemsHandler(index, item)
{
var $target = $(item);
var color = colors[index];
$target.css("background-color", color);
$target.find("abbr").attr("title", color);
}
function getRandomColor()
{
var color = "#";
for (var i = 0; i < 3; i++)
{
var part = Math.round(Math.random() * 255).toString(16);
color += (part.length > 1) ? part : "0" + part;
}
return color;
}
#MyList
{
list-style-type: upper-roman;
margin-left: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ol id = "MyList"></ol>
At 4000, roman numerals begin to include the over-line which doesn't have an ASCII representation for display in plain text. For example, 4000 is IV with a line over the top. For this reason, there is no way for browser renderers to represent the numeral in char form as a <li> bullet.
The only way to represent this would be with an ADDITIONAL css property overline.
In short, it is not possible to represent numerals over 3999 as bullet items.
I have an Array of partial hex values that get random letters appended to them forming a full hex value.
These are then randomly applied to div layers effectively shading them different colors. However what I get currently is a "Matisse" effect instead of variations of one color.
If you force var color = setHex(); to var color = '#CC0'; in the getRandomColor function you will see the effect I am after.
I want to know why the "Matisse" effect is happening when I should only be passing one hex value. How do I stop this?
See example here: http://jsfiddle.net/fyQhg/
// Set Hex
function setHex() {
var hexArray = ['#CC0','#FF9','#339'];
var randomHex = hexArray[Math.floor(Math.random() * hexArray.length)];
document.getElementById('inner').innerHTML = randomHex;
return randomHex;
}
// random color
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = setHex();
for (var i = 0; i < 3; i++ ) {
color += letters[Math.round(Math.random() * 7)];
}
return color;
}
//ditribute random colors
function buttonClick() {
var i,j, colorblock = document.getElementsByClassName('shade');
for (i=0, j=colorblock.length; i<j; i++) {
colorblock[i].style.background = getRandomColor();
}
}
window.onload = buttonClick();
var base = setHex();
// random color
function getRandomColor() {
var letters = '0123456789ABCDEF'.split('');
var color = base;
for (var i = 0; i < 3; i++ ) {
color += letters[Math.round(Math.random() * 7)];
}
return color;
}
Declaring the base outside of the method works. Example
Explaination
In this method:
for (i=0, j=colorblock.length; i<j; i++) {
colorblock[i].style.background = getRandomColor();
}
You are calling getRandomColor() repeatedly in that loop. Therefore you are also calling setHex() repeatedly which is creating a new random color each time the loop loops.
So by moving setHex() outside the method that is inside that loop into base you are effectively only calling setHex() once per load.
Why?
Because function getRandomColor() calls setHex() which returns something else every time.
How to stop?
var color = setHex();
for (i=0, j=colorblock.length; i<j; i++) {
colorblock[i].style.background = getRandomColor(color);
}
}
and
function getRandomColor(color) {
var letters = '0123456789ABCDEF'.split('');
for (var i = 0; i < 3; i++ ) {
color += letters[Math.round(Math.random() * 7)];
}
return color;
}
Every time you call getRandomColor you are calling setHex and picking another random base color. Just set the base color once, store it in a variable and use it.
For example:
var hexBase;
function setHex() {
var hexArray = ['#CC0','#FF9','#339'];
if (!hexBase) {
hexBase = hexArray[Math.floor(Math.random() * hexArray.length)];
}
return hexBase;
}
Fiddle
It seems you were close to this solution because you were storing the result of setHex in a div, but you never checked it again. Also, you shouldn't need to store things in the DOM when you can just store them in JavaScript.
Finally, if you want to avoid the global variable, you can wrap the whole thing in a function (e.g. your onload function or a IIFE).
So I've read a few similar questions, and I've managed to do things like change the background colour, but I have not yet been able to get this to work;
What I want, is for each subsequent letter on a page to be randomly coloured. The colour space used isn't really important, as that's easy to fix once it actually works (am using this one at the moment), but I can't even get the text to change colour yet. I'm hoping I'm just making a silly mistake somewhere...
This is what i'm trying at the moment; and it kind of works, but it's very dependant on what tagName i use, and because of the nature of most webpages, it can break a lot of things if i'm not careful...
jsFiddle
var elements = document.getElementsByTagName('p');
for(var i=0,l=elements.length;i<l;++i) {
var str = elements[i].textContent;
elements[i].innerHTML = '';
for(var j=0,ll=str.length;j<ll;++j) {
var n = document.createElement('span');
elements[i].appendChild(n);
n.textContent = str[j];
n.style.color = get_random_colour();
}
}
function get_random_colour() {
var letters = '0123456789ABCDEF'.split('');
var colour = '#';
for (var i = 0; i < 6; i++ ) {
colour += letters[Math.round(Math.random() * 15)];
}
return colour;
}
In this example, p works fine, and doesn't seem to break anything, but if I do * or html or body then it breaks the page. Is there a way to get all the text on the page, and not break it?
And another thing; I later changed the colour function to hopefully only pick colours that are in HSV(random,1,1) so that i only get nice bright colours, but it's not working. I'm presuming I just have some JS error in there, but I'm not that familiar with JS, so I'm finding it hard to find...
Here are the changes
To do this, you will want to recurse through just the text nodes, careful not to trash child HTML elements.
See the demo at jsFiddle.
var x = document.querySelector ("body"); // Etc.
buggerTextNodesIn (x);
function buggerTextNodesIn (node) {
var wrapClass = 'gmColorBarf';
function turnerizeTextNodes (node) {
if (node.nodeType === Node.TEXT_NODE) {
//--- Skip this node if it's already been wrapped.
if ( ! node.parentNode.classList.contains (wrapClass) ) {
var oldText = node.nodeValue;
var parent = node.parentNode;
for (var J = 0, len = oldText.length; J < len; ++J) {
var wrapSpan = document.createElement ("span");
wrapSpan.classList.add (wrapClass);
wrapSpan.textContent = oldText[J];
wrapSpan.style.color = getRandomColor ();
parent.insertBefore (wrapSpan, node);
}
parent.removeChild (node);
}
}
else if (node.nodeType === Node.ELEMENT_NODE) {
/*--- IMPORTANT! Start "bottom up" since we will be adding
gazillions of nodes and "top down" would skew our length measurement.
*/
for (var K = node.childNodes.length - 1; K >= 0; --K) {
turnerizeTextNodes (node.childNodes[K] );
}
}
}
turnerizeTextNodes (node);
}
function getRandomColor () {
var letters = '0123456789ABCDEF'.split ('');
var color = '#';
for (var J = 0; J < 6; ++J) {
color += letters[Math.round(Math.random() * 15)];
}
return color;
}
Note that to get iframed content, the easiest way is to tune the #include, #exclude, and/or #match directives to trigger on the iframe URL(s) -- if they don't already.