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