Front end: Implement a turntable game with javascript?

This article mainly introduces how to use native javascript and Css3 to implement a turntable game that often appears in major mobile applications. Since the implementation can be implemented in different ways, if you are familiar with canvas, you can also use canvas. This article uses js and css to achieve the main considerations The complexity is less and the performance is better, so if there is a better solution, you can communicate with me at any time.

Preface

The technical route in this article uses the same technology as the previous article taught you to write a idolpinpin H5 mini game (with source code) with 200 lines of code , that is, use my own dom library to simplify the dom operation, which needs to be mastered. Knowledge points are:

  • css3 background gradient, transform, transition

  • Use of less loop

  • javascript basic random algorithm

  • The use of document fragment documentFragment

Since the article does not have too advanced technology, the key is the idea, so let's start our implementation introduction.

Effect picture

Realization idea

The realization idea is divided into two parts, the first part is to draw the background of the turntable with css, and the second part is to realize the rotation of the turntable and the realization of the randomness of rotation through js.

1. Draw the background of the turntable

We use the background gradient method to achieve the fan shape with alternating stripes. The principle is to draw a semicircle and add a gradient to the semicircle to achieve it, as shown below:

To realize the CSS that turns a square into a semicircle, we use border-radius to achieve:

    width: 150px;
    height: 300px;
    border-radius: 0 150px 150px 0;

We then use the linear gradient of css, so that basically a small fan-shaped area can be realized:

The code for the gradient is as follows:

background-image: linear-gradient(120deg, #f6d365, #f6d365 75px, transparent 75px);

To realize a fan shape, we can naturally calculate it. For example, if our fan shape is 30deg, then we need 12 fan shapes to form a circle. For convenience, we use the less loop to achieve:

.loop(@n) when (@n >= 0) {
    .loop(@n - 1);
    .piece-@{n} {
        transform: rotate(-30deg * (@n + 1));
    } 
}

Another detail is that we need to change the center point of the transformation so that each sector is rendered with a center point, so that a complete circle can be formed:

transform-origin: left center;

The complete css is roughly as follows:

.piece-wrap {
    position: relative;
    width: 300px;
    height: 300px;
    margin: 100px auto  auto 173px;
    transform-origin: left center;
    transition: transform 16s cubic-bezier(0,.47,.31,1.03);
    .piece {
        position: absolute;
        left: 0;
        top: 0;
        width: 150px;
        height: 300px;
        border-radius: 0 150px 150px 0;
        transform-origin: left center;
        span {
            margin-left: 16px;
            margin-top: 20px;
            display: inline-block;
            color: #fff;
        }
        &:nth-child(2n) {
            background-image: linear-gradient(120deg, #f6d365, #f6d365 75px, transparent 75px);
        }
        &:nth-child(2n+1) {
            background-image: linear-gradient(120deg, #ff5858, #ff5858 75px, transparent 75px);
        }
    }

    .loop(@n) when (@n >= 0) {
        .loop(@n - 1);
        .piece-@{n} {
            transform: rotate(-30deg * (@n + 1));
        } 
    }

    .loop(11);
}

2. javascript implements turntable logic

Since the rotation of the turntable is random, we need to randomly generate an angle every time we click the start button, but a careful analysis of some platforms will find that the turntable will slowly start to stop after turning at least n times each time, so we will Give the turntable an initial angle, such as 720deg, 1080deg, so as to ensure that the turntable rotates at least n times before stopping.

Another point to note is how do we know the position of the turntable after it has stopped by the angle of rotation? Here is a performance problem. We try not to operate dom as much as possible. Through data control, we can calculate the stop position by the angle obtained after randomization and the radian of the unit sector area. The formula is as follows:

totalRadis = initRadis + radis * n + radis / 2

totalRadis is the angle of rotation, initRadis is the initial angle, radis is the angle of the fan shape, and radis/2 is the range of winning, which is mainly used for positioning, and n is a random number. Next, I will explain the role of n.

So how to achieve a random angle? We usually want to do it by writing a random function, but here is a new idea, which is to achieve a random angle by randomly generating the winning position. Since my fan shape is 30 degrees, there are a total of 12 fan-shaped prize areas, so index For 0-11. Therefore, the n mentioned above is our random index, and we only need to write a random number that generates a specified range.

After understanding the above knowledge, we began to prepare the initialization data:

// 转盘抽奖数据
    var wards = ['1元', '2元', '3元', '5元', '再来', 
     '算法', '0.5元', '0.1元', '0.2元', '0.6元',
     '0.5元', '来'];

To render prize data, here we use DocumentFragment. Although it is not necessary for simple rendering, it may be useful later:

// 渲染dom
var fragment = document.createDocumentFragment();
for(var i=0, len = wards.length; i < len; i++) {
    var piece = document.createElement('div');
    piece.className = 'piece piece-' + i;
    piece.innerHTML = '<span>' + wards[i] + '</span>';
    fragment.appendChild(piece);
}

$('#piece_wrap')[0].appendChild(fragment);

Method of generating random numbers in a specified range:

// 生成从 start到end的随机数
function randomArr(start, end) {
    return Math.round(start + Math.random()* (end - start))
}

When we click the start button, I will make it move by changing the transform of the turntable:

// 转动逻辑
    var radis = 30,  // 每个扇形区域的度数
            n = randomArr(0, 360/radis),  // 计算随机中奖的位置
    initRadis = 720,   // 初始转动的角度
         time = 16 * 1000,    // 转动时间 
         once = true,    // 限制一个转动周期只能点击一次
   totalRadis = initRadis + radis * n + radis/2;  // 转动角度计算公式
$('.start').on('click', function(){
    if(once) {
        once = false;
        $('#piece_wrap').css({
            'transform':'rotate(' + totalRadis + 'deg)',
            'transition': 'transform 16s cubic-bezier(0,.47,.31,1.03)'
        });
        setTimeout(function(){
            once = true;
            alert('恭喜你抽中了' + wards[n] + '!');
            $('#piece_wrap').css({
                'transform':'rotate(' + 0 + 'deg)',
                'transition': 'none'
            });
        }, time)
    }
        
    })

That's the core code, how about it, is it very simple? If you want to experience actual case effects and technical exchanges, or feel more original h5 game source code, you can follow the experience below

Wonderful review

Relax

Guess you like

Origin blog.csdn.net/KlausLily/article/details/110358838