DEV Community

Cover image for Wheel of Fortune with CSS

Wheel of Fortune with CSS

Mads Stoumann on May 23, 2024

A "Wheel of Fortune" component just popped up in my feed. I always spin, but never win! Anyway, this type of component is often built with <canv...
Collapse
 
afif profile image
Temani Afif

The height calculation is actually not correct. You need to consider the polygon shape around the circle to find the correct height (the circumscribed polygon)

It's equal to height: calc(2*50cqi*tan(180deg/var(--_items))); that you can simplify by setting the ratio aspect-ratio: 1/calc(2*tan(180deg/var(--_items))); to avoid using the width value twice.

With this you won't have issue when you apply the clip-path

Collapse
 
madsstoumann profile image
Mads Stoumann • Edited

AH, perfect — thank you! You truly are the master of CSS Shapes. I've added an update, and will use your input for the follow-up article with spinning.

Collapse
 
martin_prihoda_2e16335cab profile image
Martin Prihoda

Has anyone solved the return value of the winning field? For example index for li tag. I have something, but the results are +- one position.

Collapse
 
martin_prihoda_2e16335cab profile image
Martin Prihoda

I think it’s resolved ( Link on Codepen.io ).

// --------------------------------------------
// append code for getting index of wheel spim
// --------------------------------------------
const rangeAngles = [
  {index:  0, from: 345, to: 360},
  {index:  0, from:   0, to:  15},
  {index:  1, from:  15, to:  45},
  {index:  2, from:  45, to:  75},
  {index:  3, from:  75, to: 105},
  {index:  4, from: 105, to: 135},
  {index:  5, from: 135, to: 165},
  {index:  6, from: 165, to: 195},
  {index:  7, from: 195, to: 225},
  {index:  8, from: 225, to: 255},
  {index:  9, from: 255, to: 285},
  {index: 10, from: 285, to: 315},
  {index: 11, from: 315, to: 345},
];

// position at zero level
const calculateZeroAngle = (finalAngle) => {
  let zeroAngle = 360 - finalAngle + 90;
  zeroAngle = ((zeroAngle % 360) + 360) % 360;
  zeroAngle = Math.round(zeroAngle * 10) / 10;
  return zeroAngle;
};

// Save the final degree to determine the winning segment
animation.onfinish = async () => {
  const finalAngle = ((newEndDegree % 360) + 360) % 360;
  const zeroAngle = calculateZeroAngle( finalAngle );
  const indexfOfWinner = rangeAngles.find( a => a.from < zeroAngle && a.to >= zeroAngle ).index
  alert( `Index of Winner: ${indexfOfWinner}` )
};
Enter fullscreen mode Exit fullscreen mode
Collapse
 
madsstoumann profile image
Mads Stoumann
const normalizeAngle = (finalAngle) => {
  return (360 - finalAngle + 90) % 360;
};

const items = wheel.children.length;
const segment = 360 / items;
const offset = 15;

animation.onfinish = () => {
  const finalAngle = newEndDegree % 360;
  const normalizedAngle = normalizeAngle(finalAngle);
  const winner = Math.floor(((normalizedAngle + offset) % 360) / segment);
  console.log(wheel.children[winner].textContent);
};
Enter fullscreen mode Exit fullscreen mode
Collapse
 
madsstoumann profile image
Mads Stoumann

Cool!

Collapse
 
madsstoumann profile image
Mads Stoumann

Please share — I need to think about it too!

Collapse
 
ddebajyati profile image
Debajyati Dey

wholesome wheel! :)
Beautiful project!

Collapse
 
madsstoumann profile image
Mads Stoumann

Thank you!

Collapse
 
jocomvag profile image
Jocom Vag

Always here for an interesting CSS project. Kudos.

Collapse
 
madsstoumann profile image
Mads Stoumann

Thanks!

Collapse
 
efpage profile image
Eckehard

I suppose this would be easier done in pure Javasript using CSS only where It's appropriate (e.g. the animation). Is it really worth the effort doing anything in CSS?

Collapse
 
lcsga profile image
LcsGa

I don't think that'd be easier in javascript. Whenever you have something visual, the right tool for that is CSS. When it's easier in pure JS, this usually mean that you lack knowledge with CSS.

Collapse
 
efpage profile image
Eckehard

Oh, have fun to rebuild the [solarsystem][dev.to/cookiemonsterdev/solar-syst...] with pure CSS. There are good reasons the S in
CSS comes from "style", not from graphics...