Create spinning wheel - canvas

Hey there! I'm trying to create a cool spinning wheel using a canvas and JS. My wheel is supposed to have 10 segments, each saved as a .png file.

https://i.sstatic.net/glN1p.jpg

In order to achieve a "full circle", I want to draw these 10 segments in a for loop.

https://i.sstatic.net/5PqtU.png

I've been working on this code, but unfortunately, my "wheel" looks pretty messed up - I seem to be missing something.

const segmentCount = 10;

let initializeWheel = function() {
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  let size = $(window).width() * 0.9;
  canvas.width = canvas.height = size;
  ctx.fillStyle = "red"
  ctx.fillRect(0, 0, size, size)
  for (let segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) {
    let image = new Image()
    image.onload = function() {
      let h = ((size / 2) / image.width) * image.height,
        w = size / 2;
      let x = size / 4,
        y = h;
      let degrees = segmentIndex * (360 / segmentCount)
      ctx.save();
      ctx.translate(x + w / 2, y + h / 2);
      ctx.rotate(degrees * Math.PI / 180.0);
      ctx.translate(-x - w / 2, -y - h / 2);
      ctx.drawImage(image, x, y, w, h);
      ctx.restore();
    };
    image.src = "https://i.sstatic.net/5PqtU.png"
  }
  $(canvas).appendTo(document.body)
}

initializeWheel()
canvas {
  position: "absolute";
  left: 0;
  right: 0;
  margin: "auto";
  top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Answer №1

Here is my approach without the need for images, but feel free to use them if desired.

First, I start by drawing the initial segment from the origin. Next, I rotate the segment while also centering the context within the canvas. I hope this explanation is helpful.

const segmentCount = 10;

let initializeWheel = function() {
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  let size = $(window).width() * 0.9;
  canvas.width = canvas.height = size;
  ctx.fillStyle = "red";
  ctx.fillRect(0, 0, size, size);
  let r = 200;// the radius of the wheel
  let degrees = 2*Math.PI / segmentCount;
  function drawSegment(){
    ctx.fillStyle = "black";
    ctx.strokeStyle = "white";
    ctx.moveTo(0,0);
    ctx.lineTo(r,0);
    ctx.arc(0,0,r,0,degrees);
    ctx.closePath();
    ctx.fill();
    ctx.stroke();
  }
  
  ctx.translate(size/2,size/2); // translate the context in the center.
  for (let segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) {
  drawSegment()
  ctx.rotate(degrees);
  }
  $(canvas).appendTo(document.body)
}

initializeWheel()
canvas {
  position: "absolute";
  left: 0;
  right: 0;
  margin: "auto";
  top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

UPDATE

The original poster mentions the use of images. I have incorporated the same method as mentioned above, but this time incorporating the use of an image. To fit the image properly, I had to scale down the context due to the size of the image.

const segmentCount = 10;

let initializeWheel = function() {
  let canvas = document.createElement("canvas");
  let ctx = canvas.getContext("2d");
  let size = $(window).width() * 0.9;
  canvas.width = canvas.height = size;
  ctx.fillStyle = "red";
  ctx.fillRect(0, 0, size, size);
  //let r = 200;
  let degrees = 2*Math.PI / segmentCount;
  function drawSegment(){
    ctx.fillStyle = "black";
    ctx.strokeStyle = "white";
    ctx.moveTo(0,0);
    ctx.lineTo(r,0);
    ctx.arc(0,0,r,0,degrees);
    ctx.closePath();
    ctx.fill();
    ctx.stroke();
  }
  
  ctx.translate(size/2,size/2);
  ctx.scale(.7,.7);// the image is too big. I have to scale down the image.
  let image = new Image();
  image.src = "https://i.sstatic.net/5PqtU.png"
  image.onload = function() {
  for (let segmentIndex = 0; segmentIndex < segmentCount; segmentIndex++) {
  ctx.drawImage(image, 0, -image.height, image.width, image.height);
  //drawSegment()
  ctx.rotate(degrees);
  }
  }
  $(canvas).appendTo(document.body)
}

initializeWheel()
canvas {
  position: "absolute";
  left: 0;
  right: 0;
  margin: "auto";
  top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

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

Incorporating visuals into Doxygen documentation

Struggling to add an image with a caption in a doxygen .md file. Adding a caption is easy, but aligning the image left is proving difficult. I've tried several methods, but none have worked successfully. ![Caption](my_image.png "Caption") R ...

Error: PHP is showing an undefined index error when trying to decode JSON, even though the value

I am feeling quite puzzled. I transferred a key value pair object from jQuery to PHP and successfully alerted it back out. However, when I visit the PHP page, it indicates that the data is either null or an undefined index. Here is my jQuery code: $(&ap ...

make sure the <option> tags fit seamlessly inside a Bootstrap card

I'm currently working on a project using Angular in combination with Bootstrap 4.0. My goal is to integrate <select>, <option>, and <optgroup> elements within a card. Below is the code snippet from the component.html file: <div ...

Steps to display a JSX component stored in a variable

Presently, I am implementing an if/else statement within my code to determine the content that will be displayed in the JSX element named 'signupMessage'. Subsequently, I render the contents of this 'signupMessage' element. render() { ...

Is there a way to transform the SmartyStreets' jQuery.LiveAddress plugin into its JavaScript SDK?

My website currently utilizes the jQuery.LiveAddress plugin, however, it was deprecated and subsequently removed by SmartyStreets back in 2014. <script src="//ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <s ...

Every time I hit the play button on my video player, it starts playing multiple videos simultaneously on the same page

I'm having an issue with customizing a video player in HTML5. When I press play on the top video, it automatically plays both videos on the page simultaneously. For reference, here is my code on jsfiddle: http://jsfiddle.net/BannerBomb/U4MZ3/27/ Bel ...

Listener for 'timeupdate' event on video doesn't retain values

My html5 video event listener is designed to pause the video at a specific time while the user participates in a quiz. The first 'lesson' works fine, and the second video also appears to add the listener with the correct pause time. However, when ...

The variable process.env.CLIENT_ID is functioning correctly within a function, but does not work when declared as a global

Trying to implement oAuth for Google API Using .env file to hide sensitive variables with .gitignore Facing an issue when trying to define the CLIENT_ID variable globally CLIENT_ID = process.env.CLIENT_ID When I run and log the variable outside of a fun ...

Unexplainable space or padding issue detected in OwlCarousel grid gallery

There seems to be an unusual gap or margin at the bottom of each row section in this portfolio grid gallery that's running in OwlCarousel. You can view an example here. https://i.stack.imgur.com/NHOBd.png I've spent a lot of time trying to solv ...

Tips for designing a flexible structure with 2 columns, each containing an additional 2 columns within

Is it possible to create a 4-column responsive layout? | column left | column right | column left| column right| I would like to achieve a single row layout on larger devices as shown below | column left | column right | column left| column right| an ...

Creating a fullscreen layout in HTML with specific minimum and maximum widths

Looking to create a layout where one item takes up 1/3 of the screen-width with a minimum width of 500px and a maximum width of 700px, while another item fills the rest of the screen. Ideally, setting a width of 66% should work, but issues arise when the h ...

Using Django variable in li a:nth-child selector produces unexpected results

Currently, I am honing my web programming skills by working on a personal blog in Django. However, I have encountered a hurdle. My intention was to enable the webpage to recognize which menu element is active by passing an argument from views.py to the tem ...

Unable to navigate to the top of the page after logging in with Angular.js

There is a problem I need help with. After a user successfully logs in and enters the home page, the page automatically scrolls down due to angular.js. I want the page to remain at the top when the user reaches the home page. Can someone assist me in res ...

Executing PHP function through AJAX

I have thoroughly researched various resources regarding my issue but still have not been able to find a solution. My goal is to retrieve the result of a PHP function using jQuery AJAX. function fetch_select(){ val_name = $('#name').val(); ...

A guide on dynamically checking the checkbox values in each row of a table using JavaScript or jQuery

My table is dynamically populated with values from a database using the following code: var row = table.insertRow(i); i = i+1; // Insert new cells (<td> elements) at the 1st and 2nd position of the new <tr> element: var cell1 = row.insertCell ...

What is the method to retrieve the color of a linearGradient in an SVG at a particular

I am working on a unique progress bar that uses a linear gradient and a small ellipse to indicate the completion percentage. The AngularJS binding updates the completion percentage and a function is called. My challenge is to change the color of the ellip ...

Having trouble with the Tailwind transition in my Next.js component

I'm facing an issue with the ease out transition not working as expected. I need the side to slide in from left to right with a duration of 500ms. Despite trying various solutions, I can't seem to figure out why it's not functioning properly ...

The localhost server in my Next.js project is currently not running despite executing the 'npm run dev' command. When trying to access the site, it displays an error message saying "This site can't be

I attempted to install Next.js on my computer and followed the documentation provided to set up a Next.js project. You can find the documentation here. The steps I took were: Ran 'npx create-next-app@latest' Was prompted for the name of my proj ...

Using the setInterval function in conjunction with the remoteCommand to create a

I am attempting to create a remote command that calls a bean function and updates a progress bar every 2 seconds until cancelled. The remote command looks like this: <p:remoteCommand id="usedCall" name="queryUsed" onco ...

Enclose the text within the initial cell

I am trying to encapsulate a text label in the initial column of my table within a span. Although it seems like a simple task, I am encountering some issues. Here is my attempted solution: $('#myTable tr td:first-child').each(function() { va ...