先看一下效果圖:

ps: 圖片有晃動的效果,是博主截圖大小不一致造成的,以至於合成的gif圖有晃動的效果,實際頁面中是沒有的,請勿擔心哦
實現的原理:
1.通過canvas標簽屬性進行繪畫實現
2.實際有3層,底層是存放獎品名稱,中層是canvas畫出的刮層,表層是那個紅色的禮節 通過absolute 絕對定位實現重疊效果(單獨切紅色禮節,就是避免計算canvas特殊形狀,只需要簡單地舉行即可)
3.首次看會以為我的canvas底部畫的是不規則的形狀,其實不然,canvas刮層畫的是矩形,上面通過單獨把 紅色禮節 切圖出來,定位上去的
上代碼:
1.html :
<template>
<div class="container" id="top">
<div class="award_box">
<div class="award" v-if="showPrize">
<div class="title">
恭喜您獲得
<span>198元享受580元(燙/染2選1)優惠券</span>
</div>
</div>
<div class="surface"></div>
<canvas
id="c1"
class="canvas"
@touchmove="touchmove"
@touchstart="touchstart"
@touchend="touchend"
v-show="!isScratch"
></canvas>
</div>
</div>
</template>
2.js:
export default { name: "scratchCard", data() { return { c1: "", //畫布 ctx: "", //畫筆 ismousedown: false, //標志用戶是否按下鼠標或開始觸摸 fontem: "", // 獲取html字體大小 isScratch: false, // 是否刮過卡 showPrize: false // 顯示獎品 }; }, mounted() { this.fontem = parseInt( window.getComputedStyle(document.documentElement, null)["font-size"] ); //這是為了不同分辨率上配合@media自動調節刮的寬度 this.c1 = document.getElementById("c1"); //這里很關鍵,canvas自帶兩個屬性width、height,我理解為畫布的分辨率,跟style中的width、height意義不同。 //最好設置成跟畫布在頁面中的實際大小一樣 //不然canvas中的坐標跟鼠標的坐標無法匹配 this.c1.width = this.c1.clientWidth + 15 this.c1.height = this.c1.clientHeight; this.ctx = this.c1.getContext("2d"); this.initCanvas(); }, methods: { // 畫刮刮卡 initCanvas() { this.ctx.globalCompositeOperation = "source-over"; this.ctx.fillStyle = "#e5e5e5"; this.ctx.fillRect(0, 0, this.c1.clientWidth, this.c1.clientHeight); this.ctx.fill(); this.ctx.font = "Bold 24px Arial"; this.ctx.textAlign = "center"; this.ctx.fillStyle = "#a0a0a0"; this.ctx.fillText("刮開有獎", this.c1.width / 2, 55); //有些老的手機自帶瀏覽器不支持destination-out,下面的代碼中有修復的方法 this.ctx.globalCompositeOperation = "destination-out"; }, touchstart(e) { e.preventDefault(); this.ismousedown = true; }, // 操作刮卡 touchend(e) { sessionStorage.setItem('isScratch',true) e.preventDefault(); //得到canvas的全部數據 var a = this.ctx.getImageData(0, 0, this.c1.width, this.c1.height); var j = 0; for (var i = 3; i < a.data.length; i += 4) { if (a.data[i] == 0) j++; } //當被刮開的區域等於一半時,則可以開始處理結果 if (j >= a.data.length / 8) { this.isScratch = true; } this.ismousedown = false; }, touchmove(e) { this.showPrize = true e.preventDefault(); if (this.ismousedown) { if (e.changedTouches) { e = e.changedTouches[e.changedTouches.length - 1]; } var topY = document.getElementById("top").offsetTop; var oX = this.c1.offsetLeft, oY = this.c1.offsetTop + topY; var x = (e.clientX + document.body.scrollLeft || e.pageX) - oX || 0, y = (e.clientY + document.body.scrollTop || e.pageY) - oY || 0; //畫360度的弧線,就是一個圓,因為設置了ctx.globalCompositeOperation = 'destination-out'; //畫出來是透明的 this.ctx.beginPath(); this.ctx.arc(x, y, this.fontem * 0.5, 0, Math.PI * 2, true); // 調整畫筆的大小 //下面3行代碼是為了修復部分手機瀏覽器不支持destination-out //我也不是很清楚這樣做的原理是什么 // this.c1.style.display = 'none'; // this.c1.offsetHeight; // this.c1.style.display = 'inherit'; this.ctx.fill(); } } } };
3.css:
.container { width: 100%; height: 100%; background-color: #985113; padding:100px 0; .award_box { width: 95%; height: 360px; margin: 0px auto; background: url("./img/2.img") no-repeat center/100%; padding-top: 70px; .award { width: 85%; height: 180px; position: absolute; left: 50%; transform: translateX(-50%); width: 68%; .title { color: rgba(3, 45, 97, 1); font-size: 32px; font-weight: 800; line-height: 50px; margin-top: 50px; overflow: hidden; text-overflow: ellipsis; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; span { color: #cc162d; } } } .surface { position: absolute; z-index: 98; width: 95%; height: 160px; margin: 150px auto; background: url("./img/1.png") no-repeat center/100%; padding-top: 70px; } .canvas { position: relative; } } .map_box{ margin-top: 200px; width: 100%; height: 500px; padding:10px; bottom:5px solid orange; box-sizing:border-box; } }
