Simple way to avoid previous number in Math.random? - javascript

I am working on a random quote/color generator. I want it to avoid repeating previous color (in a simple/easy/understandable way as I'm a complete beginner in JS/jQuery).
Here is my code, I don't know what is wrong with it.
var colors = ["#8ee5ee", "#ee82ee", "#469649", "#ff4444", "#ffa500", "#dddddd", "#efc3c8", "#d2d449", "#f91589","#906161","#875d39","#ffdab9","#d1e529","#3a718b"];
var color = Math.floor(Math.random() * colors.length);
var lastcolor = 0;
while(color === lastcolor){
color = Math.floor(Math.random() * colors.length) + 1;
}
$("body").animate({backgroundColor: colors[color]}, 1000);
$("#new-quote").animate({backgroundColor: colors[color]}, 1000);
$("h6").fadeOut(1000);
$("p").fadeOut(1000);
});
});
Basically, when I click a button (#new-quote), the current background color changes to another random color and so on. But now and then the color doesn't change as the machine chose the same number/color as the current one. I'm trying to avoid that!

I guess there's some sort of loop around the code you provided. Then you shouldn't reset the color, but to assign it to the previous one.
var colors = ["#8ee5ee", "#ee82ee", "#469649", "#ff4444", "#ffa500", "#dddddd", "#efc3c8", "#d2d449", "#f91589","#906161","#875d39","#ffdab9","#d1e529","#3a718b"];
var color = Math.floor(Math.random() * colors.length);
while(color === lastcolor){
color = Math.floor(Math.random() * colors.length) + 1;
}
lastcolor = color;
And of course you should define your lastcolor at the beginning of the script. Place
var lastcolor = 0;
after <script> tag opens.

You could use simply a new random value, because if you add one, you might get undefined if the random value is the index of the last element.
while (color === lastcolor){
color = Math.floor(Math.random() * colors.length); // + 1;
// without ^^^^^^^
}
A better style would be one assignment with a do ... while loop.
var colors = ["#8ee5ee", "#ee82ee", "#469649", "#ff4444", "#ffa500", "#dddddd", "#efc3c8", "#d2d449", "#f91589", "#906161", "#875d39", "#ffdab9", "#d1e529", "#3a718b"],
color,
lastcolor = 0;
do {
color = Math.floor(Math.random() * colors.length);
} while(color === lastcolor);
lastcolor = color;

Simpler method: Use splice() method to remove the current element from your colors array so that every time you run the code, the previously occurring element wont occur again.
var color = Math.floor(Math.random() * colors.length);
//from index = color, delete that element using splice(index, # of elements to delete)
colors.splice(color, 1);
//now colors array will not contain the colors[color] element
for (var i = 0; i < colors.length; i++) {
console.log(colors[i]);
}

Related

How to stop random color from repeating?

the title changes color randomly when clicked but it repeates the same color often (I don't want it to repeat the same color in the array twice in a row). I tried to fix this with an if statement but im not sure why it didn't work.
var title = document.querySelector(".title");
function changeColor() {
let newArray = ["DarkSalmon", "LightSalmon", "Crimson", "Red",
"DeepPink", "YellowGreen", "GhostWhite"
];
let random = Math.floor(Math.random() *
Math.floor(newArray.length - 1));
console.log(random);
if (title.style.color !== newArray[random]) {
title.style.color = newArray[random];
}
}
title.addEventListener("click", changeColor);
<h1 class='title'>Berserk</h1>
If don't want colors to get repeated in a row, you could just add an else statement to your if statement.
I found the error! It's in the capitalization of your color names... Change them to all lowercase and it will magically
var title = document.querySelector(".title");
function changeColor() {
let newArray = ["darksalmon", "lightsalmon", "crimson", "red", "deeppink", "yellowgreen", "ghostwhite"];
let random = Math.floor(Math.random() * Math.floor(newArray.length - 1));
if (title.style.color != newArray[random]) {
title.style.color = newArray[random];
console.log(title.style.color);
} else {
changeColor();
}
}
title.addEventListener("click", changeColor);
<h1 class='title'>Berserk</h1>
This will let each color be selected exactly once. Once all colors have been used, the list is refreshed so all colors can be randomly selected again, and so on.
// Identifies header element & defines initial colors array and colors array
const header = document.getElementsByClassName("title")[0];
const initialColors = ["DarkSalmon", "LightSalmon", "Crimson", "Red", "DeepPink", "YellowGreen"];
let colors = [];
// Calls `changeColor` when the header is clicked
header.addEventListener("click", changeColor);
// Defines the `changeColor` function
function changeColor(){
// Remembers the most recent color (formatted as lower-case)
let previousColor = header.style.color.toLowerCase();
// Makes all colors available whenever no colors are left (including on first click)
if(colors.length === 0){
// Copies the `initialColors` array, and returns the copy
// (See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice)
colors = initialColors.slice();
}
// Cuts a random color out of the colors array
let newColor = removeRandFrom(colors);
// If removed color happens to match previous color, forces an additional change
// (Can only ever happen immediately after the `colors` array has been replenished)
if(newColor === previousColor){
newColor = removeRandFrom(colors);
}
// Sets text color to whichever color was just randomly removed
header.style.color = newColor;
}
// Defines the `removeRandFrom` helper function
function removeRandFrom(arr){
// Gets a psuedo-random number
const index = Math.floor(Math.random() * arr.length);
// Removes and returns the element at the randomly selected index
// (See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/splice)
return arr.splice(index, 1);
}
<h1 class='title'>Berserk</h1>
References:
MDN - slice
MDN - splice
The problem is that when the color would repeat and your if statement prevents that from happening, nothing else happens, either. So the effect is the same as a repeating color.
Instead of the if statement, you could use a ẁhile loop to randomly select new colors until you have one that is different from the current.
let random;
do {
random = Math.floor(Math.random() * Math.floor(newArray.length - 1));
} while (title.style.color === newArray[random]);
title.style.color = newArray[random];

Javascript button that changes properties of html elements using DOM Events

I'm trying to make a button that changes the color of the paragraph elements to a random color whenever an user clicks the button. It doesn't seem to work and my text editor (Brackets) are telling me I made 12 mistakes but I don't really sees it.
This is what I wrote towards the end of my webpage:
<button id="button1">Color Changer</button>
</div>
</div>
</div>
<script type="text/javascript" src=script.js></script>
</body>
</html>
This is script.js:
var button1El = document.getElementById("button1");
var paragraphsEl = document.getElementsByTagName("p");
var colorChange = function () {
var r = Math.floor(Math.random() * 255);
var g = Math.floor(Math.random() * 255);
var b = Math.floor(Math.random() * 255);
for (var i = 0; i < paragraphsEl.length; i += 1) {
paragraphsEl[i].style.color = rgb(r, g, b);
}
}
button1El.addEventListener("click", colorChange);
Thanks in advance!
Few things wrong here, which I listed in a comment above:
paragraphsEl is an array, you can't set style.color on an array, you need to iterate over each of the items in the array to set that value
style.color will take a string value, you're trying to call a function called rgb, which doesn't exist, pass in a string to make this work
Use integers in RGB with `Math.floor(Math.random() * 255)
Close, but you seem to be forgetting how a few things work.
Remember that breaking the issue down into pieces and figuring out what data types are being used in certain places will help you avoid a lot of these issues.
var button1El = document.getElementById("button1");
var paragraphsElements = document.getElementsByTagName("p");
var colorChange = function () {
var r = Math.floor(Math.random() * 255);
var g = Math.floor(Math.random() * 255);
var b = Math.floor(Math.random() * 255);
for(var i = 0; i < paragraphsElements.length; i++) {
paragraphsElements[i].style.color = 'rgb(' + r + ', ' + g + ', ' + b + ')';
}
}
button1El.addEventListener("click", colorChange);
Here's a codepen link that demonstrates working code, I had made a couple mistakes because I didn't test it:
https://codepen.io/anon/pen/PdmKVd

Calling a JS function to invert background-color inside a jQuery .each function

There is a question in this post about calling a JS function inside a jQuery document ready function; however, it does not answer my question.
I am trying to write a function that loops over the divs in an html doc, giving the div backgrounds a random color. This portion is working. In the next step, I want to invert the divs background color using the invertColor function; however, I cannot figure out how to incorporate this function into the jQuery code.
The working code should first assign each div a random color and then invert that color using the invertColor function.
I tried calling the invertColor function both inside and outside of the .each function.
Here is the current JS code:
function invertColor(hexTripletColor) {
var color = hexTripletColor;
color = color.substring(1); // remove #
color = parseInt(color, 16); // convert to integer
color = 0xFFFFFF ^ color; // invert three bytes
color = color.toString(16); // convert to hex
color = ("000000" + color).slice(-6); // pad with leading zeros
color = "#" + color; // prepend #return color;
}
$(document).ready(function() {
$("div").each(function() {
var color = ["#b27485", "#74b2a1", "#cedbd9", "#abece4", "#ecabb3", "#1cdb4f", "#7e8dab", ];
var rand = Math.floor(Math.random() * color.length);
$(this).css("background-color", color[rand]);
$(this).css(invertColor(color));
$(function() {
invertedColor(color);
});
});
});
The HTML code and output can be viewed in this fiddle:
invertColor does not return anything so you are setting css(undefined); and I am not sure where hexTripletColor is defined. And you are passing the array and not the color from the array to your method. $(this).css(invertColor(color));
So you are looking for something like this, I set the color to the inverted value that you calculate, not sure what exactly you were trying to set.
function invertColor(hexTripletColor) {
var color = hexTripletColor;
color = color.substring(1); // remove #
color = parseInt(color, 16); // convert to integer
color = 0xFFFFFF ^ color; // invert three bytes
color = color.toString(16); // convert to hex
color = ("000000" + color).slice(-6); // pad with leading zeros
color = "#" + color; // prepend #return color;
return {
color: color
};
}
$(document).ready(function() {
$("div").each(function() {
var color = ["#b27485", "#74b2a1", "#cedbd9", "#abece4", "#ecabb3", "#1cdb4f", "#7e8dab", ];
var rand = Math.floor(Math.random() * color.length);
$(this).css("background-color", color[rand]);
$(this).css(invertColor(color[rand]));
});
});
invertColor() doesn’t return anything, so just add a return statement at the end like so:
function invertColor(hexTripletColor) {
var color = hexTripletColor;
color = color.substring(1); // remove #
color = parseInt(color, 16); // convert to integer
color = 0xFFFFFF ^ color; // invert three bytes
color = color.toString(16); // convert to hex
color = ("000000" + color).slice(-6); // pad with leading zeros
color = "#" + color; // prepend #return color;
return color;
}
Then change $(this).css(invertColor(color)); to $(this).css("background-color", invertColor(color));

Insert a delay between every .each

I've found a few other questions pertaining to this, but the answers didn't work for me, so I'm checking to see if there's anything newer or something that will work. Essentially, I'm updating divs in a .each in jQuery, but I want them to update a couple seconds apart. Here's what I've tried:
function randomColor() {
$('div').each(function(i) {
setTimeout(function() {
var colors = ['blue', 'green'];
var n = Math.floor(Math.random() * colors.length);
var color = colors[n];
$(this).addClass(color);
}, 500 + (i * 500));
});
}
I've also tried using a separate function:
function randomColor() {
$('div').each(function(i) {
var time = 500;
setTimeout(function() {
applyColor($(this));
}, time);
time += 500;
});
}
function applyColor(div) {
var colors = ['blue', 'green'];
var n = Math.floor(Math.random() * colors.length);
var color = colors[n];
$(div).addClass(color);
}
Both of these return no errors, but the divs don't get updated. If I run this code without the setTimeout, it works perfectly. I've also tried using delay in this fashion:
$('div').delay(1000).each(function() {
...
});
And that delayed by 1 second, but then updated everything at once after that second. If I move the delay down near the addClass line, it stops working altogether again. Can anyone point out this (hopefully simple) mistake?
You're creating an anonymous function and inside that function this has a different meaning (i.e., the window object).
One solution is to cache this:
var $this = $(this);
setTimeout(function() {
var colors = ['blue', 'green'];
var n = Math.floor(Math.random() * colors.length);
var color = colors[n];
$this.addClass(color);
}, 500 + (i * 500));
I think what you want to do is:
function randomColor() {
var colors = ['blue', 'green'];
var n = Math.floor(Math.random() * colors.length);
var color = colors[n];
$('div').each(function() {
$(this).delay(1000).addClass(color);
});
});
When fuction is run, it would randomly pick a Class name ('blue' or 'green'). It would then update the DIV after waiting 1 second. Then move to the next in the Each loop.
Here's an example using setTimeout and an increment'er to loop over the divs, rather than the jQuery each method.
JSFiddle
(function randomColorDiv(ii) {
var colors = ['blue', 'green']
var n = Math.floor(Math.random() * colors.length)
var color = colors[n]
$($('div')[ii]).addClass(color)
if ( ii < $('div').length ) {
setTimeout(function() {
randomColorDiv(++ii)
}, 1000)
}
}(0))

Create an array of colors (about 100) in JavaScript, but the colors must be quite distinct

I want to create an array of colors in javascript, for that, I used the js file rainbowvis.js here, I have 100 colors, but they are not really distinct.
I should be able to see the difference because I will use this table to a chart.
Is it possible with rainbowvis.js or is there an other solution?
To generate 100 colors (each color from 1 to 1000000 - change it if you need other range):
var colors = [];
while (colors.length < 100) {
do {
var color = Math.floor((Math.random()*1000000)+1);
} while (colors.indexOf(color) >= 0);
colors.push("#" + ("000000" + color.toString(16)).slice(-6));
}
console.log(colors);
FIDDLE
Use distinct-colors.
It generates a palette of visually distinct colors.
Heres a faster alternative, we could employ a random number generator and use the 'rgb()' color model instead
var COLORS = [];
while (COLORS.length < 100) {
COLORS.push(`rgb(${rand(0, 255)}, ${rand(0, 255)}, ${rand(0, 255)})`);
}
// random number generator
function rand(frm, to) {
return ~~(Math.random() * (to - frm)) + frm;
}
Use RGB colors.
var colors=[], tds='';
for( var r=0; r<256; r+=25 ){
for( var g=0; g<256; g+=25 ){
for( var b=0; b<256; b+=25 ){
var c="rgb("+r+","+g+","+b+")";
tds+="<p style='display:inline-block;margin:0;width:32px;height:32px;background:"+c+"'></p>";
colors.push(c);
}
}
}
document.body.innerHTML=tds;

Categories

Resources