<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">

    <title>Canvas</title>

    <link rel="stylesheet" href="style.css">

</head>
<body>

<div class="container">
    <div class="caseRoulette">
        <canvas id="caseRoulette" width="800" height="180"></canvas>
    </div>
    <button id="caseRoulette__spin-button">Старт</button>
</div>

<script src="main.js"></script>

</body>
</html>
.container {
    max-width: 1280px;
    padding: 0;
    margin: 0 auto;
}

.caseRoulette {
    display: flex;
    justify-content: center;
    margin-top: 120px;
}

canvas {
    border: 1px solid red;
}
const canvas = document.getElementById("caseRoulette");
const spinButton = document.getElementById("caseRoulette__spin-button")
const ctx = canvas.getContext("2d");

const widthItemBlock = 180;
const widthImage = 140;
const heightImage = 100;
const marginImage = 40;

const items = [
    {
        firstname: "AWP",
        secondname: "Азимов",
        image: `https://steamcommunity-a.akamaihd.net/economy/image/fWFc82js0fmoRAP-qOIPu5THSWqfSmTELLqcUywGkijVjZYMUrsm1j-9xgEObwgfEh_nvjlWhNzZCveCDfIBj98xqodQ2CZknz56I_OKMyJYcxPSPqFNVfg14jfhDCM7_cotUNTkp-gAKF3otIfBOuUoNdBIHMCDX_SCZF_9uR8w0fJUfpyPpC7n3jOpZDl_eS2fcg/${widthImage}fx${heightImage}f/image.png`,
        rarity: "covert",
    },
    {
        firstname: "AK-47",
        secondname: "Снежная буря",
        image: `https://steamcommunity-a.akamaihd.net/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgpot7HxfDhjxszJemkV08u_mpSOhcjnI7TDglRd4cJ5ntbN9J7yjRrn8xA4Yj3yd9OSdFU7aVmF8wPvwrrpgpG47c7InHVjuiMm5ymOn0S2n1gSOR29uyL_/130fx97f/image.png`,
        rarity: "classified",
    },
    {
        firstname: "M4A4",
        secondname: "Азимов",
        image: `https://steamcommunity-a.akamaihd.net/economy/image/fWFc82js0fmoRAP-qOIPu5THSWqfSmTELLqcUywGkijVjZYMUrsm1j-9xgEObwgfEh_nvjlWhNzZCveCDfIBj98xqodQ2CZknz52YOLkDzRyTQmWPqFNVfg14jfhDCM7_cotVtLn87oCewy8ttHBZ7J6ZIsaGMHWDPKFM1_940k60vRdfZTcpCi8iTOpZDkfJ7O9Pw/130fx97f/image.png`,
        rarity: "covert",
    },
    {
        firstname: "Glock-18",
        secondname: "Водяной",
        image: `https://steamcommunity-a.akamaihd.net/economy/image/fWFc82js0fmoRAP-qOIPu5THSWqfSmTELLqcUywGkijVjZYMUrsm1j-9xgEObwgfEh_nvjlWhNzZCveCDfIBj98xqodQ2CZknz58OOy2OwhkZzvFDa9dV7g2_Rn5DDQx7cl3a9qz87ITJBLmsoHEYbAtMNEeF8iBU_CFNVqrv09sgqJfKsTbqCu5iyrob2deCBC65Ctazz387ae9/130fx97f/image.png`,
        rarity: "classified",
    },
    {
        firstname: "Desert Eagle",
        secondname: "Пламя",
        image: `https://steamcommunity-a.akamaihd.net/economy/image/-9a81dlWLwJ2UUGcVs_nsVtzdOEdtWwKGZZLQHTxDZ7I56KU0Zwwo4NUX4oFJZEHLbXH5ApeO4YmlhxYQknCRvCo04DEVlxkKgposr-kLAtl7PLJTjtO7dGzh7-HnvD8J_XVkjoFuMYiiLqUrI-k3le3r0s5amj7d9eTI1I-M1rW-Fm_xO-50Jfvot2XnhS4_w8U/130fx97f/image.png`,
        rarity: "restricted",
    }
]

const random = (min, max) => Math.floor(Math.random() * (max - min + 1) + min);

const image = [];
const fps = 60;

let speedRoulette = 2;
let distance = 0;
let offset = 0;
let posX;

let randomNumber;
let randomNumberOnItem;
let itemWinner;

let itemsFillMassive = items;

// https://gist.github.com/gre/1650294
function easeOutQuad(t) {
  return t*(2-t);
}

function itemsFill() {
    itemsFillMassive = doubleArray(itemsFillMassive);
    itemsFillMassive = doubleArray(itemsFillMassive);
    itemsFillMassive = shuffleArray(itemsFillMassive);
    // itemsHandler()
}

function doubleArray(array) {
    return array.concat(array);
}

function shuffleArray(array) {
    return array.sort(() => Math.random() - 0.5);
}

function itemsHandler() {
    for (let i = 0; i < itemsFillMassive.length; i++) {
        const img = new Image();
        img.firstname = itemsFillMassive[i].firstname;
        img.secondname = itemsFillMassive[i].secondname;
        img.rarity = itemsFillMassive[i].rarity;
        img.src = itemsFillMassive[i].image;
        image.push(img)
    }
    randomNumber = random(image.length / 2, image.length / 1.5)
    randomNumberOnItem = random(0, widthImage)
    itemWinner = (((widthImage + marginImage) * randomNumber) - (canvas.width / 2 + 1.5)) + randomNumberOnItem
    console.log(itemsFillMassive)
    console.log("Random item: " + randomNumber)
    console.log("Random position on item: " + randomNumberOnItem)
    requestAnimationFrame(draw);
}

const duration = 3000;
let begin = 0;


function draw(now) {
    begin = begin || now;
    const t = Math.min(1, (now - begin) / duration);
    ctx.clearRect(0, 0, canvas.width, canvas.height);

    for (let key in image) {

        posX = ((widthImage + marginImage) * key) - offset

        // Background
        if (image[key].rarity === "covert") {
            ctx.fillStyle = "#e23000";
        } else if (image[key].rarity === "classified") {
            ctx.fillStyle = "#e200a0";
        } else if (image[key].rarity === "restricted") {
            ctx.fillStyle = "#8000e2";
        }

        ctx.fillRect(posX, 5, widthItemBlock, canvas.height - 10);

        // Image
        ctx.drawImage(image[key], posX + 20, 5, widthImage, heightImage);

        // Text
        ctx.font = "16px serif";
        ctx.fontWeight = "700";
        ctx.fillStyle = "#ffffff";
        ctx.textAlign = "center";
        ctx.fillText(image[key].firstname, posX + widthItemBlock / 2, 140);
        ctx.fillText(image[key].secondname, posX + widthItemBlock / 2, 160);

    }

    ctx.moveTo(canvas.width / 2 + 0.5, 0);
    ctx.lineTo(canvas.width / 2 + 0.5, canvas.height);
    ctx.strokeStyle = "rgba(0, 0, 0, 0.5)";
    ctx.stroke();

    const rouletteSpin = requestAnimationFrame(draw);

    distance = Math.floor(itemWinner - offset);
    offset = itemWinner * easeOutQuad(t);

    if (t === 1) {
        cancelAnimationFrame(rouletteSpin);
        begin = 0;
        console.log("Анимация завершилась на предмете")
        itemsFillMassive = items
        spinButton.hidden = false
    }

}

spinButton.onclick = () => {
    spinButton.hidden = true
    itemsHandler()
};

itemsFill()

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.