1. 布局
上面用来显示底部的文字,或者图片也行
然后绝对定位,再放入canvas
覆盖
html
<style>
.wrapper {
position: relative;
width: 300px;
height: 250px;
background-color: #fcc;
}
.ticket {
display: flex;
position: absolute;
inset: 0;
}
.label {
margin: auto;
color: #fff;
font-size: 66px;
user-select: none;
}
canvas {
position: absolute;
}
</style>
<body>
<div class="wrapper">
<div class="ticket">
<span class="label">一等奖</span>
</div>
</div>
<body>
2. 创建画布
传入的参数是父容器,让他们的大小一致
js
function createScratchTicket(wrapper) {
const cvs = document.createElement('canvas')
const ctx = cvs.getContext('2d')
cvs.width = wrapper.clientWidth
cvs.height = wrapper.clientHeight
// 绘制刮奖区域
ctx.fillStyle = '#999'
ctx.fillRect(0, 0, cvs.width, cvs.height)
return cvs
}
3. 设置样式
注意globalCompositeOperation
这个属性,他可以让我们选择后面画的图与前面的图之间的绘制关系
js
function setStyle(ctx) {
// 什么颜色都行
ctx.fillStyle = 'transparent'
ctx.lineWidth = 15
ctx.lineCap = 'round'
ctx.lineJoin = 'round'
ctx.globalCompositeOperation = 'destination-out'
}
这是MDN的描述
developer.mozilla.org/zh-CN/docs/...
也就是说,设置了这个属性,当我们往画布上填充新的内容时,就能产生涂抹效果
4. 初始化
把画布放入容器中,然后设置上面的样式,再绑定事件
js
function init() {
const wrapper = document.querySelector('.wrapper')
const cvs = createScratchTicket(wrapper)
const ctx = cvs.getContext('2d')
wrapper.appendChild(cvs)
setStyle(ctx)
bindEvent(cvs, ctx)
}
5. 事件
当鼠标按下时,记录位置,鼠标移动时,填充画布,鼠标抬起时,删除事件即可
js
function bindEvent(el, ctx) {
el.onmousedown = function ({ clientX, clientY }) {
ctx.moveTo(clientX, clientY)
el.onmousemove = function ({ clientX, clientY }) {
ctx.lineTo(clientX, clientY)
ctx.stroke()
}
el.onmouseup = function () {
el.onmousemove = null
el.onmouseup = null
}
}
}
6. 问题
上面的绑定事件,有个小问题,当你的鼠标移出浏览器时,就不能解绑事件
解决方法就是多绑定一个事件,不过这样你的鼠标刮图时,就不能超出元素了
js
function bindEvent(el, ctx) {
el.onmousedown = function ({ clientX, clientY }) {
ctx.moveTo(clientX, clientY)
el.onmousemove = function ({ clientX, clientY }) {
ctx.lineTo(clientX, clientY)
ctx.stroke()
}
// 移出浏览器或元素时也会解绑
el.onmouseup = el.onmouseout = function () {
el.onmousemove = null
el.onmouseup = null
}
}
}