Let me show you how you can implement a dice-rolling simulator in less than 30 minutes of your time on the front-end.
Currently, I am playing around with Vue.js. Despite the solution with VanillaJS, I will also present how to code it quickly with Vue.js too.
Let's walk through the process:
Traditionally, we are starting with writing HTML-tree to render two dices:
<!-- index.html | VanillaJS Implementation -->
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Dice Rolling Simulator</title>
<link rel="stylesheet" href="index.css">
</head>
<body>
<div id="app" onclick="roll()">
<div class="dice" data-dots>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
<div class="dice" data-dots>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<script src="index.js"></script>
</body>
</html>
There are 2 div-parents
with the class .dice
, it means there are 2 playing dices on the screen.
The data-dots
is an attribute, which represents how many dots will be rendered on the dice after each roll.
The roll()
function makes tapping work everywhere, so the user can make a roll upon a click easily.
You already know that you need to generate random numbers for each roll. And here we need to add JavaScript:
// index.js | VanillaJS Implementation
const dices = window.document.querySelectorAll('.dice');
const roll = () => {
dices.forEach(dice => {
const dots = Math.floor(Math.random() * 6) + 1;
dice.setAttribute("data-dots", dots);
})
};
// first initial roll for when the page loads
roll();
We are going to roll 2 dices at the same time.
Then we need to loop through the dices
with forEach
method to simulate one of the six dice sides and randomize dice output after each roll: const dots = Math.floor(Math.random() * 6) + 1;
To render the output result, we set data-dots
attribute to the corresponding value dots
.
The template structure on Vue.js looks a bit differently, but not that much, let's compare:
<!-- index.html | Vue.js Implementation -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dice Rolling Simulator</title>
<link rel="stylesheet" href="./index.css">
</head>
<body>
<div id="app" v-on:click="roll">
<div class="dice"
v-for="dice in dices"
v-bind:data-dots="dice.dots"
>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
</div>
</div>
<script src="./lib/vue-2.6.11.min.js"></script>
<script src="./index.js"></script>
</body>
</html>
// index.js | Vue.js implementation
const app = new Vue({
el: '#app',
data: {
dices: [
{ dots: 1 },
{ dots: 1 },
]
},
mounted() {
// first initial roll for when the component mounts
this.roll();
},
methods: {
roll() {
this.dices.forEach(dice => {
dice.dots = Math.floor(Math.random() * 6) + 1;
});
}
}
});
Every Vue application starts by creating a new Vue instance with the Vue function: const app = new Vue({ // options })
The mounting DOM-element called el
; the data
object includes the data structure that manages the state of our component.
Additionally, to data properties, Vue instances expose instance properties, hooks, and methods too.
For our example, we have to override the mounted
hook to invoke initial "roll()" for when the user loads the page.
In methods
, there is a simple method roll()
to throw random numbers after each dice roll written in VanillaJS.
To handle click event in the browser to roll dices, v-on:click="roll"
has been added to the Vue instance with the #app
. To pass the data to the element, you have to bind with v-bind:data-dots="dice.dots"
.
Last but not least, to make it work appropriately according to the HTML mark-up and scripts, we need CSS-styles:
.dice {
display: inline-block;
position: relative;
border: 3px solid black;
width: 100px;
height: 100px;
margin: 0.5rem;
}
.dice > div {
content: ' ';
position: absolute;
width: 20px;
height: 20px;
border-radius: 100%;
}
.dice[data-dots="1"] > :nth-child(1) {
top: 40px;
left: 40px;
background-color: black;
}
.dice[data-dots="2"] > :nth-child(1) {
top: 20px;
left: 40px;
background-color: black;
}
.dice[data-dots="2"] > :nth-child(2) {
top: 50px;
left: 40px;
background-color: black;
}
/* ... see full file here: https://gist.github.com/ilonacodes/b4aef61073129f41fd99b802c7ce8d8c */
It's not the full CSS-file, but here it is important to understand the styling pattern. The example above shows you how to style dots for one dot and two dots on the dice.
It means,
if we need to render one dot:
.dice[data-dots="1"]
, we position inside the.dice
class its first child:.dice[data-dots="1"] > :nth-child(1)
according to position we have written for this selector;if we need to render two dots on the dice:
.dice[data-dots="2"] > :nth-child(1)
and.dice[data-dots="2"] > :nth-child(2)
, we just add styles to the second child within the styles of the first child.
For rendering three dots on the dice:
.dice[data-dots="3"] > :nth-child(1)
, .dice[data-dots="3"] > :nth-child(2), .dice[data-dots="3"] > :nth-child(3)
For rendering four dots on the dice:
.dice[data-dots="4"] > :nth-child(1)
, .dice[data-dots="4"] > :nth-child(2), .dice[data-dots="4"] > :nth-child(3)
, .dice[data-dots="4"] > :nth-child(4)
And so on till the dice[data-dots="6"]
included.
That's it for now. Let me know if you find these frontend code snippets useful or joyful for you.
Thank you for reading! 🙏
Code your best,
Ilona Codes
Top comments (3)
This looked like a good way to spend an hour or so of lockdown (as well as providing a neat addition to my collection of demos), so I prototyped the same thing using my own DSL. My main aim was to see how efficient I could make the algorithm for drawing the dots, so I used a table of coordinates, with 6 rows each having 6 pairs of values that specify the top/left coordinates of a dot, which is itself constructed as a rounded DIV with absolute positioning. The renderer runs along the row for the dot count requested and stops when it hits a zero. I added a simple animation for when a dice is clicked.
I've put it up on a demo website. The script is in the BODY of the page and is compiled and run by a JS library called in by the HEAD. The actual code looks like this:
Hi, I am learning Vue JS currently and was facing some difficulty grasping it and was searching online for tips when I landed on this post. I am creating an essay writing service website using Vue. I really liked Vue a lot as it is a lot cleaner than vanilla js. I would contact if I face any difficulty with my code.
Sory, but worstest way to play around with Vue is: "script src="./lib/vue-2.6.11.min.js"></script"
And telling it to others.
Vue is not so different from other frameworks.
To feel Vue, and how it could be powerfull, i think, you need to create vue-node project(or maybe better Nuxt Project) and try features assigned to it, how like a people usually says: "The devil's always in the details"
Anyway this code could be refactored by using only vuejs and this will be right way.