uni-app以其“一次開發(fā),多端覆蓋”的理念深得大家青睞,并且生態(tài)環(huán)境豐富,本文以一個幸運輪盤小例子,簡述canvas的相關(guān)操作,僅供學(xué)習(xí)分享使用,如有不足之處,還請指正。 什么是canvas?canvas又稱畫布,為uni-app提供自定義繪制的區(qū)域,通常用于圖表或者圖片的處理。在uni-app開發(fā)中,如果要在canvas中進行繪制,需要通過CanvasContext完成。 canvas相關(guān)知識點canvas屬性說明【canvas-id 在同一頁面中不可重復(fù)】 CanvasContext的定義通過uni-app提供的API【uni.createCanvasContext(canvasId, this)】完成,如下所示: 在canvas上進行繪制,主要通過CanvasContex對象進行。關(guān)于CanvasContext的使用方法,可參考官方文檔。 示例效果圖在Chrome瀏覽器上,如下所示:
在Android手機上,如下圖所示:
核心源代碼在uni-app開發(fā)中,一個功能可以封裝成一個控件,便于維護和調(diào)用。 本例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> 本例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; //數(shù)組長度 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; //總度數(shù)為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 //旋轉(zhuǎn)畫布 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 // 裝飾點 圓心 坐標(biāo)計算 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 //繪制旋轉(zhuǎn)文字 135 ctx.rotate((beginAngle + (Angle * 0.5))); //順時針旋轉(zhuǎn) 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; //數(shù)組長度 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 = "當(dāng)前獎品為:"+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 // 組件內(nèi)么有onReady和onLoad等生命周期 184 mounted: function() { 185 this.ctx = uni.createCanvasContext("canvas"); 186 this.initLottery(this.ctx,0); 187 } 188 } 189 </script> 本例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> 本例index頁面調(diào)用組件,代碼如下: ![]() 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> 另外為了頁面顯示完整,需要在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> 備注八聲甘州·對瀟瀟暮雨灑江天
【作者】柳永 【朝代】宋 對瀟瀟暮雨灑江天,一番洗清秋。
漸霜風(fēng)凄緊,關(guān)河冷落,殘照當(dāng)樓。 是處紅衰翠減,苒苒物華休。 惟有長江水,無語東流。 不忍登高臨遠,望故鄉(xiāng)渺邈,歸思難收。
嘆年來蹤跡,何事苦淹留? 想佳人、妝樓颙望,誤幾回、天際識歸舟。 爭知我,倚欄桿處,正恁凝愁。 |
|