• uni-app初探之幸运轮盘


    uni-app以其“一次开发,多端覆盖”的理念深得大家青睐,并且生态环境丰富,本文以一个幸运轮盘小例子,简述canvas的相关操作,仅供学习分享使用,如有不足之处,还请指正。

    什么是canvas?

    canvas又称画布,为uni-app提供自定义绘制的区域,通常用于图表或者图片的处理。在uni-app开发中,如果要在canvas中进行绘制,需要通过CanvasContext完成。

    canvas相关知识点

    canvas属性说明【canvas-id 在同一页面中不可重复】

    CanvasContext的定义通过uni-app提供的API【uni.createCanvasContext(canvasId, this)】完成,如下所示:

     在canvas上进行绘制,主要通过CanvasContex对象进行。关于CanvasContext的使用方法,可参考官方文档

    示例效果图

    在Chrome浏览器上,如下所示:

    在Android手机上,如下图所示:

    核心源代码

    在uni-app开发中,一个功能可以封装成一个控件,便于维护和调用。

    本例Lottery控件的template源码如下:

     1 <template>
     2     <view class="content1">
     3         <canvas type="2D" canvas-id="canvas" id="canvas" :style="canvasStyle">
     4 
     5         </canvas>
     6         <image :src="inLottery?'../../static/img/start_disabled.png':'../../static/img/start.png'" id="start" @tap="playReward"></image>
     7         <view class="bottom1">
     8             <image src="../../static/img/xiaolian.png" class="smile"></image>
     9             <view class="winner">{{winner}}</view>
    10         </view>
    11         
    12     </view>
    13 </template>
    View Code

    本例Lottery控件的JavaScript源码如下:

      1 <script>
      2     var ctx = null;
      3     export default {
      4         props: {
      5             l {
      6                 type: Number,
      7                 default: 100,
      8 
      9             },
     10             lheight: {
     11                 type: Number,
     12                 default: 100
     13             },
     14             inLottery: {
     15                 type: Boolean,
     16                 default: false
     17             },
     18             
     19             parts: {
     20                 type: Array,
     21                 default: function() {
     22                     return [{
     23                             id: 1,
     24                             name: '香蕉',
     25                             img: '',
     26                             color: "#AABBCC"
     27                         },
     28                         {
     29                             id: 2,
     30                             name: '苹果',
     31                             img: '',
     32                             color: "#FFCCFF"
     33                         },
     34                         {
     35                             id: 3,
     36                             name: '梨子',
     37                             img: '',
     38                             color: "#FFFFFF"
     39                         },
     40                         {
     41                             id: 4,
     42                             name: '青瓜',
     43                             img: '',
     44                             color: "#FFCCFF"
     45                         },
     46                         {
     47                             id: 5,
     48                             name: '番茄',
     49                             img: '',
     50                             color: "#FFFFFF"
     51                         }
     52                     ]
     53                 }
     54             }
     55         },
     56         data() {
     57             return {
     58                 winner:"请抽奖"
     59             };
     60         },
     61         computed: {
     62             canvasStyle() {
     63                 return {
     64                      (this.lwidth) + "px",
     65                     height: (this.lheight) + "px"
     66                 };
     67             },
     68             
     69         },
     70         methods: {
     71             initLottery:function(ctx,angleTo){
     72                 
     73                 const len = this.parts.length; //数组长度
     74                 if (len == 0) {
     75                     return;
     76                 }
     77                 var center_x = this.lwidth / 2;
     78                 var center_y = this.lheight / 2;
     79                 var total = 2 * Math.PI; //总度数为2π
     80                 var Angle = total / len; //平均值
     81                 var radius = center_x - 14;
     82                 center_x = center_x;
     83                 center_y = center_y;
     84                 angleTo = angleTo || 0;
     85                 ctx.clearRect(0,0, this.lwidth, this.lheight);
     86                 ctx.translate(center_x, center_y);
     87                 ctx.setFontSize(14);
     88                 ctx.setLineWidth(14);
     89                 ctx.save();
     90                 //旋转画布
     91                 ctx.rotate(angleTo * Math.PI / 180);
     92                 //
     93                 var beginAngle = 2 * Math.PI / 360 * (-90);
     94                 //先画外圆
     95                 ctx.setStrokeStyle("#ffaa00");
     96                 ctx.arc(0, 0, radius + 3, 0, Math.PI * 2);
     97                 ctx.stroke();
     98                 //画装饰点
     99                 for (var i = 0; i < 24; i++) {
    100                     // 装饰点 圆心 坐标计算
    101                     ctx.beginPath();
    102                     var r = radius + 6;
    103                     var xr = r * Math.cos(beginAngle);
    104                     var yr = r * Math.sin(beginAngle);
    105                 
    106                     ctx.fillStyle = "#FFFFFF";
    107                     ctx.arc(xr, yr, 4, 0, 2 * Math.PI);
    108                     ctx.fill();
    109                 
    110                     beginAngle += (2 * Math.PI / 360) * (360 / 24);
    111                 
    112                 }
    113                 ctx.setLineWidth(0.1);
    114                 beginAngle = 2 * Math.PI / 360 * (-90);
    115                 //绘制填充形状
    116                 for (var i = 0; i < len; i++) {
    117                     // console.log("color = "+this.parts[i].color);
    118                     // console.log("beginAngle="+beginAngle);
    119                     ctx.save();
    120                     ctx.beginPath();
    121                     ctx.moveTo(0, 0);
    122                     ctx.setStrokeStyle(this.parts[i].color);
    123                     ctx.setFillStyle(this.parts[i].color);
    124                 
    125                     ctx.arc(0, 0, radius, beginAngle, beginAngle + Angle, false);
    126                     //ctx.stroke();
    127                     ctx.fill();
    128                     ctx.save();
    129                     beginAngle = beginAngle + Angle;
    130                 }
    131                 beginAngle = 0; //Angle / 2;
    132                 for (var i = 0; i < len; i++) {
    133                     var ry = -(center_x / 2) - 25;
    134                     //绘制旋转文字
    135                     ctx.rotate((beginAngle + (Angle * 0.5))); //顺时针旋转
    136                     ctx.setTextAlign("center");
    137                     ctx.setFillStyle("#AA00CC");
    138                     ctx.fillText(this.parts[i].name, 0, ry);
    139                 
    140                     ctx.restore();
    141                     beginAngle = beginAngle + Angle;
    142                 }
    143                 ctx.save();
    144                 ctx.beginPath();
    145                 ctx.arc(0, 0, 8, 0, Math.PI * 2);
    146                 ctx.setFillStyle("#FFFFFF");
    147                 ctx.fill();
    148                 ctx.draw();
    149             },
    150             playReward:function(){
    151                 var len = this.parts.length; //数组长度
    152                 if (len == 0) {
    153                     return;
    154                 }
    155                 var angle = 360/len ; 
    156                 var num =Math.floor(Math.random()*len);
    157                 //num= num%len;
    158                 angle = num * angle + angle / 2;
    159                 angle = angle || 0;
    160                 angle = 360-angle;
    161                 angle += 1440;
    162                 console.log("angle = "+angle +",num = "+num);
    163                 var that = this;
    164                 var count = 1;
    165                 // 基值(减速)
    166                 var baseStep = 50;
    167                 // 起始滚动速度
    168                 var baseSpeed =1;
    169                 var timer = setInterval(function(){
    170                     console.log("count = "+count);
    171                     that.initLottery(that.ctx,count) ;
    172                     if (count == angle) {
    173                         clearInterval(timer);
    174                         that.winner = "当前奖品为:"+that.parts[num].name;
    175                     }
    176                     count =  count + baseStep * (((angle - count) / angle) > baseSpeed ? baseSpeed : ((angle - count) / angle))+0.1;
    177                     if (angle - count < 0.5) {
    178                         count = angle;
    179                     }
    180                 },25);
    181             }
    182         },
    183         // 组件内么有onReady和onLoad等生命周期
    184         mounted: function() {
    185             this.ctx = uni.createCanvasContext("canvas");
    186             this.initLottery(this.ctx,0);
    187         }
    188     }
    189 </script>
    View Code

     本例Lottery控件的CSS源码如下:

     1 <style>
     2     .content1 {
     3         width: 100%;
     4         height: 100%;
     5         text-align: center;
     6         display: flex;
     7         flex-direction: column;
     8         align-items: center;
     9         position: relative;
    10     }
    11 
    12     #canvas {
    13         left: 2rpx;
    14         top: 2rpx;
    15     }
    16 
    17     #start {
    18         position: absolute;
    19         width: 110rpx;
    20         height: 150rpx;
    21         cursor: pointer;
    22         top: 240rpx;
    23     }
    24     .bottom1{
    25         display: flex;
    26         flex-direction: row;
    27         justify-content: center;
    28         justify-content: center;
    29     }
    30     .winner{
    31         height: 70rpx;
    32         vertical-align: middle;
    33         padding-top: 10rpx;
    34         color: #FFFFFF;
    35     }
    36     .smile{
    37         width: 70rpx;
    38         height: 70rpx;
    39     }
    40 </style>
    View Code

     本例index页面调用组件,代码如下:

     1 <template>
     2     <view class="content">
     3         <view class="top"></view>
     4         <lottery  class="lottery" :lwidth="lwidth" :lheight="lheight"></lottery>
     5         <view class="bottom">Provider By Alan.hsiang</view>
     6     </view>
     7 </template>
     8 
     9 <script>
    10     import lottery from "@/components/Lottery/Lottery.vue"
    11     export default {
    12         components:{
    13             lottery
    14         },
    15         data() {
    16             return {
    17                 title: 'Hello',
    18                 l300,
    19                 lheight:300
    20             }
    21         },
    22         onLoad() {
    23 
    24         },
    25         methods: {
    26 
    27         }
    28     }
    29 </script>
    30 
    31 <style>
    32     .content {
    33         display: flex;
    34         flex-direction: column;
    35         /* align-items: center; */
    36         /* justify-content: center; */
    37         background-image: url(../../static/img/bg.jpg);
    38         background-position: center;
    39         background-repeat: no-repeat;
    40         background-size: cover;
    41         height: 100%;
    42         width: 100%;
    43     }
    44     .top{
    45         height: 35%;
    46         width: 100%;
    47     }
    48     .lottery{
    49         /* position: absolute; */
    50         /* top: 200rpx; */
    51         /* bottom: 200rpx; */
    52         margin: 2rpx;
    53         width: 100%;
    54         height: 700rpx;
    55     }
    56     .bottom{
    57         position: absolute;
    58         bottom: 10rpx;
    59         color: #FFFFFF;
    60         width: 100%;
    61         text-align: center;
    62     }
    63 </style>
    View Code

    另外为了页面显示完整,需要在App.vue中定义页面显示100%,如下所示:

     1 <script>
     2     export default {
     3         onLaunch: function() {
     4             console.log('App Launch')
     5         },
     6         onShow: function() {
     7             console.log('App Show')
     8         },
     9         onHide: function() {
    10             console.log('App Hide')
    11         }
    12     }
    13 </script>
    14 
    15 <style>
    16     /*每个页面公共css */
    17     uni-page-body,#app {width:100%;height: 100%;}
    18     page{
    19         width: 100%;
    20         height: 100%;
    21     }
    22 </style>
    View Code

    备注

    八声甘州·对潇潇暮雨洒江天
    【作者】柳永 【朝代】宋
    对潇潇暮雨洒江天,一番洗清秋。
    渐霜风凄紧,关河冷落,残照当楼。
    是处红衰翠减,苒苒物华休。
    惟有长江水,无语东流。
     
    不忍登高临远,望故乡渺邈,归思难收。
    叹年来踪迹,何事苦淹留?
    想佳人、妆楼颙望,误几回、天际识归舟。
    争知我,倚栏杆处,正恁凝愁。
  • 相关阅读:
    小程序面试题及答案
    Git常用指令
    《剑指offer》面试题23 从上往下打印二叉树 Java版
    《剑指offer》面试题22 栈的压入、弹出序列 Java版
    《剑指offer》面试题21 包含min函数的栈 Java版
    《剑指offer》面试题20 顺时针打印矩阵 Java版
    《剑指offer》面试题19 二叉树的镜像 Java版
    《剑指offer》面试题18 树的子结构 Java版
    《剑指offer》面试题17 合并两个排序的链表 Java版
    《剑指offer》面试题16 反转链表 Java版
  • 原文地址:https://www.cnblogs.com/hsiang/p/14017985.html
Copyright © 2020-2023  润新知