Ways to showcase the outcome of a spin after each rotation

I am currently working on a spinning code snippet that allows users to spin and potentially win different amounts. The code includes functionality to prevent more than 3 spins, set random rotation values, and animate the spinning effect.

However, I now want to enhance the user experience by adding an indicator that displays the result of each spin once it stops. For example, if a user lands on $10, I want to visibly show them their winnings below the spinning wheel.

This concept is best illustrated in the image linked below:

Answer №1

Here is the solution for you :).

To determine the position of the spinner, I implemented a while loop that continuously subtracted 360 from the degrees value until it fell within the range of 0 to 360. By considering the 8 sections of the spinner and their respective angles (45 degrees each), along with the starting point at $40, I used conditional statements in JavaScript to pinpoint where the spinner landed.

In addition, I included a div element

<div id="line"></div>
to create an arrow indicator indicating the final result. You can view the code snippet here:

[JavaScript code snippet]  
[CSS styling rules]
[HTML structure]

Answer №2

By utilizing the getBoundingClientRect() method, we can ascertain the position of the top paddle. The paddles are divided in half based on their width values, with the group containing the top paddle having the smallest width. Within this group, the paddle with the lowest y coordinate is identified as the topmost paddle.

All paddle elements are selected using the querySelectorAll function, converted into an array using Array.from(), and iterated over using forEach().

A multi-dimensional array is populated with the paddle's text content, width, and y coordinate. This array is sorted first by width, then by y coordinate, placing the topmost paddle at the beginning of the array. The amount associated with the winning paddle can be accessed at paddles[0][0].

function getSpin() {
  let paddles = [];
  Array.from(document.querySelectorAll('span[class^="span"]')).forEach(function(paddle) {
    let gbcr = paddle.getBoundingClientRect();
    paddles.push([paddle.textContent, Math.round(gbcr.width), Math.round(gbcr.y)]);
  });
  return paddles.sort(function(a, b) {
    if (a[1] > b[1]) {
      return 1;
    } else if (a[1] < b[1]) {
      return -1;
    }
    if (a[2] < b[2]) {
      return -1;
    } else if (a[2] > b[2]) {
      return 1;
    }
  })[0][0];
}

A message div is included beneath the button:

<button class="spin" onclick="myfunction()">SPIN</button>

<div id="spinresult">Click "SPIN" to play.</div>

The winning message is calculated and displayed within it during the setTimeout function nested in the myFunction function.

setTimeout(function() {
  element.classList.add('animate');
  document.querySelector('#spinresult').textContent = `Congratulations, you've won ${getSpin()}!`;
}, 5000); //5000 = 5 seconds

An arrow down indicator is rendered using a div placed before the spin box and styled using CSS.

<div class="arrow-down"></div>
<div id="box" class="box">

// JavaScript code here truncated for brevity
// CSS code here truncated for brevity
// HTML code here truncated for brevity

Answer №3

After finding inspiration from @john 's response...

A new technique utilizing a random degree value and the JavaScript remainder operator % has been implemented to determine the range in which the spin wheel's degree value falls:

1-45, 46-90, 91-135, 136-180, 181-225, 226-270, 271-315, 316-360
.

To account for the starting offset of 22 degrees on the wheel, ensuring that the top paddle is centered, the calculated degree range value is adjusted by subtracting 21 degrees.

By adjusting the range value appropriately, the specific portion of the wheel—corresponding to a paddle—can be identified by dividing it by 45 degrees and rounding down. Typically, this provides a value between 0 - 7, aligning with the array of win values. However, if the degree range is below 22, a -1 is returned and adjusted to index 7.

let spinCount = 0;
let [xx, yy] = [1024, 9999]; // [min, max]
let win = ["$60", "$10", "$80", "$30", "$50", "$20", "$70", "$40"];

document.querySelector('.spin').addEventListener('click', spin);

function spin() {
  if (spinCount > 3) {
    alert("No more spins.");
    return false;
  }
  let deg = Math.floor(Math.random() * (xx - yy)) + yy;
  let deg_off = (deg % 360) - 21;
  let widx = Math.floor((deg_off / 45));
  widx = (0 <= widx) ? widx : 7;

  document.getElementById('box').style.transform = `rotate(${deg}deg)`;
  let mainbox = document.getElementById('mainbox');
  mainbox.classList.remove('animate');

  setTimeout(function() {
    mainbox.classList.add('animate');
    document.getElementById("winnings").textContent 
      = `Congratulations, you've won ${win[widx]}`;
  }, 5000); //5000 = 5 second

  spinCount++;
}
* {
  box-sizing: border-box;
  padding: 0;
  margin: 0;
  outline: none;
}

body {
  font-family: Open Sans;
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
  overflow: hidden;
  background: rgb(60, 60, 242);
  background: linear-gradient(90deg, rgba(60, 60, 242, 1) 0%, rgba(98, 245, 230, 1) 52%, rgba(60, 60, 242, 1) 100%);
  background-size: cover;
}

.mainbox {
  position: relative;
  width: 500px;
  height: 500px;
  text-align: center;
}

.mainbox:after {
  position: absolute;
  content: '';
  width: 32px;
  height: 32px;
  background: url('../img/arrow-wheel.png') no-repeat;
  background-size: 32px;
  right: -30px;
  top: 50%;
  transform: translateY(-50%);
}

.box {
  width: 100%;
  height: 100%;
  position: relative;
  border-radius: 50%;
  border: 10px solid #fff;
  overflow: hidden;
  transition: all ease 5s;
}

span {
  width: 50%;
  height: 50%;
  display: inline-block;
  position: absolute;
}

.span1 {
  clip-path: polygon(0 92%, 100% 50%, 0 8%);
  background-color: #fffb00;
  top: 120px;
  left: 0;
}

.span2 {
  clip-path: polygon(100% 92%, 0 50%, 100% 8%);
  background-color: #ff4fa1;
  top: 120px;
  right: 0;
}

.span3 {
  clip-path: polygon(50% 0%, 8% 100%, 92% 100%);
  background-color: #ffaa00;
  bottom: 0;
  left: 120px;
}

.span4 {
  clip-path: polygon(50% 100%, 92% 0, 8% 0);
  background-color: #22ff00;
  top: 0;
  left: 120px;
}

.box1 .span3 b {
  transform: translate(-50%, -50%) rotate(-270deg);
}

.box1 .span1 b,
.box2 .span1 b {
  transform: translate(-50%, -50%) rotate(185deg);
}

.box2 .span3 b {
  transform: translate(-50%, -50%) rotate(90deg);
}

.box1 .span4 b,
.box2 .span4 b {
  transform: translate(-50%, -50%) rotate(-85deg);
}

.box2 {
  width: 100%;
  height: 100%;
  transform: rotate(-135deg);
}

span b {
  font-size: 24px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.spin {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 75px;
  height: 75px;
  border-radius: 50%;
  border: 4px solid #fff;
  background-color: #001aff;
  color: #fff;
  box-shadow: 0 5px 20px #000;
  font-weight: bold;
  font-size: 22px;
  cursor: pointer;
}

.spin:active {
  width: 70px;
  height: 70px;
  font-size: 20px;
}

.mainbox.animate:after {
  animation: animateArrow 0.7s ease infinite;
}

@keyframes animateArrow {
  50% {
    right: -40px;
  }
}

#winnings {
  padding: 1em;
  font-family: sans-serif;
  color: white;
}

.arrow-down {
  position: absolute;
  right: 50%;
  z-index: 9;
}

.arrow-down::before {
  position: absolute;
  left: -1.35em;
  content: "";
  border-top: 1em solid red;
  border-left: 1em solid transparent;
  border-right: 1em solid transparent;
}
<div id="mainbox" class="mainbox">
  <div class="arrow-down"></div>
  <div id="box" class="box">
    <div class="box1">
      <span class="span1"><b>$10</b></span>
      <span class="span2"><b>$20</b></span>
      <span class="span3"><b>$30</b></span>
      <span class="span4"><b>$40</b></span>
    </div>
    <div class="box2">
      <span class="span1"><b>$50</b></span>
      <span class="span2"><b>$60</b></span>
      <span class="span3"><b>$70</b></span>
      <span class="span4"><b>$80</b></span>
    </div>
  </div>

  <button class="spin">SPIN</button>
  <div id="winnings">Click "SPIN" to initiate.</div>

</div>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

parsing and building a sophisticated JSON object

i have a complex array structure as shown below, array=[ { 'mm': '1', exp: 'exp1' }, { 'mm': '2', exp: 'exp2' }, { 'mm': [ '1', '3', '7' ], exp: &ap ...

Error: module 'next/react' not found

Recently delving into next.js, I encountered an error after creating a project with npx create-next-app. Oddly enough, the app still runs despite this issue. { "resource": "/E:/codes/news-website/news-website/pages/index.js", ...

Learn how to securely download files from an Azure Storage Container using Reactjs

I'm currently working on applications using reactjs/typescript. My goal is to download files from azure storage v2, following a specific path. The path includes the container named 'enrichment' and several nested folders. My objective is to ...

Seeking assistance with dilemmas related to jQuery (specifically kendo), .NET Web Service (asmx), and Json

After conducting extensive research on the subject, I was unable to find any satisfactory answers or complete examples. Since I have limited experience with jquery, I am in search of a straightforward sample that demonstrates what I'm trying to achiev ...

Leveraging parameters within a sequence of object properties

Within the realm of Angular, I am dealing with interfaces that take on a structure similar to this (please note that this code is not my own): export interface Vehicles { id: number; cars: Car; trucks: Truck; } Export interface Car { make: ...

Retrieve data from a URL using Angular 6's HTTP POST method

UPDATE: Replaced res.json(data) with res.send(data) I am currently working on a web application using Angular 6 and NodeJS. My goal is to download a file through an HTTP POST request. The process involves sending a request to the server by calling a func ...

Having trouble with media queries on my iPad

I currently have a media query set up as follows: @media only screen and (max-width: 959px) It works when I resize my browser, however, it does not seem to be functioning correctly when my iPad is in portrait mode. When I include and (max-device-width: 9 ...

Is it possible to break a single word when word wrapping?

Is it possible to apply word-wrap: break-word to just one word within an element without affecting the entire element? I find that when I apply it to the entire element, it looks messy. I tried searching for a solution but couldn't find anything. Has ...

Adding elements to a JSON array in JavaScript/AngularJS

Looking for help with inserting a new item "uid" into a JSON array. Here is the initial array: var testArr=[{name:"name1",age:20},{name:"name1",age:20},{name:"name1",age:20}] The desired output after inserting the "uid" would be: var testArr=[{name:"nam ...

There appears to be a malfunction with WebRupee

I have incorporated the new rupee sign into my website to represent Indian currency. Below is the code snippet I used: For the script, I included " and also added the following: <span class="WebRupee">Rs.</span> 116,754.00 To style it using ...

JavaScript - The progression of a virtual pet even when the user is offline

Currently, I am utilizing VueJS and MongoDB to develop an interactive virtual pet. Our approach involves storing user data in localStorage for easy access and retrieval. I'm exploring the concept of allowing the virtual pet to evolve autonomously (s ...

Receive the most recent query in a Nuxt plugin following the completion of page loading

So, here's the issue - I have a plugin containing some functions that are supposed to update URL queries. However, every time I run $global.changePage(2) or $global.changeLimit(2), the console.log(query) outputs an empty object and doesn't show t ...

Transforming a vertical table into a horizontal layout

I'm facing an issue with transforming the database object for table display. My database contains a table structured like this. name total date Awoc1 100 9/14/2022 Awoc1 200 9/15/2022 Awoc1 300 9/16/2022 Awoc2 100 9/14/2022 Awoc2 ...

Step-by-step guide on incorporating CSS box-shadow with the .style JavaScript property

I have a JavaScript code snippet that looks like this: document.getElementById("imgA").style.box-shadow = "0 0 5px #999999"; The hyphen in box-shadow is causing an invalid assignment exception to be thrown by the JavaScript engine (specifically in Firefo ...

Exploring the use of Angular with tables: applying classes dynamically using ngClass and repeating items using

My table is generated from a Web Service JSON, each row has a button to mark it for deletion. When you click the button, a JS alert displays the ID of the row element, and I also need to add the 'danger' bootstrap class to the row. Now, I can cap ...

Learn how to synchronize global packages across multiple computers using npm

After installing several npm global packages on my work computer, I am now looking to synchronize these packages with another device. In a typical project, we utilize a package.json file to keep track of package details, making it easy to install all the ...

Navigating on Blogger can be a tricky task when it comes to searching and

I recently added a Table to my blogger post, along with an input form for readers to easily search data. After finding the code on W3Schools (link here), I implemented it successfully. However, I am looking to make some improvements. Here is my question: ...

Javascript issue: SyntaxError - A numerical value is required after the decimal point

I am currently in the process of setting up an HTML form to trigger an AJAX update when a user exits a field. My current attempt is focusing on one table cell and it looks like this: <td><input type="text" class="form-control" id="firstName" name ...

Is it possible to integrate Laravel as the backend for an already existing HTML website template?

I recently designed an HTML template for a salon listing directory site, and while it looks great, I realize I also need a backend solution to manage listings, add advertisements, and more. Can I seamlessly integrate a Laravel-based admin panel into my c ...

Animate.css does not function properly when loaded locally

I'm currently using a Flask server to host an HTML file for testing purposes. Within the head of this HTML file, I have linked to a locally stored animate.min.css file (<link rel="stylesheet" type="text/css" href="{{ url_fo ...