经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » HTML/CSS » CSS3 » 查看文章
Vue+CSS3实现转盘抽奖的示例代码_CSS教程_CSS
来源:jb51  时间:2019/6/26 11:28:34  对本文有异议

最近有个转盘抽奖的需求,搜了一下现有的轮子,有的是用jQuery的动画函数实现的,有的是用canvas绘图然后再用高频率的setTimeout调用旋转方法,前者太老了没法简单移植到vue项目,后者感觉性能表现可能不会太好。也有一些用CSS动画的方案,设计了加速-匀速-减速三个动画,再计算偏转角度让三个动画尽可能无缝衔接,但我感觉绕了大远路,应该有更简单轻量的实现方案。个人更倾向于用transition来实现,不过网上的例子感觉还不够好,有的倾斜文字都没有对齐,最后还是自己手写了一个。

无需jQuery,不用js脚本实现动画细节,动画效果完全连续无需衔接,支持动态设置2个以上任意数量的奖项。

核心思路是用transition以及rotate实现旋转动画,使用transition-origin和rotate绘制出定位较为精确的轮盘奖项。

代码及实例展示

  1. <script src="//unpkg.com/vue/dist/vue.js"></script>
  2. <span id="app">
  3. <span>Prize number: {{ prizeNumber }}</span>
  4. <button type="button" @click="!rolling && prizeNumber < 8 && (prizeNumber++)" :disabled="rolling || prizeNumber === 8">Add</button>
  5. <button type="button" @click="!rolling && prizeNumber > 2 && (prizeNumber--)" :disabled="rolling || prizeNumber === 2">Remove</button>
  6. <div class="wheel-wrapper">
  7. <div
  8. class="wheel-pointer"
  9. @click="onClickRotate"
  10. >
  11. Start
  12. </div>
  13. <div
  14. class="wheel-bg"
  15. :class="{freeze: freeze}"
  16. :style="`transform: rotate(${wheelDeg}deg)`"
  17. >
  18. <div class="prize-list">
  19. <div
  20. class="prize-item-wrapper"
  21. v-for="(item,index) in prizeList"
  22. :key="index"
  23. >
  24. <div
  25. class="prize-item"
  26. :style="`transform: rotate(${(360/ prizeList.length) * index}deg)`"
  27. >
  28. <div class="prize-name">
  29. {{ item.name }}
  30. </div>
  31. <div class="prize-icon">
  32. <img :src="item.icon">
  33. </div>
  34. </div>
  35. </div>
  36. </div>
  37. </div>
  38. </div>
  39. </div>
  1. html {
  2. background: #DD7C7D;
  3. }
  4.  
  5. .wheel-wrapper {
  6. width: 300px;
  7. height: 300px;
  8. position: absolute;
  9. top: 50%;
  10. left: 50%;
  11. transform: translate(-50%, -50%);
  12. }
  13.  
  14. .wheel-pointer {
  15. width: 60px;
  16. height: 60px;
  17. border-radius: 1000px;
  18. background: yellow;
  19. position: absolute;
  20. left: 50%;
  21. top: 50%;
  22. transform: translate(-50%, -50%);
  23. text-align: center;
  24. line-height: 60px;
  25. z-index: 10;
  26. }
  27. .wheel-bg {
  28. width: 100%;
  29. height: 100%;
  30. border-radius: 1000px;
  31. overflow: hidden;
  32. transition: transform 4s ease-in-out;
  33. background: #7EEF97;
  34. &.freeze {
  35. transition: none;
  36. background: red;
  37. }
  38. }
  39.  
  40. .prize-list {
  41. width: 100%;
  42. height: 100%;
  43. position: relative;
  44. text-align: center;
  45. }
  46.  
  47. .prize-item-wrapper {
  48. position: absolute;
  49. top: 0;
  50. left: 50%;
  51. transform: translateX(-50%);
  52. width: 150px;
  53. height: 150px;
  54. }
  55.  
  56. .prize-item {
  57. width: 100%;
  58. height: 100%;
  59. transform-origin: bottom;
  60.  
  61. .prize-name {
  62. padding: 16px 0;
  63. }
  64.  
  65. .prize-icon {}
  66. }
  67.  
  1. var Main = {
  2. data() {
  3. return {
  4. freeze: false,
  5. rolling: false,
  6. wheelDeg: 0,
  7. prizeNumber: 8,
  8. prizeListOrigin: [
  9. {
  10. icon: "https://picsum.photos/40?random=1",
  11. name: "$10000"
  12. },
  13. {
  14. icon: "https://picsum.photos/40?random=6",
  15. name: "Thank you!"
  16. },
  17. {
  18. icon: "https://picsum.photos/40?random=2",
  19. name: "$500"
  20. },
  21. {
  22. icon: "https://picsum.photos/40?random=3",
  23. name: "$100"
  24. },
  25. {
  26. icon: "https://picsum.photos/40?random=6",
  27. name: "Thank you!"
  28. },
  29. {
  30. icon: "https://picsum.photos/40?random=4",
  31. name: "$50"
  32. },
  33. {
  34. icon: "https://picsum.photos/40?random=5",
  35. name: "$10"
  36. },
  37. {
  38. icon: "https://picsum.photos/40?random=6",
  39. name: "Thank you!"
  40. }
  41. ]
  42. };
  43. },
  44. computed: {
  45. prizeList () {
  46. return this.prizeListOrigin.slice(0, this.prizeNumber)
  47. }
  48. },
  49. methods: {
  50. onClickRotate() {
  51. if (this.rolling) {
  52. return;
  53. }
  54. this.rolling = true;
  55. const { wheelDeg, prizeList } = this;
  56. const random = Math.floor(Math.random() * (prizeList.length ));
  57. console.log(random);
  58. this.wheelDeg =
  59. wheelDeg -
  60. wheelDeg % 360 +
  61. 6 * 360 +
  62. (360 - 360 / prizeList.length * random);
  63. setTimeout(() => {
  64. this.rolling = false;
  65. alert("Result:" + prizeList[random].name);
  66. }, 4500);
  67. }
  68. },
  69. watch: {
  70. prizeNumber () {
  71. this.freeze = true
  72. this.wheelDeg = 0
  73. setTimeout(() => {
  74. this.freeze = false
  75. }, 0)
  76. }
  77. }
  78. };
  79. var App = Vue.extend(Main);
  80. new App().$mount("#app");

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号