作者: 陳淇
前言:
"我隻是想中個彩票一輩子不用不上班而已, 很過分嗎 又不是想要天上的星星"。
前段時間經常聽見這句話,但是對于我來說,中彩票的幾率還是太小了,還是老老實實撸代碼吧,用代碼來實作一下中彩票的快樂。
效果展示
實作步驟
第一步:建立結構
首先根據實作效果建立相應的結構,給刮刮樂畫設定背景圖檔,讓它看起來美觀
實作效果:
hml代碼:
xxx.hml
<div class="container" >
<div class="card">
<div class="prize-box">
<!-- 開獎區域-->
<text class="text">
{{ prize }}
</text>
<!-- 刮刮樂塗層-->
<canvas ref="canvas" style="width:202px;height:43px;" @touchstart="touchstart"
@touchmove="touchmove" @touchend="touchend" @touchcancel="touchcancel" class="canvas"></canvas>
</div>
</div>
</div>
css代碼部分:
.container {
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color:#284243 ;
font-family: sans-serif;
}
/*設定刮獎背景*/
.card{
width:300px;
height:300px;
background-image: url(/common/images/guaguale.png);
background-size: cover;
justify-content: space-around;
align-items: center;
flex-direction: column;
}
.prize-box{
margin-left: 5%;
margin-top: 33%;
width:202px;
}
/*開獎區域樣式*/
.text{
text-align: center;
position: absolute;
width:202px;
height:43px;
background-color: #fff;
z-index: 1;
font-size: 18px;
font-weight:600;
}
/*刮刮樂塗層*/
.canvas{
z-index: 2;
}
完成後實作的效果
第二步:寫js代碼實作上層刮刮樂塗層效果
通過ctx.fillRect方法實作矩形區域的塗層填充,将畫布變為灰色;通過ctx.font設定字型大小,ctx.fillText實作塗層上方文字效果,ctx.fillStyle實作文字顔色設定. 在onShow處進行調用就能實作基礎的塗層效果了;
效果圖如下:
注意:這裡在onInit處調用函數不能成功展示出畫布,在onShow 時調用才顯示成功
xxx.js
onShow(){
this.draw();
},
draw(){
var el = this.$refs.canvas;
var ctx = el.getContext('2d',{ antialias: true });
this.el = el
this.ctx = ctx
//填充的顔色
ctx.fillStyle = 'gray';
//填充矩形 fillRect(起始X,起始Y,終點X,終點Y)
ctx.fillRect(0, 0, 202, 43);
this.ctx.fillStyle = '#000';
//繪制填充文字
this.ctx.font = "28px";
this.ctx.fillText('刮開有獎', 50, 30);
},
第三步:給canvas設定觸摸事件,實作效果
給canvas畫布上綁定觸摸事件,在觸摸時計算觸摸點的位置,以觸摸點的坐标為圓心,進行圓形區域的擦除。
觸摸點坐标計算: 通過觸摸事件得到一個對象, 将對象進行解析會得到對應的值,對資料進行處理,拿到觸摸點的X,Y坐标點。
調用ctx.arc方法進行畫圓,選中圓形區域進行消除。
xxx.hml
<canvas ref="canvas" style="width:202px;height:43px;" @touchstart="touchstart"
@touchmove="touchmove" @touchend="touchend" @touchcancel="touchcancel" class="canvas"></canvas>
xxx.js
touchstart() {
this.isDraw = true;
},
touchmove(e) {
let x = JSON.stringify(e.touches)
//去掉中括号,将其變成對象
let x1 = x.replace(/\[|]/g,'')
let x2 = JSON.parse(x1)
let x3 = JSON.stringify(x2)
//計算觸摸點位置
let X1 = parseInt(JSON.parse(x3).localX)
let Y1 = parseInt(JSON.parse(x3).localY)
this.ctx.globalCompositeOperation = 'destination-out';
//畫圓
this.ctx.arc(X1, Y1, 10, 0, 2 * Math.PI);
console.log('6666666')
//填充圓形
this.ctx.fill();
},
touchend() {
this.isDraw = false;
},
touchcancel(){
this.isDraw = false
},
第四步:設定超過一定百分比清除畫布
計算刮過區域的面積:使用ctx.getImageData方法得到整個區域的圖像資訊。
getImageData() 方法傳回 ImageData 對象,該對象拷貝了畫布指定矩形的像素資料。
對于 ImageData 對象中的每個像素,都存在着四方面的資訊,即 RGBA 值:
- R - 紅色 (0-255)
- G - 綠色 (0-255)
- B - 藍色 (0-255)
- A - alpha 通道 (0-255; 0 是透明的,255 是完全可見的)
color/alpha 以數組形式存在,并存儲于 ImageData 對象的 data 屬性中。
通過判斷像素點的A值是否為0來判斷已經刮過的區域進行計算,最終将計算出的區域面積與總面積進行對比來設定刮除區域超過多少百分比時進行清除整個區域。
通過調用ctx.clearRect方法來進行整個區域的清除。
//計算已經刮過的區域占整個區域的百分比
getFilledPercentage(){
let imgData = this.ctx.getImageData(0,0,this.mWidth,this.mHeight);
//imgData.data是個數組,存儲着指定區域每個像素點的資訊,數組中4個元素表示一個像素點的rgba值
let pixels = imgData.data;
let transPixels = [];
for(let i=0;i<pixels.length;i+=4){
//需要判斷像素點是否透明需要判斷該像素點的a值是否為0
if(pixels[i+3] == 0){
transPixels.push(pixels[i+3])
}
}
return (transPixels.length/(pixels.length/4)*100).toFixed(2) + '%'
},
//設定門檻值,去除灰色塗層
handleFilledPercentage(percentage){
percentage = percentage || 0;
console.log('percentage =' + percentage)
if(parseInt(percentage)>50){
//去除畫布方法一:直接将canvas塗層清除
this.ctx.clearRect(0,0,this.mWidth,this.mHeight)
console.log('清除畫布')
//方法2:将canvas塗層設定為透明
//this.ctx.fillStyle = 'rgba(255,255,255)';
//this.ctx.fillRect(0,0,this.mWidth,this.mHeight)
}
},
源碼位址
https://gitee.com/chen-qi-7/demo-g
總結
以上就是制作一個刮刮樂的詳細過程了,最終效果與上面的效果一樣.其實是一個很簡單的功能,利用了canvas的一些特性來進行操作,後期還可以給其增加更多的功能,歡迎各位開發者一起讨論與研究,希望本次分享對大家的學習有所幫助。
更多原創内容請關注:中軟國際 HarmonyOS 技術團隊
入門到精通、技巧到案例,系統化分享HarmonyOS開發技術,歡迎投稿和訂閱,讓我們一起攜手前行共建鴻蒙生态。
想了解更多關于鴻蒙的内容,請通路:
51CTO和華為官方合作共建的鴻蒙技術社群
https://ost.51cto.com/#bkwz