好久之前就想去写一个这样的示例了,然后就忘了…
在线链接
https://linyisonger.github.io/H5.Examples/?name=./34.%E6%8A%BD%E5%A5%96%E9%A1%B5%E9%9D%A2.html
图片可能会丢失,都是在网上随便搜的。
这里使用到了贝塞尔函数,如果不懂可以看看。
三钻老师的 https://blog.csdn.net/TriDiamond6/article/details/115438950
这种数学对于我来说太难了,看不是很懂。
首先先引用@3r/tool
这个包
⚠生产可不要这样去写哦!这种写法可能会导致一些适配问题,我这里是演示,就很随便。
<script type="module">
import { Maths, Randoms, Animation } from "https://gcore.jsdelivr.net/npm/@3r/[email protected]/index.js"
script>
书写元素位置,这个位置顺序影响着效果中黄框转动的方向,当然你可以使用javascript
去循环出来,我比较赖,哈哈哈哈。
<div class="prize-container">
<div class="prize-item" style="left: 0;top: 0;">div>
<div class="prize-item" style="left: 200px;top: 0;">div>
<div class="prize-item" style="left: 400px;top: 0;">div>
<div class="prize-item" style="left: 400px;top: 200px;">div>
<div class="prize-item" style="left: 400px;top: 400px;">div>
<div class="prize-item" style="left: 200px;top: 400px;">div>
<div class="prize-item" style="left: 0;top: 400px;">div>
<div class="prize-item" style="left: 0;top: 200px;">div>
<div class="prize-turn" style="left: 200px;top: 200px;">开始转动div>
div>
将奖品渲染到页面盒子中去
let prizes = [
{
name: '苹果13',
weight: 1,
imgSrc: 'https://img10.360buyimg.com/n1/s450x450_jfs/t1/122791/34/35195/31712/63e4d4f8Fc242eca8/e8b37a3c1c707551.jpg'
},
{
name: '兰博基尼5元优惠券',
weight: 1000,
imgSrc: 'https://youjia-image.cdn.bcebos.com/modelImage/5567ba4dd1ac4a059511ce1968cf8e31/16233074995453266694.jpg@!watermark_1'
},
{
name: '香港一日游满5000-5券',
weight: 200,
imgSrc: 'https://wx4.sinaimg.cn/mw690/0076qYpPgy1hb22ws8hjdj30nw0fydp9.jpg'
},
{
name: '王者荣耀绝美皮肤一套',
weight: 200,
imgSrc: 'https://img2.40407.com/upload/202111/09/091448320eecb8dV5D4vrsertjn.jpg'
},
{
name: '鼠标垫',
weight: 200,
imgSrc: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fcbu01.alicdn.com%2Fimg%2Fibank%2F2020%2F940%2F595%2F17542595049_1110060834.jpg&refer=http%3A%2F%2Fcbu01.alicdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1678946052&t=f6b6664f8bfb36eee1bfa142f74e6dc5'
},
{
name: '再来一次',
weight: 100,
imgSrc: 'https://q.qqbiaoqing.com/q/2017/03/04/33a5791469c29d97fea7e7a96debdf4c.gif'
},
{
name: '吹风机',
weight: 20,
imgSrc: 'https://img2.baidu.com/it/u=4244035486,2082281147&fm=253&fmt=auto&app=138&f=JPEG?w=777&h=500'
},
{
name: '扫地机器人',
weight: 10,
imgSrc: 'https://img0.baidu.com/it/u=305646170,4023681037&fm=253&fmt=auto&app=120&f=JPEG?w=600&h=433'
},
]
// 展示效果
for (let i = 0; i < prizeDomList.length; i++) {
const prizeItem = prizeDomList[i];
const prizeText = document.createElement('div')
const prizeImage = document.createElement('img')
prizeText.textContent = prizes[i].name
prizeImage.setAttribute("src", prizes[i].imgSrc)
prizeItem.appendChild(prizeImage)
prizeItem.appendChild(prizeText)
}
这里通过await
和setTimeout
进行等待,通过循环次数的easeIn的值延迟时间的比例来更改延迟时间*,从而达到从快到慢的过程。
通过奖品权重值的大小来随机出现占比程度,越大越容易出现。
当曲线值大于0.9且开始索引取余于数组长度是否与结束索引相等的时候,判断是否可以结束。
关于曲线值大于0.9这点儿写的感觉有点随便了,一般写应该是从开始就算好到哪里停的,这点儿我不知道怎么去算,会的可以跟我讲讲,谢谢~
// 等待时间
let waitTime = function (time) {
return {
then: function (resolve) {
setTimeout(resolve, time)
}
}
}
// 转动
let turn = async function () {
let offset = 1 / (prizes.length * 10) // 执行次数
let interval = 200; // 延迟
let minInterval = 50; // 最小延迟
let endIndex = Randoms.getRandomIndexByWeight(prizes) // 随机结束奖品
let lastDom = null
for (let i = 0; i <= 1; i += offset) {
// 延迟时间
await waitTime(Math.max(Animation.easeIn(i) * interval, minInterval))
lastDom?.classList?.remove('active');
lastDom = prizeDomList.item(startIndex % prizeDomList.length)
lastDom.classList.add('active')
if (i > .9 && (startIndex % prizeDomList.length === endIndex)) break;
startIndex++;
}
let name = prizes[endIndex].name
setTimeout(() => {
if (name == "再来一次")
alert(`请${name}吧~`)
else
alert(`您获得了${name}`)
}, interval);
}
https://github.com/linyisonger/H5.Examples