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

2022-03-21 20:39:15 浏览数 (1)

作者:汪娇娇

日期: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暂时就到这儿了。

0 人点赞