vue3.0+TypeScript实现卡片九宫格选中后卡片翻转特效

vue3.0+TypeScript实现卡片九宫格选中后卡片翻转特效

在这里插入图片描述

API:
参数说明类型默认值
intervalTime卡片抽奖间隔时间number
delayTime中奖延迟显示时间number
priceWidth抽奖卡片的宽度number
priceHeight抽奖卡片的高度度number
circleTime抽奖几次之后中奖number
circleNum抽奖转动的次数number
priceId中奖ID(需要后台返回)number
抽奖数据API:
参数说明类型默认值
id抽奖IDnumber
info中奖信息string
front中奖面图片地址string
back抽奖面图片地址string
代码示例(父组件):
父组件
<template>
  <Lottery :priceList="priceList"></Lottery>
</template>
<script setup lang="ts">
import { ref, onMounted } from "vue";
import Lottery from "./../compoments/lottery.vue";
onMounted(() => {
  // getSlideEle()
});
// 左侧浮窗轮播列表
const bargainUserVosList = ref([
  "1恭喜书友123***5464获得《生命的真相》实体书5折券一张",
  "2恭喜书友123***5464获得《生命的真相》实体书5折券一张",
  "3恭喜书友123***5464获得《生命的真相》实体书5折券一张",
  "4恭喜书友123***5464获得《生命的真相》实体书5折券一张",
  "5恭喜书友123***5464获得《生命的真相》实体书5折券一张",
  "6恭喜书友123***5464获得《生命的真相》实体书5折券一张",
  "7恭喜书友123***5464获得《生命的真相》实体书5折券一张",
]);
interface priceInfo {
  // 抽检间隔时间
  intervalTime: number;
  // 中奖延迟显示时间
  delayTime: number;
  // 中间显示奖品宽度
  priceWidth: number;
  // 中间显示奖品高度
  priceHeight: number;
  // 抽奖次数
  circleTime: number;
  // 抽奖循环次数
  circleNum: number;
  // 中奖Id
  priceId: number;
}
interface listInfo {
  id?: number;
  front?: string;
  back?: string;
  info?: string;
}
const priceList: listInfo[] = [
  {
    id: 1,
    info: "1元优惠券",
    front: "https://XXX.com/activity/smile/is_all.png",
    back: "https://XXX.com/activity/smile/all.png",
  },
  {
    id: 2,
    info: "10元优惠券",
    front: "https://XXX.com/activity/smile/is_person.png",
    back: "https://XXX.com/activity/smile/person.png",
  },
  {
    id: 3,
    info: "谢谢惠顾",
    front: "https://XXX.com/activity/smile/is_good.png",
    back: "https://XXX.com/activity/smile/good.png",
  },
  {
    id: 4,
    info: "豪华电动车",
    front: "https://XXX.com/activity/smile/is_bless.png",
    back: "https://XXX.com/activity/smile/bless.png",
  },
  {
    id: 5,
    info: "1w购物券",
    front: "https://XXX.com/activity/smile/is_agency.png",
    back: "https://XXX.com/activity/smile/agency.png",
  },
];
const priceOptions = ref<priceInfo>({
  // 抽检间隔时间
  intervalTime: 200,
  // 中奖延迟显示时间
  delayTime: 500,
  // 中间显示奖品宽度
  priceWidth: 100,
  // 中间显示奖品高度
  priceHeight: 140,
  // 抽奖次数
  circleTime: 3,
  // 抽奖循环次数
  circleNum: 20,
  // 中奖Id
  priceId: 1,
});
</script>
代码示例(子组件):
<template>
  <div class="lottery-container" id="lottery-container"></div>
</template>

<script setup lang="ts">
import { ref, onMounted, defineProps } from "vue";
const drawOrder: any = ref([]); //抽奖书序
const currentIndex = ref<number | null>(null); // 当前选中的奖品
const count = ref(0); //抽奖次数
const isDrawing = ref(false); //是否在抽奖
const circle = ref(20);
const lotteryId = ref(1);
const priceObj = ref<priceInfo>({
  intervalTime: 500,
  delayTime: 200,
  priceWidth: 100,
  priceHeight: 140,
  circleTime: 3,
  circleNum: 20,
  priceId: 1,
});
interface listInfo {
  id?: number;
  front?: string;
  back?: string;
  info?: string;
}
interface priceInfo {
  // 抽检间隔时间
  intervalTime: number;
  // 中奖延迟显示时间
  delayTime: number;
  // 中间显示奖品宽度
  priceWidth: number;
  // 中间显示奖品高度
  priceHeight: number;
  // 抽奖次数
  circleTime: number;
  // 抽奖循环次数
  circleNum: number;
  // 中奖Id
  priceId: number;
}
const props = defineProps({
  priceParameter: {
    type: Object as () => priceInfo,
    default: () => ({
      intervalTime: 50,
      delayTime: 200,
      priceWidth: 100,
      priceHeight: 140,
      circleTime: 3,
      circleNum: 20,
      priceId: 1,
    }),
  },
  priceList: {
    type: Array<listInfo>,
    default: () => [],
  },
});
onMounted(() => {
  customOrder();
  createDiv();
  conductLottery();
});
// 创建所需要的抽奖的卡片个数
function createDiv() {
  let parentElement = document.getElementById("lottery-container") as any;

  parentElement.innerHTML = props.priceList
    .map((v, index) => {
      return `<div class = "lottery-con-item">
					<div class = "lottery-item-box front"></div>
					<div class = "lottery-item-box back"></div>
				</div>`;
    })
    .join("");
  let childElement = document.getElementsByClassName("lottery-con-item") as any;
  let allElement = document.getElementById("lottery-container")?.children as any;
  for (let i = 0; i < allElement.length; i++) {
    allElement[i].style.width = Number(props.priceParameter.priceWidth) / 37.5 + "rem";
    allElement[i].style.height = Number(props.priceParameter.priceHeight) / 37.5 + "rem";
  }
  for (let i = 0; i < drawOrder.value.length; i++) {
    childElement[drawOrder.value[i]].children[0].style.backgroundImage = `url(${props.priceList[i].front})`;
    childElement[drawOrder.value[i]].children[1].style.backgroundImage = `url(${props.priceList[i].back})`;
  }
  let childHeight = childElement[0].offsetHeight + 15;
  parentElement.style.height = `${(2 * childHeight) / 37.5}rem`;
}
// 自定义排序
function customOrder() {
  let listArr: any = [];
  props.priceList.forEach((val, index) => {
    listArr.push(index);
  });
  // 自定义排序函数
  listArr.sort((a: number, b: number) => {
    // 定义目标顺序数组
    const order = [9, 10, 11, 6, 7, 8, 3, 4, 5, 0, 1, 2];
    // 获取元素在目标顺序数组中的索引
    const indexA = order.indexOf(a);
    const indexB = order.indexOf(b);

    // 如果元素不在目标顺序数组中,放在后面
    if (indexA === -1) return 1;
    if (indexB === -1) return -1;
    // 根据目标顺序数组的索引进行排序
    return indexA - indexB;
  });
  drawOrder.value = listArr;
}
// 进行抽奖
const conductLottery = () => {
  var allChild = document.getElementsByClassName("lottery-con-item");
  const timer = setInterval(() => {
    currentIndex.value = drawOrder.value[count.value % drawOrder.value.length];
    count.value++;
    for (let i = 0; i < allChild.length; i++) {
      if (i == currentIndex.value) {
        allChild[currentIndex.value].classList.add("lottery-con-item-acitive");
      } else {
        allChild[i].classList.remove("lottery-con-item-acitive");
      }
    }
    if (count.value > circle.value && currentIndex.value === drawOrder.value[lotteryId.value - 1]) {
      // 抽奖结束
      clearInterval(timer);
      // 停顿一会显示中奖
      setTimeout(() => {
        count.value = 0;
        currentIndex.value = null;
        let turnBoxChildren = document.getElementsByClassName(`lottery-con-item-acitive`);
        turnBoxChildren[0].children[0].classList.add("lottery-animation1");
        turnBoxChildren[0].children[1].classList.add("lottery-animation2");
      }, props.priceParameter.intervalTime);
    }
  }, props.priceParameter.delayTime);
};
</script>

<style>
.lottery-container {
  display: flex;
  justify-content: space-evenly;
  flex-wrap: wrap-reverse;
  width: 100%;
  min-height: 400px;
  box-sizing: border-box;
  /* background-color: red; */
}

.lottery-con-item {
  position: relative;
  transform-style: preserve-3d;
}

.lottery-con-item-acitive {
  transform: scale(1.1);
}

.lottery-item-box {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-size: 100% 100%;
  backface-visibility: hidden;
}

.lottery-item-box.fornt {
  width: 100%;
  height: 100%;
  animation: backface 1s ease-in-out 0.5s normal forwards;
}

.lottery-item-box.back {
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
}

.lottery-animation1 {
  transform: rotateY(180deg);
  animation: lottery-backface 1s ease-in-out normal forwards;
}

.lottery-animation2 {
  animation: lottery-backface1 1s ease-in-out normal forwards;
}

@keyframes lottery-backface {
  100% {
    transform: rotateY(0);
  }
}

@keyframes lottery-backface1 {
  100% {
    transform: rotateY(180deg);
  }
}
</style>

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值