vue实现简单转盘抽奖功能

yizhihongxing

下面我来详细讲解如何用vue实现简单转盘抽奖功能的完整攻略:

1. 搭建项目

首先我们需要使用vue-cli来搭建一个vue项目,输入以下命令来创建一个新的vue项目:

vue create lottery

安装依赖,进入项目目录并启动本地服务器:

cd lottery
npm install
npm run serve

2. 编写转盘组件

接下来我们需要编写转盘组件,组件分为圆盘和奖品两个子组件,在子组件中分别绘制相应的内容:

<!-- circle component -->
<template>
  <div class="circle" :style="circleStyle">
    <div class="pointer" :style="pointerStyle"></div>
    <slot></slot>
  </div>
</template>

<script>
export default {
  name: "Circle",
  props: {
    size: {
      type: Number,
      default: 300
    },
    border: {
      type: String,
      default: "10px solid #ccc"
    },
    color: {
      type: String,
      default: "#f60"
    }
  },
  computed: {
    circleStyle() {
      return {
        width: `${this.size}px`,
        height: `${this.size}px`,
        border: this.border,
        borderRadius: "50%",
        position: "relative"
      };
    },
    pointerStyle() {
      return {
        width: "0",
        height: "0",
        border: "15px solid transparent",
        borderTop: `15px solid ${this.color}`,
        position: "absolute",
        left: "50%",
        bottom: "-3px",
        transform: "translateX(-50%) rotate(-22.5deg)"
      };
    }
  }
};
</script>

<style scoped>
.circle {
  display: flex;
  justify-content: center;
  align-items: center;
  background-color: #fff;
}

.pointer {
  z-index: 1;
}
</style>
<!-- prize component -->
<template>
  <div class="prize" :style="prizeStyle">
    <div class="item" v-for="(item, index) in prizeList" :style="itemStyle(index)" :key="index">
      {{ item }}
    </div>
  </div>
</template>

<script>
export default {
  name: "Prize",
  props: {
    prizeList: {
      type: Array,
      default: () => []
    },
    color: {
      type: String,
      default: "#f60"
    }
  },
  computed: {
    prizeLength() {
      return this.prizeList.length;
    },
    prizeStyle() {
      return {
        width: "100%",
        height: "100%",
        position: "relative"
      };
    }
  },
  methods: {
    itemStyle(index) {
      const deg = (360 / this.prizeLength) * index;
      return {
        width: "100%",
        height: `${100 / this.prizeLength}%`,
        lineHeight: `${100 / this.prizeLength}%`,
        textAlign: "center",
        transformOrigin: "50% 100%",
        transform: `rotate(${deg}deg) skewY(-22.5deg)`,
        boxSizing: "border-box",
        position: "absolute",
        left: 0,
        top: 0,
        borderTop: `5px solid ${this.color}`
      };
    }
  }
};
</script>

<style scoped>
.prize {
  display: -webkit-box;
  display: flex;
  -webkit-box-pack: center;
          justify-content: center;
  -webkit-box-align: center;
          align-items: center;
}

.item {
  font-size: 18px;
  box-sizing: border-box;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  border-bottom: 5px solid #fff;
  transition: transform 3s cubic-bezier(0.27, 0.47, 0.17, 0.84);
}

.item.active {
  transform: rotate(360deg) skewY(-22.5deg);
  font-weight: bold;
}
</style>

我们的转盘组件就编写完成了,可以通过在父组件中使用<circle><prize>标签来调用两个子组件。

3. 实现抽奖功能

在父组件中,我们需要先定义一个奖品列表,然后将奖品列表传递给<prize>组件,再定义一个变量来表示当前选中的奖品下标,然后在页面中绑定一个“抽奖”按钮,当点击“抽奖”按钮时,随机生成一个奖品下标,再将这个下标传递给<circle>组件,通过修改<prize>组件中的样式来实现转盘停在指定的奖品上。

<template>
  <div>
    <circle :size="circleSize" :color="color" ref="circle">
      <prize :prizeList="prizeList" :color="color" ref="prize"></prize>
    </circle>
    <button @click="handleClick">抽 奖</button>
  </div>
</template>

<script>
import Circle from "./components/Circle.vue";
import Prize from "./components/Prize.vue";

export default {
  name: "Lottery",
  components: {
    Circle,
    Prize
  },
  data() {
    return {
      circleSize: 300,
      color: "#f60",
      prizeList: ["奖品 1", "奖品 2", "奖品 3", "奖品 4", "奖品 5"],
      activeIndex: -1
    };
  },
  methods: {
    handleClick() {
      // 生成一个随机的奖品下标
      const index = Math.floor(Math.random() * this.prizeList.length);
      this.activeIndex = index;
      this.$refs.prize.$el.querySelectorAll(".item").forEach((item, i) => {
        if (i === index) {
          item.classList.add("active");
        } else {
          item.classList.remove("active");
        }
      });
      this.$refs.circle.$el.querySelector(".pointer").style.transform = `translateX(-50%) rotate(${360 / this.prizeList.length * index + 22.5}deg)`;
    }
  }
};
</script>

<style>
button {
  margin-top: 20px;
  padding: 10px 20px;
  font-size: 16px;
  background-color: #f60;
  color: #fff;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}
</style>

通过上述代码,我们实现了一个简单的转盘抽奖功能。当点击“抽奖”按钮时,转盘会随机停留在一个奖品上,同时页面中也会显示出选中的奖品。我们也可以在<circle>组件中加入多个旋转效果的动画,以增强页面的视觉效果。

示例说明

示例1

这里提供了一个基于vue开发的简单转盘抽奖功能的在线演示,你可以访问该网页体验转盘抽奖的功能。

示例2

如果你不希望使用默认的样式或者奖品列表,可以自行修改代码中的相关变量,例如,我们可以将抽奖按钮修改为一个图标,代码如下:

<button @click="handleClick">
  <svg width="20" height="20" viewBox="0 0 20 20">
    <path fill="#fff" d="M15.62 7.38a6 6 0 1 1-8.48 0A.999.999 0 1 1 7.38 4.38a8 8 0 1 0 5.66 5.66c.12-.12.21-.26.31-.39l2.37 2.37a1 1 0 0 1-1.41 1.41L14.21 9C14.37 8.88 14.49 8.71 14.62 8.54a.996.996 0 0 1 1.41 0c.37.36.37.92 0 1.28l-1.41 1.41a.998.998 0 1 1-1.41-1.41l.35-.35-2.12-2.12a2.986 2.986 0 0 1-.05 4.23 2.986 2.986 0 0 1-4.23 0 3 3 0 0 1 0-4.24c.02-.02.05-.04.07-.06L3.3 5.5c-.35.68-.54 1.44-.54 2.23a6 6 0 0 0 10.86 3.38 6.03 6.03 0 0 0-1.5-4z"></path>
  </svg>
  &nbsp;开始抽奖
</button>

你也可以自行添加其他的样式和行为来满足自己的需求。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue实现简单转盘抽奖功能 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • Vue中的过滤器(filter)详解

    Vue中的过滤器(Filter)详解 什么是过滤器(Filter)? 过滤器(Filter)是Vue.js提供的一种可复用功能的方法,用于对数据的格式化处理。 在Vue.js的模板语法中, 可以用管道符(|)来应用过滤器。管道符前面是要过滤的数据项,管道符后面是过滤器的名称。 例如: <div>{{message | capitalize}}&l…

    Vue 2023年5月27日
    00
  • Vue.js中this如何取到data和method里的属性详解

    对于Vue.js项目中,我们经常需要在代码中引用Vue实例中的属性或方法。在此过程中,我们需要清楚地了解this关键字的作用和作用域。本文将详细讲解如何在Vue.js中获取data和method中的属性。 this关键字的作用和作用域 在Vue.js中,this关键字是指Vue实例的上下文。Vue实例中的属性和方法都可以通过this在相应的位置中访问。但是,…

    Vue 2023年5月28日
    00
  • React中Portals与错误边界处理实现

    当React应用程序遇到问题或出现错误时,错误边界(error boundaries)特别有用。错误边界是React组件,它会在渲染期间捕获并打印任何在树的子组件中抛出的JavaScript错误,并且,相当于错误被“停留”在边界内,防止应用程序崩溃。下面就让我们来详细讲解React中的错误边界处理以及Portals的使用。 错误边界(Error Bounda…

    Vue 2023年5月28日
    00
  • Vue2实现组件props双向绑定

    下面我将详细讲解如何在Vue2中实现组件props的双向绑定。 1. Vue2中props的单向绑定 Vue2中的props是单向绑定的,即父组件可以向子组件传递数据,但是子组件不能直接修改父组件传递的props。在子组件中默认情况下只能读取父组件传递的props值,如果想要修改这些值,需要通过事件的形式在子组件中触发父组件传递的方法来实现。 下面是一个示例…

    Vue 2023年5月28日
    00
  • 浅谈vue+webpack项目调试方法步骤

    下面我会详细讲解“浅谈vue+webpack项目调试方法步骤”的完整攻略,包含两个示例说明: 1. 前言 在开发 Vue.js 项目的过程中,使用 webpack 打包工具的情况非常普遍。然而,当我们要进行项目调试时,可能会遇到很多问题,例如如何设置断点,如何在浏览器中查看 console 输出等。本文旨在分享一些使用 Vue.js 与 webpack 进行…

    Vue 2023年5月27日
    00
  • 关于vue属性使用和不使用冒号的区别说明

    关于Vue属性的使用和不使用冒号的区别,主要涉及Vue的模板语法和组件属性传递。在Vue中,通常使用“v-bind”指令和冒号来将数据绑定到HTML元素的属性上。而不使用冒号,则意味着传递一个具体字符串值或变量名。 Vue属性使用冒号的区别: 数据绑定 在Vue中使用冒号可以实现数据绑定,让模板中的HTML元素及其对应的属性随数据变化而动态更新。这个特性可以…

    Vue 2023年5月27日
    00
  • 使用Vue.$set()或者Object.assign()修改对象新增响应式属性的方法

    使用Vue.js时,我们通常会遇到在组件渲染时需要动态新增响应式属性的情况。Vue提供了两种方式使对象属性(非响应式的)能被监听到,即Vue.$set()和Object.assign()。 使用Vue.$set()方法 Vue.$set()方法是Vue.js提供的Vue实例方法,用于响应式地向已有对象添加新的属性,或修改已有属性的值。这个方法的第一个参数是目…

    Vue 2023年5月28日
    00
  • 解决vue打包后vendor.js文件过大问题

    解决vue打包后vendor.js文件过大问题是一个非常重要的优化工作。通常采用分包策略和动态导入的方式,能有效地将vendor.js体积缩小到最小值。 以下是解决vue打包后vendor.js文件过大问题的完整攻略: 1. 分包策略 将项目的公共库和第三方库分别打包,使项目的vendor.js文件从一个大文件拆成多个小的vendor文件,每个文件都对应一部…

    Vue 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部