Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

uni-app初探之幸运轮盘

Alan.hsiang 2020-11-21 23:58:00 阅读数:15 评论数:0 点赞数:0 收藏数:0

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  lwidth: {
 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 width: (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  lwidth:300,
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

备注

八声甘州·对潇潇暮雨洒江天
【作者】柳永 【朝代】宋
对潇潇暮雨洒江天,一番洗清秋。
渐霜风凄紧,关河冷落,残照当楼。
是处红衰翠减,苒苒物华休。
惟有长江水,无语东流。
 
不忍登高临远,望故乡渺邈,归思难收。
叹年来踪迹,何事苦淹留?
想佳人、妆楼颙望,误几回、天际识归舟。
争知我,倚栏杆处,正恁凝愁。
版权声明
本文为[Alan.hsiang]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/hsiang/p/14017985.html