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 :style="canvasStyle" 4 5 </canvas 6 image :src="inLottery?'../../static/img/start_disabled.png':'../../static/img/start.png'"="start" @tap="playReward"></image 7 ="bottom1" 8 src="../../static/img/xiaolian.png" class="smile" 9 ="winner">{{winner}}view10 11 12 13 >
本例Lottery控件的JavaScript源码如下:
1 <script> 2 var ctx = null; 3 export default { 4 props: { 5 lwidth: { 6 type: Number, 7 default: 100,1)"> 8 9 },1)"> 10 lheight: { 11 12 default: 100 13 14 inLottery: { 15 type: Boolean,1)"> 16 default: false 17 18 19 parts: { 20 type: Array,1)"> 21 function() { 22 return [{ 23 id: 1 24 name: '香蕉' 25 img: '' 26 color: "#AABBCC" 27 },1)"> 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 },1)"> 56 data() { 57 58 winner:"请抽奖" 59 }; 60 61 computed: { 62 canvasStyle() { 63 64 width: (this.lwidth) + "px" 65 height: (this.lheight) + "px" 66 }; 67 68 69 70 methods: { 71 initLottery:(ctx,angleTo){ 72 73 const len = this.parts.length; //数组长度 74 if (len == 0) { 75 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,this.lwidth,1)">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,radius + 3,Math.PI * 2 97 ctx.stroke(); 98 画装饰点 99 for (var i = 0; i < 24; i++100 装饰点 圆心 坐标计算 101 ctx.beginPath(); 102 var r = radius + 6103 var xr = r * Math.cos(beginAngle); 104 var yr = r * Math.sin(beginAngle); 105 106 ctx.fillStyle = "#FFFFFF"107 ctx.arc(xr,yr,4,2 * Math.PI); 108 ctx.fill(); 109 110 beginAngle += (2 * Math.PI / 360) * (360 / 24111 112 113 ctx.setLineWidth(0.1114 beginAngle = 2 * Math.PI / 360 * (-90115 绘制填充形状 116 var i = 0; i < len; i++117 console.log("color = "+this.parts[i].color); 118 console.log("beginAngle="+beginAngle); 119 ctx.save(); 120 121 ctx.moveTo(0,0122 ctx.setStrokeStyle(.parts[i].color); 123 ctx.setFillStyle(124 125 ctx.arc(0,radius,beginAngle,beginAngle + Angle,1)">false126 ctx.stroke(); 127 128 129 beginAngle = beginAngle + Angle; 130 131 beginAngle = 0; Angle / 2; 132 133 var ry = -(center_x / 2) - 25134 绘制旋转文字 135 ctx.rotate((beginAngle + (Angle * 0.5))); 顺时针旋转 136 ctx.setTextAlign("center"137 ctx.setFillStyle("#AA00CC"138 ctx.fillText(this.parts[i].name,ry); 139 140 ctx.restore(); 141 beginAngle = beginAngle +142 143 144 ctx.beginPath(); 145 ctx.arc(0,8,1)">146 ctx.setFillStyle("#FFFFFF"147 ctx.fill(); 148 ctx.draw(); 149 150 playReward:(){ 151 var len = 152 153 154 155 var angle = 360/len ; 156 var num =Math.floor(Math.random()*len); 157 num= num%len; 158 angle = num * angle + angle / 2159 angle = angle || 0160 angle = 360-angle; 161 angle += 1440162 console.log("angle = "+angle +",num = "+num); 163 var that = 164 var count = 1165 基值(减速) 166 var baseStep = 50167 起始滚动速度 168 var baseSpeed =1169 var timer = setInterval(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.1177 if (angle - count < 0.5178 count = angle; 179 180 },25181 182 183 组件内么有onReady和onLoad等生命周期 184 mounted: 185 this.ctx = uni.createCanvasContext("canvas"186 this.initLottery(this.ctx,1)">187 } 188 } 189 </script>
本例Lottery控件的CSS源码如下:
1 <style> 2 .content1 { 3 width: 100%; 4 height: 5 text-align: center; 6 display: flex; 7 flex-direction: column; 8 align-items: 9 position: relative; 10 } 11 12 #canvas { 13 left: 2rpx; 14 top:15 } 16 17 #start { 18 absolute; 19 110rpx; 20 150rpx; 21 cursor: pointer; 22 240rpx; 23 } 24 .bottom1{ 25 26 row; 27 justify-content:28 29 } 30 .winner{ 31 70rpx; 32 vertical-align: middle; 33 padding-top: 10rpx; 34 color: #FFFFFF; 35 } 36 .smile{ 37 38 39 } 40 </style>
本例index页面调用组件,代码如下:
="content"="top" 4 lottery ="lottery" :lwidth="lwidth" :lheight="lheight"lottery="bottom">Provider By Alan.hsiang 6 7 8 9 script10 import lottery from "@/components/Lottery/Lottery.vue" 11 export default12 components:{ 13 lottery 14 15 16 return17 title: 'Hello18 lwidth:30019 lheight:300 20 21 22 onLoad() { 23 24 25 26 27 28 29 30 31 style32 .content { 33 display: flex; 34 flex-direction column35 /* align-items: center; */ 36 justify-content: center; 37 background-image url(../../static/img/bg.jpg)38 background-position center39 background-repeat no-repeat40 background-size cover41 height 100%42 width43 } 44 .top45 35%46 47 48 .lottery49 position: absolute; 50 top: 200rpx; 51 bottom: 200rpx; 52 margin 2rpx53 54 700rpx55 56 .bottom57 position absolute58 bottom 10rpx59 color #FFFFFF60 61 text-align62 63 >
另外为了页面显示完整,需要在App.vue中定义页面显示100%,如下所示:
2 3 onLaunch: function 4 console.log(App Launch) 5 6 onShow: 7 App Show 8 9 onHide: App Hide14 15 16 每个页面公共css uni-page-body,#app {width100%;height page21 22 >
备注
八声甘州·对潇潇暮雨洒江天
【作者】柳永 【朝代】宋
【作者】柳永 【朝代】宋
对潇潇暮雨洒江天,一番洗清秋。
渐霜风凄紧,关河冷落,残照当楼。
是处红衰翠减,苒苒物华休。
惟有长江水,无语东流。
渐霜风凄紧,关河冷落,残照当楼。
是处红衰翠减,苒苒物华休。
惟有长江水,无语东流。
不忍登高临远,望故乡渺邈,归思难收。
叹年来踪迹,何事苦淹留?
想佳人、妆楼颙望,误几回、天际识归舟。
争知我,倚栏杆处,正恁凝愁。
叹年来踪迹,何事苦淹留?
想佳人、妆楼颙望,误几回、天际识归舟。
争知我,倚栏杆处,正恁凝愁。