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)
And our design drawing is designed like this (the text is parallel to the radius)
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.
The following summarizes some implementation ideas: divided into canvas version and div+css version
Implementation of canvas idea
- Canvas turntable drawing, including the drawing of text and pictures on each sector (in fact, this needs to be changed)
- Recursive requestAnimationFrame and then constantly changing the starting angle of drawing (the initial angle of canvas drawing) to make the turntable move
- 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:
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 rotate2 * 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
- requestAnimationFrame is nothing to say, browsing compatibility is not a problem now
- 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
- 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
- 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 waytransform: skew(-y) rotate(-x)
reference - 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
- The core code is developed with ts (without framework dependency)
- Considering that the scenario that my code satisfies is relatively niche and is not packaged as an npm package
- Friends who have the same scene needs can copy the code directly
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。