I got this code (the answer from Roko C. Buljan). I am transforming it into a class where each instance should be a different wheel.
The constructors receives 3 parameters, 2 of them are dom elements and the least one is an array with all the sectors of the wheel.
The problem is that js says the var wheel
(the dom element I passed through the constructor) is undefined.
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>site do prof Matheus</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<link rel='stylesheet' type='text/css' media='screen' href='main.css'>
<!-- <script src='./src/main.js'></script> -->
</head>
<body>
<div id="roulette">
<canvas id="wheel" width="300" height="300"></canvas>
<div id="spin">SPIN</div>
</div>
<div id="op_roulette">
<canvas id="op_wheel" width="300" height="300"></canvas>
<div id="op_spin">SPIN</div>
</div>
<script type="module" src="./src/main.js"></script>
</body>
</html>
main.js:
import { wheel } from "./wheel.js";
const sectors = [
{ color: "#f82", label: "1" },
{ color: "#0bf", label: "2" },
{ color: "#fb0", label: "3" },
{ color: "#0fb", label: "4" },
{ color: "#b0f", label: "5" },
{ color: "#f0b", label: "-1" },
{ color: "#bf0", label: "-2" },
{ color: "#f82", label: "-3" },
{ color: "#0bf", label: "-4" },
{ color: "#fb0", label: "-5" },
{ color: "#0fb", label: "0" },
{ color: "#b0f", label: "n" },
];
var mywheel = new wheel(
document.querySelector("#spin"),
document.querySelector("#wheel").getContext('2d'),
sectors
)
wheel.js:
class wheel {
static friction = 0.991; // 0.995=soft, 0.99=mid, 0.98=hard
rad = wheel.canvas.width / 2;
arc = 2 * Math.PI / sectors.length;
angVel = 0; // Angular velocity
ang = 0; // Angle in radians
getIndex = () => Math.floor(sectors.length - ang / (2 * Math.PI) * sectors.length) % sectors.length;
drawSector(sector, i) {
const ang = arc * i;
wheel.save();
// COLOR
wheel.beginPath();
wheel.fillStyle = sector.color;
wheel.moveTo(rad, rad);
wheel.arc(rad, rad, rad, ang, ang + arc);
wheel.lineTo(rad, rad);
wheel.fill();
// TEXT
wheel.translate(rad, rad);
wheel.rotate(ang + arc / 2);
wheel.textAlign = "right";
wheel.fillStyle = "#fff";
wheel.font = "bold 30px sans-serif";
wheel.fillText(sector.label, rad - 10, 10);
//
wheel.restore();
};
rotate() {
const sector = sectors[getIndex()];
wheel.canvas.style.transform = `rotate(${ang - Math.PI / 2}rad)`;
EL_spin.textContent = !angVel ? "SPIN" : sector.label;
EL_spin.style.background = sector.color;
}
frame() {
if (!angVel) return;
angVel *= friction; // Decrement velocity by friction
if (angVel < 0.002) angVel = 0; // Bring to stop
ang += angVel; // Update angle
ang %= 2 * Math.PI; // Normalize angle
rotate();
}
engine() {
frame();
requestAnimationFrame(engine)
}
// INIT
constructor(EL_spin, wheel, sectors) {
this.sectors = sectors;
this.EL_spin = EL_spin;
this.wheel = wheel;
this.wheel.sectors.forEach(this.drawSector.bind(this));
rotate(); // Initial rotation
engine(); // Start engine
this.wheel.EL_spin.addEventListener("click", () => {
if (!angVel) angVel = Math.random() * (0.25 - 0.35) + 0.35;
});
};
}
export { wheel };
main.css:
#roulette {
display: inline-block;
position: relative;
overflow: hidden;
}
#wheel {
display: block;
}
#spin {
font: 1.5em/0 sans-serif;
user-select: none;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 50%;
left: 50%;
width: 30%;
height: 30%;
margin: -15%;
background: #fff;
color: #fff;
box-shadow: 0 0 0 8px currentColor, 0 0px 15px 5px rgba(0, 0, 0, 0.6);
border-radius: 50%;
transition: 0.8s;
}
#spin::after {
content: "";
position: absolute;
top: -17px;
border: 10px solid transparent;
border-bottom-color: currentColor;
border-top: none;
}
#op_roulette {
display: inline-block;
position: relative;
overflow: hidden;
}
#op_wheel {
display: block;
}
#op_spin {
font: 1.5em/0 sans-serif;
user-select: none;
cursor: pointer;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
top: 50%;
left: 50%;
width: 30%;
height: 30%;
margin: -15%;
background: #fff;
color: #fff;
box-shadow: 0 0 0 8px currentColor, 0 0px 15px 5px rgba(0, 0, 0, 0.6);
border-radius: 50%;
transition: 0.8s;
}
#op_spin::after {
content: "";
position: absolute;
top: -17px;
border: 10px solid transparent;
border-bottom-color: currentColor;
border-top: none;
}
and here is the error im getting:
Uncaught TypeError: Cannot read properties of undefined (reading 'width')
at wheel.<instance_members_initializer> (wheel.js:3:24)
at new wheel (wheel.js:54:16)
at main.js:18:15