canvas进阶2

2017-12-27

canvas画图片

  • ctx.drawImage(图片对象,x,y);
    三个参数:图片对象,开始绘制图片的坐标(即从图片的何位置开始绘制)
  • ctx.drawImage(图片对象,x,y,width,height);
    五个参数:后两个参数是所绘画的图片在画布中的宽和高
  • ctx.drawImage(图片对象,x,y,width,height,x1,y1,width1,height1);
    九个参数:后四个参数分别为所绘图片在画布中开始绘画的位置坐标和在画布中的宽和高。
  • 因为图片、视频等属于资源数据,加载需要一定的时间,所以需要预加载。
    1
    2
    3
    4
    5
    var img=new Image();
    img.src="path./src.png";
    img.onload=function(){
    ctx.drawImage(img,0,0,100,100,10,10,100,100);
    }

屏幕快照 2017-12-27 下午9.22.22.png

getImageData(0,0,500,500);获取图片像素点

  • 四个参数分别为:开始获取像素点的坐标,获取范围的宽和高
    1
    2
    3
    4
    5
    6
    7
    var img=new Image();
    img.src="path./src.png";
    img.onload=function(){
    ctx.drawImage(img,0,0,100,100,0,0,500,500);
    var imageData=ctx.getImageData(0,0,500,500);
    console.log(imageData);
    }

imageData

  • 可以打印看看里面的数据形式
  • 所得到的imageData是一个对象,分别为:data数组、所获取像素点的宽度、所获取像素点的高度
  • 所获取到的imageData是所有的rgba(r,g,b,a)的四个参数,4个为一组
  • 所以遍历imageData.data数组,可以得到所有的像素点。
  • 利用对像素点的处理,可以改变整个图片的色调,进而对图片进行简单的色调处理。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    var img=new Image();
    img.src="path./src.png";
    img.onload=function(){
    ctx.drawImage(img,0,0,100,100,0,0,500,500);
    var imageData=ctx.getImageData(0,0,500,500);
    console.log(imageData);
    for(var i=0;i<imageData.data.length;i+=4){
    var r=imageData.data[i];
    var g=imageData.data[i+1];
    var b=imageData.data[i+2];
    var a=imageData.data[i+3];//透明度
    }
    var gray=(r+g+b)/3;
    imageData.data[i]=gray;
    imageData.data[i+1]=gray;
    imageData.data[i+2]=gray;
    }
    //再把变之后的颜色重新赋值给imageData对象
    ctx.putImageData(imageData,100,100);//后两个参数为要给颜色的位置,(画布中的坐标),还可以利用这个属性对图像进行反色处理,如下图所示.

屏幕快照 2017-12-28 下午7.07.29.png

bezier曲线

  • 二次贝塞尔曲线ctx.quadraticCurveTo(500,0,500,500);画贝塞尔曲线包括画一个起始点,即ctx.moveTo(0,0);函数里面的两个坐标分别为控制点的坐标和结束点的坐标。
  • 三次贝塞尔曲线ctx.bezierCurveTo(500,0,0,500,500,500);跟二次贝塞尔曲线一样,只不过多了一对控制点,可以画更丰富的曲线。它也同样需要一个开始点。
    1
    2
    3
    4
    ctx.beginPath();
    ctx.moveTo(0,0);
    ctx.quadraticCurveTo(500,0,500,500);
    ctx.stroke();

屏幕快照 2017-12-28 下午7.20.41.png

1
2
3
4
ctx.beginPath();
ctx.moveTo(0,0);
ctx.bezierCurveTo(500,0,0,500,500,500);
ctx.stroke();

屏幕快照 2017-12-28 下午7.21.13.png

小栗子🎩🎩🎩

动态贝塞尔曲线动画

  • 实现这个效果有两种方法可以判断鼠标的点在红球上还是蓝球上,一是计算鼠标落下的点距离小球圆心的距离,第二种方法就是下面所演示的利用ctx.isPointInPath(x,y);来判断某一点是否在当前画布中,此方法只能判断当前画布的点,所以把红球和蓝色球分开画,分开判断就行了。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    function draw(x1,y1,x2,y2){
    //画灰色虚线
    ctx.beginPath();
    ctx.moveTo(0,500);
    ctx.lineTo(500,0);
    ctx.lineWidth=15;
    ctx.strokeStyle="lightgray";
    ctx.stroke();
    //画黑色实线
    ctx.beginPath();
    ctx.moveTo(500,0);
    ctx.bezierCurveTo(x1,y1,x2,y2,0,500);
    ctx.lineWidth=15;
    ctx.strokeStyle="black";
    ctx.stroke();
    //画两条细黑线
    ctx.beginPath();
    ctx.moveTo(0,500);
    ctx.lineTo(x1,y1);
    ctx.lineWidth=5;
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(500,0);
    ctx.lineTo(x2,y2);
    ctx.lineWidth=5;
    ctx.stroke();
    }
    //画红球的方法
    function redBall(x1,y1){
    ctx.beginPath();
    ctx.fillStyle="pink";
    ctx.arc(x1,y1,10,0,Math.PI*2);
    ctx.fill();
    }
    //画蓝球的方法
    function blueBall(x2,y2){
    ctx.beginPath();
    ctx.fillStyle="blue";
    ctx.arc(x2,y2,10,0,Math.PI*2);
    ctx.fill();
    }
    //初始化
    var x1=100;
    var y1=100;
    var x2=400;
    var y2=400;
    draw(x1,y1,x2,y2);
    redBall(x1,y1);
    blueBall(x2,y2);
    mycanvas.onmousedown=function(e){
    var ev=e || window.event;
    var xx=ev.clientX-mycanvas.offsetLeft;
    var yy=ev.clientY-mycanvas.offsetTop;
    redBall(x1,y1);
    //判断鼠标落下的点在不在红球内
    if(ctx.isPointInPath(xx,yy)){
    console.log("在红球中");
    mycanvas.onmousemove=function(e){
    var ev=e || window.event;
    var xx1=ev.clientX-mycanvas.offsetLeft;
    var yy1=ev.clientY-mycanvas.offsetTop;
    ctx.clearRect(0,0,mycanvas.width,mycanvas.height);
    x1=xx1;
    y1=yy1;
    draw(x1,y1,x2,y2);
    redBall(x1,y1);
    blueBall(x2,y2);
    }
    }
    blueBall(x2,y2);
    //判断鼠标落下的点在不在红球内
    if(ctx.isPointInPath(xx,yy)){
    console.log("在蓝球中");
    mycanvas.onmousemove=function(e){
    var ev=e || window.event;
    var xx1=ev.clientX-mycanvas.offsetLeft;
    var yy1=ev.clientY-mycanvas.offsetTop;
    ctx.clearRect(0,0,mycanvas.width,mycanvas.height);
    x2=xx1;
    y2=yy1;
    draw(x1,y1,x2,y2);
    redBall(x1,y1);
    blueBall(x2,y2);
    }
    }
    }
    document.onmouseup=function(){
    mycanvas.onmousemove=null;
    }

0.gif

刮刮卡效果

  • 在canvas画布中,画布的默认颜色是透明的,并且利用组合图形的相关函数我们可以做出刮刮卡的效果
  • ctx.globalCompositeOperation设置组合图形的目标图和源图的组合方式
  • 在canvas中把先画的图叫做目标图,后画的图叫做源图。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    //目标图
    ctx.beginPath();
    ctx.fillStyle="gray";
    ctx.fillRect(0,0,mycanvas.width,mycanvas.height);
    ctx.globalCompositeOperation="destination-out";
    //画源图
    mycanvas.onmousedown=function(e){
    var ev=window.event || e;
    var x1=ev.clientX-mycanvas.offsetLeft;
    var y1=ev.clientY-mycanvas.offsetTop;
    ctx.beginPath();
    ctx.moveTo(x1,y1);
    mycanvas.onmousemove=function(e){
    var ev=window.event || e;
    var x2=ev.clientX-mycanvas.offsetLeft;
    var y2=ev.clientY-mycanvas.offsetTop;
    ctx.lineTo(x2,y2);
    ctx.lineWidth=23;
    ctx.lineCap="round";
    ctx.stroke();
    }
    }
    document.onmouseup=function(){
    mycanvas.onmousemove=null;
    }

b.gif

进阶版刮刮卡

  • 可以通过对像素点的利用让刮刮卡刮到一半的时候自动刮开。
  • 即判断所有的像素点透明度为0的点,a的值=0.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    //目标图
    ctx.beginPath();
    ctx.fillStyle="gray";
    ctx.fillRect(0,0,mycanvas.width,mycanvas.height);
    ctx.globalCompositeOperation="destination-out";
    //画源图
    mycanvas.onmousedown=function(e){
    var ev=window.event || e;
    var x1=ev.clientX-mycanvas.offsetLeft;
    var y1=ev.clientY-mycanvas.offsetTop;
    ctx.beginPath();
    ctx.moveTo(x1,y1);
    mycanvas.onmousemove=function(e){
    var ev=window.event || e;
    var x2=ev.clientX-mycanvas.offsetLeft;
    var y2=ev.clientY-mycanvas.offsetTop;
    ctx.lineTo(x2,y2);
    ctx.lineWidth=23;
    ctx.lineCap="round";
    ctx.stroke();
    all();
    }
    }
    document.onmouseup=function(){
    mycanvas.onmousemove=null;
    }
    //判断像素点的函数
    function all(){
    var imgData=ctx.getImageData(0,0,mycanvas.width,mycanvas.height);
    var per=imgData.data.length/8;
    var count=0;
    for(var i=0;i<imgData.data.length;i+=4){
    var a=imgData.data[i+3];
    if(a==0){
    count++;
    if(count>=per){
    ctx.clearRect(0,0,mycanvas.width,mycanvas.height);
    }
    }
    }
    }

c.gif