EDIT: I misconstrued the question. Thought they meant 'percentages' in terms of color opacity. I left that code-snippet in the end of this answer, in case it's of use to anyone. Apologies for the confusion.
Code Improvement
In terms of code, here's a quick way to reduce all those lines. When you have such code as this (with so many if-else
the first thing you must question yourself is... What happens if tomorrow you add a new color to the array? What if you add 100 colors? Then you'd need 100 more if-else
cases. Absolute nightmare, right? So let's think of a way to fix that.
Keep in mind that coding is all you want, you set the rules and magic. It's beautiful. So, how can you use the information you have in colors
so as not to repeat yourself?
STEP ONE
Add CSS rules to the box where you want to show the color. The CSS rules would match the names of the colors you have inside your variable colors
so you can quickly add/remove
CSS classes.
For the code snippet I removed various colors so as not to write so many CSS rules. When you improve some, look up wonderful SASS
, it'd be perfect for this kind of example.
STEP 2
Remove all those if/else
statements and for loop
and make use of your jQuery
library for all its got, like the functions addClass()
and removeClass()
. So what you actually might want to do is have a single HTML element as target for your random color, and chance it's class according to the random color generated. The CSS class will be the one in charge of outputting the appropriate color generated.
In the JS
code, all you have to do is get your random color, then clean the HTML element target of your random color, and then add the generated color. (Sorry for such long wording).
Super simple, super cute.
Code snippet for this improvement:
var colors = ["red", "yellow", "blue", "green"];
$(document).ready(function() {
$('#spin-btn').click(function() {
var output = colors.length,
randomNumber = Math.floor(Math.random() * output),
color_container = $('#color-output');
var color = colors[randomNumber];
color_container.removeClass(); //Cleanup previous color classes
color_container.addClass(color);
});
});
#spin-btn {
padding: 20px;
margin-bottom: 10px;
background-color: #eee;
cursor: pointer;
}
#color-output {
width: 100px;
height: 100px;
}
.default { background: gray; }
.blue { background: blue;}
.yellow { background: yellow;}
.red { background: red; }
.green { background: green;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="spin-btn">Generate random color</div>
<div id="color-output" class="default"></div>
So if tomorrow you added 100 new colors, you'd just update the colors
variable, and add the pertaining CSS classes. Your actual JS code would not change. Yay DRY! (Don't-repeat-yourself).
Adding probability to Code Improvement
In terms of probability and letting the users choose what color most likely should appear, I am basing my answer on this link provided by user Rory in comments to original question.
You'd have to dynamically manipulate your colors
variable to include more/less of the colors that the user wants to come out.
You can start off with your default array of colors
, then pass it to a function that adds the pertaining colors the users have chosen, then choose a random color based on the manipulated colors
array.
For that I've added the following functions (which can be greatly improved to be more dynamic, this is just a stepping stone to get started, I leave the improvement off to you).
function getColors() {
var blue_prob = $('#blue-prob').val(), //These are your inputs
red_prob = $('#red-prob').val();
var colors = ["red", "yellow", "blue"]; // default colors
addProbability(colors, blue_prob - 1, "blue"); //blue_prob - 1 because "blue" already appears once
addProbability(colors, red_prob - 1, "red"); //red_prob - 1 because "red" already appears once
return colors;
}
function addProbability(colors, probability, color) {
for (let i = 0; i < probability; ++i)
colors.push(color);
}
Code snippet for this part:
It's best to run at at full screen, cause the console output
will fill it up real quick. So try out the inputs, the default ones, 2
for blue and 1
for red, will make blue appear twice and red appear once.
$(document).ready(function() {
$('#spin-btn').click(function() {
var colors = getColors();
var output = colors.length,
randomNumber = Math.floor(Math.random() * output),
color_container = $('#color-output');
console.log(colors);
var color = colors[randomNumber];
color_container.removeClass(); //Cleanup previous color classes
color_container.addClass(color);
});
});
function getColors() {
var blue_prob = $('#blue-prob').val(),
red_prob = $('#red-prob').val();
var colors = ["red", "yellow", "blue"]; // default colors
addProbability(colors, blue_prob - 1, "blue"); //blue_prob - 1 because "blue" already appears once
addProbability(colors, red_prob - 1, "red"); //red_prob - 1 because "blue" already appears once
return colors;
}
function addProbability(colors, probability, color) {
for (let i = 0; i < probability; ++i)
colors.push(color);
}
#spin-btn {
padding: 20px;
margin-bottom: 10px;
background-color: #eee;
cursor: pointer;
}
#color-output {
width: 100px;
height: 100px;
}
.default {
background: gray;
}
.blue {
background: blue;
}
.yellow {
background: yellow;
}
.red {
background: red;
}
.green {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="spin-btn">Generate random color</div>
<div id="color-output" class="default"></div>
<span>Blue probability</span><input id="blue-prob" value="2" /> <br>
<span>Red probability</span><input id="red-prob" value="1" /> <br>
Things to build upon this existing code
- Make input more dynamic not just hard-coded blue/red
- Let users input percentages (10%, 20%, 30%...) then in your code convert that to numbers between 1-10. Take it down a decimal.
- Error checking (user inputs text, or something like 10.5% ... etc)
Adding color saturation percentages
Here's where SASS
would be real magic. Alright, you want percentages too right? Well just expand on the principle of class name. You could have a whole bunch of CSS classes such as
.color-10 { opacity: 0.1; }
.color-20 { opacity: 0.2; }
.color-30 { opacity: 0.3; }
Since you are not using SASS
that's cumbersome to write out in CSS. So I'd suggest to go with inline-styles
instead. So instead of having the CSS class give it the opacity
, use jQuery
to manipulate it. The trick on this is to have the body background
on white. Or you'll color will be affected.
EDIT: (explaining why I chose opacity as a simple way to achieve color variation)
The opacity is to make use of the percentages for the color. Opacity changes how opaque an element is. In other words, transparency of the element. It's not the most proper way to do it, but it is simple. So if you set the rectangle red, then make it 50% transparent, the color red will seem "pinkish" , as if you desaturated it. In order for this way to work, the background of the element must be white, or your color will change its hue when you set the opacity of the element.
Simple code snippet:
var colors = ["red", "yellow", "blue", "green"];
$(document).ready(function() {
$('#spin-btn').click(function() {
var output = colors.length,
randomNumber = Math.floor(Math.random() * output),
color_container = $('#color-output');
var color = colors[randomNumber],
percentage = getPercentage();
console.log(color, percentage);
color_container.removeClass(); //Cleanup previous color classes
color_container.addClass(color);
color_container.css({
'opacity': percentage
});
});
function getPercentage() {
return Math.random(); //Work on this, I just spat it out in 5 seconds. Will NOT include 1, full opacity
}
});
#spin-btn {
padding: 20px;
margin-bottom: 10px;
background-color: #eee;
cursor: pointer;
}
#color-output {
width: 100px;
height: 100px;
}
.default {
background: gray;
}
.blue {
background: blue;
}
.yellow {
background: yellow;
}
.red {
background: red;
}
.green {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="spin-btn">Generate random color</div>
<div id="color-output" class="default"></div>
The way I would go about it is by using rgba()
which allows a fourth parameter to include the opacity of the color itself.
.blue-40 {
background-color: rgba(0, 0, 255, 0.40);
}
But I'd use SASS
for generating all those CSS rules. If you are not using SASS
I'm sure you can use JS
to figure out how to get an rgba()
color.
Hope this helped :)