前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >canvas小案例集合(小画板、画的回放、刮刮乐)

canvas小案例集合(小画板、画的回放、刮刮乐)

作者头像
jojo
发布2022-03-21 20:39:15
1.2K0
发布2022-03-21 20:39:15
举报
文章被收录于专栏:jojo的技术小屋jojo的技术小屋

作者:汪娇娇

日期:2016.12.8

在现在这个公司呆了4个多月,也是研究了canvas将近4个月,前两周心里就痒痒的想写这方面的博客,但一直没时间。可一直拖着也不是个办法,就这样抽抽空来写吧。

canvas的常用方法我就不介绍了,主要是给大家展示几个常用的canvas案例,也是自己做过的一些小东西,希望能对大家有帮助吧。

案例一:小画板

这个应该是canvas最常用的案例之一了:小画板,也就是鼠标画画。PC端和手机端皆有兼容:

成果图:

代码如下:

小提醒:为了兼容手机端,记得加上viewport:

代码语言:javascript
复制
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

1、html代码:

代码语言:javascript
复制
<body>
    <!--画布-->
    <div class="box">
        <canvas id="canvas"></canvas>
    </div>
    
    <!--颜色-->
    <div class="color">
        <span></span>
        <span class="active"></span>
        <span></span>
        <span></span>
        <span></span>
        <span></span>
    </div>
    
    <!--橡皮擦和清除画布-->
    <div class="clear">
        <button id="eraser">橡皮擦</button>
        <button id="btn">清除画布</button>
    </div>
</body>

2、css代码:

代码语言:javascript
复制
<style>
    body{
        margin:0;
        padding:0;
        background: #f1f1f1;
    }
    .box{
        width: 100vw;
        overflow: hidden;
        display: flex;
        justify-content: center;
    }
    #canvas{
        background: #EBE9BB;
    }
    .color{
        overflow: hidden;
        display: flex;
        justify-content: center;
        align-items: center;
        padding: 10px 0;
    }
    .color span{
        display: block;
        width: 40px;
        height: 40px;
        border-radius: 50%;
        margin-right: 10px;
    }
    .active{
        border: 3px solid darkmagenta;
    }
    .clear{
        overflow: hidden;
        text-align: center;
    }
    .clear button{
        padding: 7px 15px;
        background: #008000;
        border-radius: 5px;
        color: #fff;
        font-size: 5vw;
        border: 0;
    }
    #btn{
        background: #ff328e!important;
    }
</style>

3、js代码:

注:我是提前引入jQuery的:

代码语言:javascript
复制
<script src="//cdn.bootcss.com/jquery/1.11.3/jquery.min.js"></script>
代码语言:javascript
复制
<script>
    var w=document.body.clientWidth;
    var width,x1,y1,x2,y2,a=10;
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    
    //画布宽高初始化
    if(w>=320 && w<=480){
        canvas.width=w;
        canvas.height=w;
        width=w;
    }else if(w>480){
        canvas.width=480;
        canvas.height=480;
        width=w;
    }
    
    //颜色初始化
    var colors="green";
    var color=["black","green","red","gray","blue","yellow"];
    for(var i=0;i<color.length;i++){
        var j=i+1;
        $(".color>span:nth-child("+j+")").css("background",color[i]);
    }
    
    //选颜色
    $(".color>span").click(function(){
        $(this).addClass("active");
        $(this).siblings().removeClass("active");
        colors=$(this)[0].style.background; 
        a=10;
        tapClip();
    })
    
    //点击“橡皮擦”按钮
    $("#eraser").click(function(){
        colors="#EBE9BB";
        a=30;
        tapClip();
    })
    
    //点击“清除画板”按钮
    $("#btn").click(function(){
        ctx.clearRect(0,0,width,width);
    })
    
    tapClip();
    //在画板上画画的函数
    function tapClip(){
        //区分PC还是手机
        var hastouch = "ontouchstart" in window ? true:false,
            tapstart = hastouch ? "touchstart":"mousedown",
            tapmove = hastouch ? "touchmove":"mousemove",
            tapend = hastouch ? "touchend":"mouseup";
        
        //笔触圆滑
        ctx.lineCap = "round";
        ctx.lineJoin = "round";
        ctx.lineWidth = a;
        ctx.strokeStyle=colors;
        
        //touchstart或者mousedown
        canvas.addEventListener(tapstart , function(e){
            e.preventDefault();
            x1 = hastouch?e.targetTouches[0].pageX-canvas.offsetLeft:e.clientX-canvas.offsetLeft;
            y1 = hastouch?e.targetTouches[0].pageY-canvas.offsetTop:e.clientY-canvas.offsetTop;
            ctx.beginPath()
            ctx.moveTo(x1,y1);
            ctx.lineTo(x1+1,y1+1);  //考虑到点击时能画出一个点
            ctx.stroke();
            
            //touchmove或者mousemove
            canvas.addEventListener(tapmove , tapmoveHandler);
            
            //touchend或者mouseup
            canvas.addEventListener(tapend , function(){
                canvas.removeEventListener(tapmove , tapmoveHandler);
            });
            
            //move时的处理函数
            function tapmoveHandler(e){
                e.preventDefault()
                x2 = hastouch?e.targetTouches[0].pageX-canvas.offsetLeft:e.clientX-canvas.offsetLeft;
                y2 = hastouch?e.targetTouches[0].pageY-canvas.offsetTop:e.clientY-canvas.offsetTop;                
                ctx.moveTo(x1,y1);
                ctx.lineTo(x2,y2);
                ctx.stroke();
                x1 = x2;
                y1 = y2;
            }
        })
    }
</script>

案例二:画的回放

方法:结合getImageData()和putImageData()

原理:通过 getImageData() 复制画布上的像素数据,然后通过 putImageData() 将图像数据放回画布。

getImageData()格式:

ImageData下面的data就是构成画布上的像素数据。

效果图如下:

以下代码仅以PC端为例:

1、html代码:

代码语言:javascript
复制
<body>
    <div class="box">
        <canvas id="canvas" width=320px" height="320px"></canvas>
    </div>
    
    <button id="btn">点击回放</button>
</body>

2、css代码:

代码语言:javascript
复制
<style>
    *{
        margin: 0;
        padding: 0;
    }
    .box{
        width: 100vw;
        overflow: hidden;
        display: flex;
        justify-content: center;
        margin-bottom: 10px;
    }
    #canvas{
        background: #EBE9BB;
    }
    #btn{
        display: block;
        margin: 0 auto;
        padding: 7px 15px;
        background: #ff328e;
        border-radius: 5px;
        color: #fff;
        font-size: 20px;
        border: 0;
    }
</style>

3、js代码:

代码语言:javascript
复制
<script>
	var w=320;
    var width,arr=[];
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    var btn=document.getElementById("btn");
    
    //鼠标按下
    canvas.onmousedown=function(event){
        ctx.moveTo(event.pageX-canvas.offsetLeft,event.pageY-canvas.offsetTop)
        ctx.lineTo(event.pageX-canvas.offsetLeft+1,event.pageY-canvas.offsetTop+1)
        ctx.stroke();
        //获取像素,存到数组
        var imageData=ctx.getImageData(0,0,w,w);
        arr.push(imageData);
        //鼠标移动
        canvas.onmousemove=function(event){
            ctx.lineTo(event.pageX-canvas.offsetLeft,event.pageY-canvas.offsetTop)
            ctx.stroke();
            //获取像素,存到数组
            var imageData=ctx.getImageData(0,0,w,w);
            arr.push(imageData);
        }
        //鼠标释放
        canvas.onmouseup=function(){
            canvas.onmousemove=null;
            canvas.onmousestart=null;
        }
    }	   
    
    //点击“点击回放”按钮
    btn.onclick=function(){
        ctx.clearRect(0,0,w,w);
        var i=0;
        var timer;
        clearInterval(timer);
        //利用定时器回放像素
        timer=setInterval(function(){
            if(arr.length==0){
                clearInterval(timer);
            }else{
                ctx.putImageData(arr[i],0,0);
                i++;
                if(i>=arr.length){
                    clearInterval(timer);
                }
            }
        },10)
    }
</script>

这是其中一个办法,还有一个办法就是通过存储坐标点,然后用定时器回放坐标点。方法类似,大家可以自己研究研究。

案例三:刮刮乐()

原理:ctx.globalCompositeOperation = "destination-out";

在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。

效果图:

1、html代码:

代码语言:javascript
复制
<body>
	<div class="box" id="bb">
		<canvas id="canvas"></canvas>
	</div>
</body>

2、css代码:

代码语言:javascript
复制
<style>
	body{
		margin:0;
		padding:0;
	}
	.box{
	    width: 100vw;
	    height: 30vh;
		position: absolute;
		left:0;
		top:0;
		overflow: hidden;
	}
</style>

3、js代码:

代码语言:javascript
复制
<script>
	var canvas = document.getElementById("canvas");
	var ctx = canvas.getContext("2d");
	var x1,y1,a=60;
	canvas.width = document.getElementById("bb").clientWidth;
	canvas.height = document.getElementById("bb").clientHeight;
	var w=$("#canvas").width();
    var h=$("#canvas").height();
    
    //加载图片
	var img = new Image();
	img.src = "dim.png";
	img.onload = function(){
		ctx.drawImage(img,0,0,canvas.width,canvas.height);
		$(".box").css("background","url('noScratch.png') no-repeat");
		$(".box").css("background-size","100% 100%");
		tapClip();
	}
	
    //在小画板上画画的函数
	function tapClip(){
		var hastouch = "ontouchstart" in window ? true:false,
			tapstart = hastouch ? "touchstart":"mousedown",
			tapmove = hastouch ? "touchmove":"mousemove",
			tapend = hastouch ? "touchend":"mouseup";

		ctx.lineCap = "round";
		ctx.lineJoin = "round";
		ctx.lineWidth = a;
		
		//在源图像外显示目标图像。只有源图像外的目标图像部分会被显示,源图像是透明的。
		ctx.globalCompositeOperation = "destination-out";
		
        //touchstart或mousedown
		canvas.addEventListener(tapstart , function(e){
			e.preventDefault();
			ctx.beginPath();
            //touchmove或mousemove
			canvas.addEventListener(tapmove , tapmoveHandler);
			canvas.addEventListener(tapend , function(){
				canvas.removeEventListener(tapmove , tapmoveHandler);
                //获取像素
				var data = ctx.getImageData(0,0,w,h).data;
				for (var i=0,j=0;i<data.length;i+=4){
                    if(data[i]&&data[i+1]&&data[i+2]&&data[i+3]){
                        j++;
                    }
                }
				//刮到60%时显示全部
				if(j<=canvas.width*canvas.height*0.6){
                    ctx.clearRect(0,0,w,h);
                }
			});
            //move时的处理函数
			function tapmoveHandler(e){
				e.preventDefault()
				x2 = hastouch?e.targetTouches[0].pageX:e.clientX-canvas.offsetLeft;
				y2 = hastouch?e.targetTouches[0].pageY:e.clientY-canvas.offsetTop;
				
				ctx.moveTo(x1,y1);
				ctx.lineTo(x2,y2);
				ctx.stroke();
				
				x1 = x2;
				y1 = y2;
			}
		})
	}
</script>

思考:刮刮乐的方法可以延伸到彩色画笔,大家自己思考一下哈,如下图:

canvas暂时就到这儿了。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017/01/17 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档