![]() |
| Something like this! |
So yeah, let's do something like that today. Totally randomize the text and colors. We'll use VueJS for this because... why the hell not, eh?
We're going to have some boilerplate HTML to start with. We have a div with the id ctmApp that will be Vue's placeholder. There's also a script remote link to VueJS.
<!DOCTYPE html>
<html>
<head>
<title>Color Troll Meme</title>
<style>
</style>
</head>
<body>
<div id="ctmApp">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.18/vue.min.js"></script>
<script>
</script>
</body>
</html>
<html>
<head>
<title>Color Troll Meme</title>
<style>
</style>
</head>
<body>
<div id="ctmApp">
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.18/vue.min.js"></script>
<script>
</script>
</body>
</html>
Inside the script tag, We declare app as a call to Vue(). In it, we pass an object. In the classic VueJS pattern, the object will have el, data, methods and created. el will be set to ctmApp.
<script>
var app = new Vue
(
{
el: "#ctmApp",
data:
{
},
methods:
{
},
created: function()
{
}
}
);
</script>
var app = new Vue
(
{
el: "#ctmApp",
data:
{
},
methods:
{
},
created: function()
{
}
}
);
</script>
In data, we want two arrays - ctms, inUse and the object wordTypes.
data:
{
ctms:
[
],
inUse:
[
],
wordTypes:
{
}
},
{
ctms:
[
],
inUse:
[
],
wordTypes:
{
}
},
ctms is an array of objects. You can have as many as you want, though I'd go with 9. Each object has name, color and textColor properties.
data:
{
ctms:
[
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
}
],
inUse:
[
],
wordTypes:
{
}
},
{
ctms:
[
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
}
],
inUse:
[
],
wordTypes:
{
}
},
inUse is a placeholder array which defaults to empty. We won't need to worry about it yet. wordTypes is an objects that has area, condition, condition_prefix and condition_suffix arrays as properties. These arrays contain strings.
data:
{
ctms:
[
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
}
],
inUse:
[
],
wordTypes:
{
area:
[
],
condition:
[
],
condition_prefix:
[
],
condition_suffix:
[
]
}
},
{
ctms:
[
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
}
],
inUse:
[
],
wordTypes:
{
area:
[
],
condition:
[
],
condition_prefix:
[
],
condition_suffix:
[
]
}
},
I've filled these in. area is supposed to be embarrassing areas of the human body to develop medical conditions in. condition is an array of medical conditions that range from mild to nasty. condition_prefix and condition_suffix are descriptors that are supposed to go with the words in area.
data:
{
ctms:
[
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
}
],
inUse:
[
],
wordTypes:
{
area:
[
"testicle",
"anus",
"vagina",
"nipple",
"groin",
"penis",
"labia",
"cleavage",
"rectum"
],
condition:
[
"dehydration",
"constipation",
"arthritis",
"bronchitis",
"myopia",
"baldness",
"pinkeye",
"narcolepsy",
"epilepsy",
"insomnia",
"dementia",
"psychosis",
"indigestion",
"heartburn"
],
condition_prefix:
[
"detached",
"bruised",
"inverted",
"ingrown",
"misaligned",
"ruptured"
],
condition_suffix:
[
"lacerations",
"tumor",
"ulcers",
"blisters",
"blockage",
"fracture",
"ulcers",
"inflammation",
"necrosis",
"discharge",
"dysfunction",
"fungus"
]
}
},
{
ctms:
[
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
},
{
name: "",
color: "",
textColor: ""
}
],
inUse:
[
],
wordTypes:
{
area:
[
"testicle",
"anus",
"vagina",
"nipple",
"groin",
"penis",
"labia",
"cleavage",
"rectum"
],
condition:
[
"dehydration",
"constipation",
"arthritis",
"bronchitis",
"myopia",
"baldness",
"pinkeye",
"narcolepsy",
"epilepsy",
"insomnia",
"dementia",
"psychosis",
"indigestion",
"heartburn"
],
condition_prefix:
[
"detached",
"bruised",
"inverted",
"ingrown",
"misaligned",
"ruptured"
],
condition_suffix:
[
"lacerations",
"tumor",
"ulcers",
"blisters",
"blockage",
"fracture",
"ulcers",
"inflammation",
"necrosis",
"discharge",
"dysfunction",
"fungus"
]
}
},
For the methods object, we will put in five methods - fillInfo(), getColor(), getCondition(), getOne() and getRandomNo(). In the created method, we will run the fillInfo() method.
methods:
{
fillInfo: function()
{
},
getColor: function()
{
},
getCondition: function()
{
},
getOne: function()
{
},
getRandomNo:function()
{
}
},
created: function()
{
this.fillInfo();
}
{
fillInfo: function()
{
},
getColor: function()
{
},
getCondition: function()
{
},
getOne: function()
{
},
getRandomNo:function()
{
}
},
created: function()
{
this.fillInfo();
}
In the HTML, add this in the ctmApp div. We use v-for to dictate that we want a div for each element in the ctms array, styled using the CSS class ctm.
<div id="ctmApp">
<div class="ctm" v-for="ctm in ctms">
</div>
</div>
<div class="ctm" v-for="ctm in ctms">
</div>
</div>
In the CSS, add the CSS class for ctm. It's basically a deep grey circle.
<style>
.ctm
{
width: 300px;
height: 300px;
float: left;
margin-left: 10%;
margin-top: 10%;
border-radius: 50%;
background-color: rgb(10, 10, 10);
}
</style>
.ctm
{
width: 300px;
height: 300px;
float: left;
margin-left: 10%;
margin-top: 10%;
border-radius: 50%;
background-color: rgb(10, 10, 10);
}
</style>
You'll see 9 deep grey circles. Because I put 9 elements inside the ctms array. Depending on your screen size, you may need to scroll.
Let's work on the methods now. This is getRandomNo(). Give it a parameter, max. It should return a random number from 0 to max minus 1.
getRandomNo:function(max)
{
return Math.floor(Math.random() * max);
}
{
return Math.floor(Math.random() * max);
}
For getOne(), we have the parameter, arr, which is an array. We return one of the elements of arr.
getOne: function(arr)
{
return arr[];
},
{
return arr[];
},
Which one? Well, we let getRandomNo() decide.
getOne: function(arr)
{
return arr[this.getRandomNo()];
},
{
return arr[this.getRandomNo()];
},
But of course, we need to pass in the size of arr so that the random number generated is not out of bounds for arr.
getOne: function(arr)
{
return arr[this.getRandomNo(arr.length)];
},
{
return arr[this.getRandomNo(arr.length)];
},
For getColor(), there is the parameter maxRGB. maxRGB is used to restrict how bright each color component is. In here, we declare r, g and b, and each one is set by using getRandomNo() to grab any number from 0 to maxRGB minus 1.
getColor: function(maxRGB)
{
var r = this.getRandomNo(maxRGB);
var b = this.getRandomNo(maxRGB);
var g = this.getRandomNo(maxRGB);
},
{
var r = this.getRandomNo(maxRGB);
var b = this.getRandomNo(maxRGB);
var g = this.getRandomNo(maxRGB);
},
Then we return an array containing these three values.
getColor: function(maxRGB)
{
var r = this.getRandomNo(maxRGB);
var b = this.getRandomNo(maxRGB);
var g = this.getRandomNo(maxRGB);
return [r, g, b];
},
{
var r = this.getRandomNo(maxRGB);
var b = this.getRandomNo(maxRGB);
var g = this.getRandomNo(maxRGB);
return [r, g, b];
},
And for the last small method, we have getCondition(). For this, we have the parameters area and prefix. Here, we assume that area has already been taken from the area array, and prefix is a Boolean that is true by default.
getCondition: function(area, prefix = true)
{
},
{
},
We declare cond as an empty string, then use an If block on prefix.
getCondition: function(area, prefix = true)
{
var cond = "";
if (prefix)
{
}
else
{
}
},
{
var cond = "";
if (prefix)
{
}
else
{
}
},
If prefix is true, we set cond to a random element in condition_prefix using getOne(), and return a string of cond and area. If not, we set cond to a random element in condition_suffix, and return a string of area and cond.
getCondition: function(area, prefix = true)
{
var cond = "";
if (prefix)
{
cond = this.getOne(this.wordTypes.condition_prefix);
return cond + " " + area;
}
else
{
cond = this.getOne(this.wordTypes.condition_suffix);
return area + " " + cond;
}
},
{
var cond = "";
if (prefix)
{
cond = this.getOne(this.wordTypes.condition_prefix);
return cond + " " + area;
}
else
{
cond = this.getOne(this.wordTypes.condition_suffix);
return area + " " + cond;
}
},
Now, time to work on fillInfo()! It will use all of the methods we've worked on up to now, either directly or otherwise. We begin by iterating through the ctms array.
fillInfo: function()
{
this.ctms.forEach(
(ctm, index) =>
{
}
);
},
{
this.ctms.forEach(
(ctm, index) =>
{
}
);
},
We declare isLast as a Boolean. If the current value of index is exactly the length of ctms minus 1, that means it's the last element. Then we have an If block based on isLast.
fillInfo: function()
{
this.ctms.forEach(
(ctm, index) =>
{
var isLast = (index === this.ctms.length - 1);
if (isLast)
{
}
else
{
}
}
);
},
{
this.ctms.forEach(
(ctm, index) =>
{
var isLast = (index === this.ctms.length - 1);
if (isLast)
{
}
else
{
}
}
);
},
We'll leave the first case along for now. For all other ctm objects in the ctms array, we set the name property to a random string from the condition array.
fillInfo: function()
{
this.ctms.forEach(
(ctm, index) =>
{
var isLast = (index === this.ctms.length - 1);
if (isLast)
{
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
}
}
);
},
{
this.ctms.forEach(
(ctm, index) =>
{
var isLast = (index === this.ctms.length - 1);
if (isLast)
{
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
}
}
);
},
Now, here in the HTML, we have a h1 tag with the value of name.
<div class="ctm" v-for="ctm in ctms">
<h1>{{ ctm.name }}</h1>
</div>
<h1>{{ ctm.name }}</h1>
</div>
In the HTML, let's just set the h1 tag to have a certain size, center it, and so on. Most importantly, we set the color to a light grey so we can see the contrast.
<style>
.ctm
{
width: 300px;
height: 300px;
float: left;
margin-left: 10%;
margin-top: 10%;
border-radius: 50%;
background-color: rgb(10, 10, 10);
}
.ctm h1
{
margin-top: 40%;
font-size: 30px;
text-align: center;
color: rgb(100, 100, 100);
}
</style>
.ctm
{
width: 300px;
height: 300px;
float: left;
margin-left: 10%;
margin-top: 10%;
border-radius: 50%;
background-color: rgb(10, 10, 10);
}
.ctm h1
{
margin-top: 40%;
font-size: 30px;
text-align: center;
color: rgb(100, 100, 100);
}
</style>
Look at this! Conditions are populated, but "pinkeye" is repeated.
To fix this, check if the value of name is in the inUse array. And keep reassigning the name property until you get a value that isn't in the inUse array.
if (isLast)
{
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
}
{
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
}
Once that's done, push the value into the inUse array, so that this value can be one of the values compared against further down.
if (isLast)
{
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
this.inUse.push(ctm.name);
}
{
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
this.inUse.push(ctm.name);
}
Now you'll see no repeats! Bear in mind that this only works as long as you have less elements in the ctms array (OK, not counting the final element) than there are elements in the condition array. Otherwise you're going to get an infinite loop.
Now to handle the condition for the last element in ctms. Declare prefix as a Boolean, and use getRandomNo() with a argument of 2, to get a random number between 0 and 1. Then declare area, and use getOne() to obtain a random value from the area array, as its value.
if (isLast)
{
var prefix = (this.getRandomNo(2) === 0);
var area = this.getOne(this.wordTypes.area);
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
this.inUse.push(ctm.name);
}
{
var prefix = (this.getRandomNo(2) === 0);
var area = this.getOne(this.wordTypes.area);
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
this.inUse.push(ctm.name);
}
Then set the name property by using getCondition() and passing in area and prefix as arguments.
if (isLast)
{
var prefix = (this.getRandomNo(2) === 0);
var area = this.getOne(this.wordTypes.area);
ctm.name = this.getCondition(area, prefix);
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
this.inUse.push(ctm.name);
}
{
var prefix = (this.getRandomNo(2) === 0);
var area = this.getOne(this.wordTypes.area);
ctm.name = this.getCondition(area, prefix);
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
this.inUse.push(ctm.name);
}
See? The very last circle at the bottom right now reads "misaligned rectum"!
Let's handle colors now. After the If block, declare colorArr as the array returned from calling the getColor() method. Pass in 100 as an argument so that the RGB values won't be greater than 100. That means it'll be a somewhat dark color. After that, formulate a CSS rgb() string based on colorArr's elements, and assign the value to the color property of the current element of ctms.
if (isLast)
{
var prefix = (this.getRandomNo(2) === 0);
var area = this.getOne(this.wordTypes.area);
ctm.name = this.getCondition(area, prefix);
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
this.inUse.push(ctm.name);
}
var colorArr = this.getColor(100);
ctm.color = "rgb(" + colorArr[0] + "," + colorArr[1] + "," + colorArr[2] + ")";
{
var prefix = (this.getRandomNo(2) === 0);
var area = this.getOne(this.wordTypes.area);
ctm.name = this.getCondition(area, prefix);
}
else
{
ctm.name = this.getOne(this.wordTypes.condition);
while (this.inUse.indexOf(ctm.name) > -1)
{
ctm.name = this.getOne(this.wordTypes.condition);
}
this.inUse.push(ctm.name);
}
var colorArr = this.getColor(100);
ctm.color = "rgb(" + colorArr[0] + "," + colorArr[1] + "," + colorArr[2] + ")";
Bake this value into the div's style attribute.
<div class="ctm" v-for="ctm in ctms" style="background-color:{{ ctm.color }}">
<h1>{{ ctm.name }}</h1>
</div>
<h1>{{ ctm.name }}</h1>
</div>
You can see that now the circles are colored different. Each one is a different color.
Now for the text! Each circle's text should have the same color as its div, but several shades brighter. Remember we capped the RGB values at 100 earlier? That was deliberate so we could have a buffer between 100 and 255, the actual maximim RGB value. Now declare opacity and set it to 1. Then set the textColor property to what we previously set color as, except that we use rgba() instead and use opacity as the last argument.
var colorArr = this.getColor(100);
ctm.color = "rgb(" + colorArr[0] + "," + colorArr[1] + "," + colorArr[2] + ")";
var opacity = 1;
ctm.textColor = "rgba(" + colorArr[0] + "," + colorArr[1] + "," + colorArr[2] + "," + opacity + ")";
ctm.color = "rgb(" + colorArr[0] + "," + colorArr[1] + "," + colorArr[2] + ")";
var opacity = 1;
ctm.textColor = "rgba(" + colorArr[0] + "," + colorArr[1] + "," + colorArr[2] + "," + opacity + ")";
For each value (except opacity), we add 150. This makes the text color much brighter, but keeps them at the same proportions.
var colorArr = this.getColor(100);
ctm.color = "rgb(" + colorArr[0] + "," + colorArr[1] + "," + colorArr[2] + ")";
var opacity = 1;
ctm.textColor = "rgba(" + (colorArr[0] + 150) + "," + (colorArr[1] + 150) + "," + (colorArr[2] + 150) + "," + opacity + ")";
ctm.color = "rgb(" + colorArr[0] + "," + colorArr[1] + "," + colorArr[2] + ")";
var opacity = 1;
ctm.textColor = "rgba(" + (colorArr[0] + 150) + "," + (colorArr[1] + 150) + "," + (colorArr[2] + 150) + "," + opacity + ")";
Now bake the color of the text into the h1 tag.
<div class="ctm" v-for="ctm in ctms" style="background-color:{{ ctm.color }}">
<h1 style="color:{{ ctm.textColor }}">{{ ctm.name }}</h1>
</div>
<h1 style="color:{{ ctm.textColor }}">{{ ctm.name }}</h1>
</div>
There you go. You can see all the text colors are basically brighter versions of their backgrounds.
Finally, the opacity!
Remember the variable opacity? It's supposed to be very low for the final div, and varying higher levels for the others. The idea here is that the more clearly you can see the text, the less likely that you have that condition. So for the last medical condition, it's super unclear and when the user can finally read it, it says something embarrassing. That's the joke!So here, if isLast is true, we set opacity at a really low value, such as 0.05.
var opacity = (isLast ? 0.05 : );
And if not, we get a random number from 0 to 7.
var opacity = (isLast ? 0.05 : this.getRandomNo(8));
We add 2, so we get a number from 2 to 9.
var opacity = (isLast ? 0.05 : this.getRandomNo(8) + 2);
Then we divide by 10, so the final result is between 0.2 to 0.9.
var opacity = (isLast ? 0.05 : (this.getRandomNo(8) + 2) / 10);
See that everything else is relatively easy to read, but the last one is almost invisible! It says "ingrown rectum", which sounds painful.
Have fun with this. Refresh. See what results you get. Add more to the arrays!
Better go see a doctor for that testicle necrosis!
T___T
T___T



























