仿csgo横向滚动抽奖效果 (源码直接复制)

仿csgo横向滚动抽奖效果 (源码直接复制)

简述

  • 最近小伙伴找到我,希望可以写一个仿csgo横向滚动抽奖效果,快速写了一个demo满足需求,记录一下具体代码。

效果

在这里插入图片描述

抽奖特效

代码

<template>
  <div id="app">
    <div>
      <div class="wrap">
        <div class="check">↑</div>
        <div class="list-group-wrap" :class="{ roll_animation: rollState == 'start' }" :style="{
          transform: `translateX(${translateX}px)`,
          'transition-duration': duration + 'ms',
        }">
          <div v-for="(item, index) in shaftList" :key="index" :style="{
            background: item.color,
          }" class="list-group-item">
            {{ item.index }}
          </div>
          <!-- <div class="list-group-wrap"></div> -->
        </div>
      </div>
      <div style="margin-left: 65px; margin-top: 15px">
        <button @click="roll({ index: 1 })">1</button>
        <button @click="roll({ index: 4 })">4</button>
        <button @click="roll({ index: 5 })">5</button>
        <button @click="roll({ index: 6 })">6</button>
        <button @click="roll({ index: 7 })">7</button>
        <button @click="roll({ index: 8 })">8</button>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  data () {
    return {
      prizeList: [
        { "index": 1, "color": "red" },
        { "index": 2, "color": "orange" },
        { "index": 3, "color": "yellow" },
        { "index": 4, "color": "green" },
        { "index": 5, "color": "blue" },
        { "index": 6, "color": "indigo" },
        { "index": 7, "color": "violet" },
        { "index": 8, "color": "pink" },
        { "index": 9, "color": "brown" },
        { "index": 10, "color": "grey" },
        { "index": 11, "color": "purple" },
        { "index": 12, "color": "cyan" },
        { "index": 13, "color": "magenta" },
        { "index": 14, "color": "lime" },
        { "index": 15, "color": "teal" }
      ],
      // 位置
      translateX: 0,
      // 摇奖状态
      rollState: "stop",
      // 总的摇奖时间 单位毫秒
      duration: 4000,
      // 滚动列表
      shaftList: [],
      selfWidth: 0,
      defaultNum: 4,//第一次加载时指针指向的数字 (宽度修改了这里也要改变)
    };
  },
  mounted () {
    this.init({
      duration: 3500,
    });
    this.$nextTick(() => {
      let element = document.querySelector('.list-group-item')
      let computedStyle = window.getComputedStyle(element);
      this.selfWidth = Number(computedStyle.width.replace('px', '')) + Number(computedStyle.marginRight.replace('px', ''));
      console.log(Number(computedStyle.width.replace('px', '')) + Number(computedStyle.marginRight.replace('px', '')))
    })
  },
  methods: {
    // 初始化
    init ({
      duration = 3500,
    }) {
      // 最低4秒
      if (duration < 4000) {
        duration = 4000;
      }
      this.shaftList = [];
      this.shaftList = this.shuffle(this.prizeList, 9);
      this.$nextTick(function () {
        this.duration = duration;
      });
    },
    // 拷贝们的数组,方遍横项滚动
    shuffle (arr, num) {
      let tmpShaft = [];
      while (num > 0) {
        tmpShaft.push(...arr);
        num--;
      }
      return tmpShaft;
    },
    // 设定位置
    setTranslateX (index) {
      const groupPrizeLength = this.prizeList.length
      // 倒序遍历奖品列表,找出开奖结果的最靠后的下标
      for (let k = this.shaftList.length - 1 - groupPrizeLength; k >= 0; k--) {
        console.log(this.shaftList[k].index == index, this.shaftList[k].index, index, k)
        if (this.shaftList[k].index == index) {
          // 延迟滚动
          this.translateX = -(k - (this.defaultNum - 1)) * this.selfWidth;
          break;
        }
      }
    },
    // 摇奖
    roll ({
      index
    }) {
      if (this.rollState == "start") {
        return console.warn("正在抽奖哦!");
      }

      this.rollState = "start";
      // 滚动到指定位置
      this.setTranslateX(index);
      setTimeout(() => {
        this.stop(index);
      }, this.duration + 1000);
    },
    stop (index) {
      this.rollState = "stop";
      this.$nextTick(function () {
        // 停止滚动之后,位移到第二组奖品列表的对应位置,为下一次摇奖留下滚动空间,实现多次摇奖无缝滚动效果
        this.translateX = -(this.prizeList.length + (index - (this.defaultNum))) * this.selfWidth;
      });
    },
  },
};
</script>

<style scoped>
.wrap {
  position: relative;
  margin-top: 15px;
  margin-left: 30px;
  width: 740px;
  height: 120px;
  border: 1px solid #ccc;
  border-radius: 5px;
  overflow: hidden;
}

.check {
  position: absolute;
  left: 50%;
  right: 50%;
  bottom: 0;
  z-index: 999;
}

.list-group-wrap {
  /* position: absolute; */
  width: 63000px;
  /* display: flex */
  /* align-items: center; */
  /* position: absolute; */
  /* width: 2400px; */
  transition-property: none;
  transition-duration: 0s;
  padding: 10px;
}

.list-group-item {
  display: inline-block;
  width: 100px;
  height: 100px;
  margin-right: 10px;

}

.item_actived {
  border: 3px dashed #c5821c;
}

.roll_animation {
  transition-property: transform;
  transition-timing-function: cubic-bezier(0, 0, 0.58, 1);
}
</style>

### 实现CSS仿CSGO抽奖动画中的放大镜效果 要实现类似于CSGO抽奖动画中的放大镜效果,可以通过组合HTML、CSS以及JavaScript来完成。以下是具体的实现方法: #### HTML结构 首先定义基本的HTML结构,用于展示奖品列表和放大镜区域。 ```html <div class="prize-container"> <div class="magnifier"></div> <ul class="prizes"> <li>奖项1</li> <li>奖项2</li> <li>奖项3</li> <!-- 更多奖项 --> </ul> </div> ``` #### CSS样式 通过CSS设置基础布局和动态效果。 ##### 奖品容器 奖品容器需要支持横向滚动,并隐藏溢出部分的内容。 ```css .prize-container { position: relative; overflow: hidden; /* 隐藏超出的部分 */ width: 400px; /* 容器宽度可以根据实际需求调整 */ } ``` ##### 放大镜层 放大镜是一个透明的覆盖层,通常会跟随鼠标移动并高亮显示特定范围内的内容。 ```css .magnifier { position: absolute; top: 0; left: 0; width: 80px; /* 放大镜宽度 */ height: 100%; /* 和父级高度一致 */ background-color: rgba(255, 255, 255, 0.7); /* 半透明背景色 */ pointer-events: none; /* 不响应点击事件 */ transform: translateX(-9999px); /* 初始位置不可见 */ transition: all 0.3s ease-in-out; /* 平滑过渡效果 */ } ``` ##### 奖品列表 奖品列表采用水平排列的方式,配合`white-space: nowrap`属性防止换行。 ```css .prizes { list-style-type: none; padding: 0; margin: 0; white-space: nowrap; /* 防止自动换行 */ overflow-x: auto; /* 启用水平滚动条 */ } .prizes li { display: inline-block; min-width: 100px; /* 每项奖品的最小宽度 */ text-align: center; line-height: 50px; /* 调整垂直居中 */ font-size: 16px; border: 1px solid #ccc; box-sizing: border-box; } ``` #### JavaScript交互逻辑 利用JavaScript监听鼠标的移动事件,实时更新放大镜的位置。 ```javascript const container = document.querySelector('.prize-container'); const magnifier = document.querySelector('.magnifier'); container.addEventListener('mousemove', (e) => { const rect = container.getBoundingClientRect(); const mouseX = e.clientX - rect.left; // 计算放大镜的新位置 let newPosition = Math.min(Math.max(mouseX - magnifier.offsetWidth / 2, 0), rect.width - magnifier.offsetWidth); // 更新放大镜的位置 magnifier.style.transform = `translateX(${newPosition}px)`; // 显示放大镜 magnifier.style.transform = 'none'; }); ``` 以上代码实现了当用户将鼠标悬停在奖品容器上时,放大镜会随之移动的效果[^1]。 --- ### 注意事项 为了优化用户体验,还可以进一步增强功能: - 添加动画效果使放大镜平滑移动; - 使用媒体查询适配不同屏幕尺寸下的表现; - 如果涉及复杂的视觉特效,可能还需要引入Canvas或其他图形库辅助开发。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lazy_tomato

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值