canvas应用----刮刮乐

最近在学习html5,为了更好地学习和帮助其他人我决定把我写过的案例写下来~~

先说一下刮刮乐这个程序实现的注意点

  • 材料:一张图片和canvas画布
  • 在html页面只要放图片元素,canvas由js生成。 这是为了保证canvas生成在img上面而且保证刚打开页面的时候不会看见图片
  • 生成的canvas涂层要保证大小和位置和图片的相同

CSS

*{padding:0;margin:0;}
body{
	background-color: skyblue;
	text-align: center;
}
#img{
	margin-top: 100px;
	user-select: none;
}
canvas{
	user-select: none;
}

html

<img src = "img/1.jpg" alt="" id = "img">
<input type = "text" id = "txt">

js

let img = document.querySelector("#img")
let txt = document.querySelector("#txt")

// 保证图片和canvas生成顺序不会出错
if( img.readyState === "complete" ){
	draw()
} else{
	img.onload = draw
}

function draw() {
	// 生成canvas涂层
	let can = document.createElement("canvas")
	// 保证涂层宽高与画布宽高一致
	can.width = img.width
	can.height = img.height
	// 保证涂层位置与画布位置一致
	can.style.position = "absolute"
	can.style.left = img.offsetLeft + "px"
	can.style.top = img.offsetTop + "px"
	// 插入生成的canvas
	img.parentNode.insertBefore( can, img )
	// canvas样式
	let ctx = can.getContext("2d")
	ctx.fillStyle = "#bbb" // 涂层的颜色
	ctx.fillRect( 0, 0, img.width, img.height ) // 填充canvas涂层
	// 以上的样式可以先写在一个字符串中,然后只要用ctx.cssText就好了  但是这里为了更直观我就一步步写了
	
	// 合成  处理合成图片的透明样式
	// 拖拽的时候使canvas涂层透明
	ctx.globalCompositeOperation = "destination-out"
	
	// 画笔样式
	ctx.lineWidth = 30
	ctx.lineCap = "round"

	// 拖拽事件
	can.onmousedown = function (e) {
		let x = e.pageX - can.offsetLeft
		let y = e.pageY - can.offsetTop
		// 在涂层点一下的时候要有一个圆点
		ctx.beginPath()
		ctx.arc( x, y, 15, 0, 2*Math.PI, false ) 
		ctx.fill()

		 can.onmousemove = function (e) {
		 	ctx.beginPath()
		 	ctx.moveTo(  x, y )
		 	ctx.lineTo( e.pageX - can.offsetLeft, e.pageY - can.offsetTop )

			// 滚动过程中实时更新坐标
			x = e.pageX - can.offsetLeft
			y = e.pageY - can.offsetTop
			// 描线
			ctx.stroke() // 这里是描线,用fill会没有效果
		 } 

		 document.onmouseup = function (e) {
		 	 // 这里对document绑定事件是因为抬起鼠标的时候可能是在图片之外抬起
			can.onmousemove = null
			this.onmouseup = null
			check() // 这里增加一个功能,已涂面积超过30%的时候显示全部图片
		 }
	}
	
	function check () {
		let data = ctx.getImageData( 0, 0, can.width, can.height ).data
		let n = 0 // 已经刮开的像素点
		for( let i = 0; i < data.length; i+=4 ){
			if( data[i] === 0 && data[i+1] === 0 && data[i+2] === 0 && data[i+3] === 0 ) {
				// 这里的data表示一个像素点的rgba  由于被刮过的像素点变透明,因此此时rgba都为0
				n++
			}
		}
		// 算出当前已刮面积占比
		let f = n * 100 / ( can.width * can.height )
		txt.value = `刮开面积:${f.toFixed(2)}%`
		// 如果超过30%则展示完整画面
		if( f > 30 ){
			ctx.beginPath()
			ctx.fillRect( 0, 0, can.width, can.height )
			txt.value = `给你看完整的图片吧~~`
		}
	}
}

好了,要是有什么问题或者建议的话欢迎联系我~

Wish you godspeed!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值