头图
Recently, there is a need to develop a page of the lottery big turntable. I thought that this kind of thing must be ready-made, but after looking around, I found that it is basically different from our design drawing. If you directly use the ready-made package It is estimated that the acceptance will not pass.

The layout of open source projects is generally like this (the text in the turntable is facing the center of the circle). We recommend a popular open source project that supports multiple terminals and multiple game modes (big turntable, nine-square grid, slot machine)

image.png

And our design drawing is designed like this (the text is parallel to the radius)

image.png

Unfortunately, the ready-made packages cannot be used, so we plan to downgrade the open source project and modify it to meet the requirements of our business scenario.

stackblitz effect preview

The following summarizes some implementation ideas: divided into canvas version and div+css version

Implementation of canvas idea

  1. Canvas turntable drawing, including the drawing of text and pictures on each sector (in fact, this needs to be changed)
  2. Recursive requestAnimationFrame and then constantly changing the starting angle of drawing (the initial angle of canvas drawing) to make the turntable move
  3. Use the easing algorithm to make the turntable rotate more naturally: the initial stage of the turntable is slow 加速 -> 匀速 -> 减速 finally stops at the specified sector (the winning result must be returned by the api, the front end needs to be controlled and finally stops at the specified position, according to lucky -The statement on the canvas is 刻舟求剑 )

Here are some points to note:

  1. The canvas drawing needs to be noted that the starting angle starts from three o'clock, and the drawing circle is 2 * Math.PI . My requirement is to have 8 sectors, that is, to rotate 2 * Math.PI / 8 * 2 ), it is recommended to convert radians (I don't know if it is correct to use radians here 😄) into an angle during development, so that the operation process is more convenient, It will also reduce the error caused by infinite non-looping decimals

     /**
     * 转换为运算角度
     * @param { number } deg 数学角度
     * @return { number } canvas 画圆角度
     */
    const getAngle(deg: number): number => (Math.PI / 180) * deg
  2. requestAnimationFrame is nothing to say, browsing compatibility is not a problem now
  3. Easing algorithm: In fact, it calculates a value (the amount of change of animation) based on some series of variables. For details, please refer to Zhang Xinxu's simple implementation of tween.js
  4. The sector where the turntable stops, according to the winning result returned by the api, the sector index index is obtained: const prizeDeg = 360 - index * (360 / 8) + initDeg; (initDeg is the initial angle of the first rotation)
After the requirements are completed, I found that it is very convenient to use div without canvas to achieve this effect.

div implementation

Except for the first step of turntable drawing, the other two steps have roughly the same idea

  1. Use div + css instead of canvas, mainly used --- transform: rotate(-x) skew(-y) transform: rotate(x) skew(y) , it should be noted that the child elements of div will also be rotated and twisted after twisting. transform: rotate(-x) skew(-y) , but I don't know that transform transformations are ordered in this way transform: skew(-y) rotate(-x) reference
  2. After using div, the rotation is not constantly redrawing the canvas, it only needs to constantly change the parent element's transform: rotate() , which is much simpler than the canvas

Code reference https://github.com/hugeorange/lucky-spin

  1. The core code is developed with ts (without framework dependency)
  2. Considering that the scenario that my code satisfies is relatively niche and is not packaged as an npm package
  3. Friends who have the same scene needs can copy the code directly

大桔子
588 声望51 粉丝

下一步该干什么呢...