你的位置:首页 > 网页设计

[网页设计]canvas基础学习(二)


一、图像绘制

canvas绘制图像的方法是ctx.drawImage();该方法有三种使用方式

1、ctx.drawImage(img,x,y);

img是指图像对象,x和y分别是这个图像左上角在canvas画布的坐标,而图像显示的大小为图像本身的像素值,超出canvas画布的部分不显示。

2、ctx.drawImage(img,x,y,w,h);

和上面的那个函数相比,可以控制图像在canvas中显示的宽度和高度,而不再是图片自身的高宽像素

3、ctx.drawImage(img , dx , dy , dw , dh , x , y , w , h);

这个又比之前的函数多了dx、dy、dw、dh这四个参数,这四个参数可以控制图片切片显示在canvas画布中。在图片上同样以左上角为原点,向右为X轴正方向,向下为Y轴正方向,这四个参数表示,在图片中在(dx,dy)这个坐标,切dw和dh大小的切片。然后将这个切片显示在canvas画布上。

最后这个img参数,不单单可以是Image对象,还可以是video对象,也可以是另外的canvas对象。所以可以通过该方法对video视频进行截屏,也可以通过加载canvas制作图像水印、放大镜、以及淘宝双11主会场那样的特效,一个canvas加载另一个canvas,也被称为canvas的离屏技术。

 

二、图像的像素级处理

1、ctx.getImageData(x , y , w , h);

这个方法是获取画布(x,y)坐标,宽高分别为w和h的像素对象。而这个对象的data属性,则是其rgba的值。一个画布的像素值是从画布的原点,从左向右,从上到下,一排一排的排列下来的。常用取出canvas像素值的方法有两种,一种是采用一层循环,另一种是采用双重for循环,代码如下:

var imageData = ctx.getImageData(0 , 0 , canvasW , canvasH),   pixelData = imageData.data;//方式一for(var i = 0; i < canvasH*canvasW ; i++){  var r = pixelData[4*i + 0],     g = pixelData[4*i + 1],     b = pixelData[4*i + 2],       a = pixelData[4*i + 3];} //方式二for(var y = 0 ; i < canvasH ; y++){  for(var x = 0 ; x < canvasW ; x++){   var pixe = canvasW*y + x,     r = pixelData[4*pixe + 0],     g = pixelData[4*pixe + 1],     b = pixelData[4*pixe + 2],     a = pixelData[4*pixe + 3];  }}

 

2、ctx.putImageData()

该方法是设置canvas画布上的像素数据,它有七个参数,在w3c上是这么解释的

 我的理解就是将imgData,放在画布上的位置是(x + dirtyX , y + dirtyY),高宽分别是dirtyHeight、dirtyWidth的矩形。

 

三、代码demo

1、图片缩放,以及像素变换

<!DOCTYPE html><html>  <head>    <meta charset="utf-8">    <title>图像学习</title>    <style>      #main,#copy,.contain{        margin: 15px;        padding: 0;        float: left;              }      #main{        cursor:move      }      .contain *{        padding: 2px;        margin: 0;z      }      .contain a{        display: block;        text-align: center;         margin-top:5px;        font-size:15px;        line-height: 20px;      }    </style>  </head>  <body>    <canvas id="main" width="400" height="300" style="display:block;border: 1px solid #AAA;">      亲,您的浏览器不支持canvas    </canvas>    <div class="contain" style="width: 290px;height: 300px;">      <div>        <span>缩放</span>        <input type="range" id="scaleChange" min="0.5" max="4.0" step="0.03" value="1.0"           style="display:inline-block;width: 240px;"/>      </div>      <a href="javascript:void(0)" id="greyChange">灰度转换</a>      <a href="javascript:void(0)" id="blackChange">黑度转换</a>      <a href="javascript:void(0)" id="reverChange">反相转换</a>      <a href="javascript:void(0)" id="blurChange">模糊处理</a>      <a href="javascript:void(0)" id="mosaicChange">马赛克处理</a>    </div>    <canvas id="copy" width="400" height="300" style="display:block;border: 1px solid #AAA;">      亲,您的浏览器不支持canvas    </canvas>    <canvas id="waterMark" style="display: none;">         亲,您的浏览器不支持canvas       <!--           水印作图的canvas,把一个canvas载入另一个canvas的做法叫做,离屏canvas       -->    </canvas>  </body>  <script>    document.body.onload = function(){      var canvas = document.getElementById("main"),        scaleChange = document.getElementById("scaleChange"),        copyCanvas = document.getElementById("copy"),        waterMarkCanvas = document.getElementById("waterMark"),        ctx = canvas.getContext("2d"),        copyCtx = copyCanvas.getContext("2d"),        canvasW = canvas.width,        canvasH = canvas.height;      var img = new Image();      img.src = "img.jpg";      img.onload = function(){    //当图片加载完毕后,执行canvas画图函数        init();      }      //用于初始化      function init(){        toolFunc.handleWaterMark();        toolFunc.handleScale();        toolFunc.drawImg();        toolFunc.handleEffect();        toolFunc.handleCanvasMove();      }      var toolFunc = {        scaleImgX : 0,        scaleImgY : 0,        drawImg : function(moveX , moveY){  //绘制图片          var scale = scaleChange.value;            //根据比例计算缩放后图像的大小            var imgW = canvasW*scale,              imgH = canvasH*scale,              x = (canvasW - imgW)/2,              y = (canvasH - imgH)/2,              tempX = x , tempY = y;            if(moveX || moveY){              x = this.scaleImgX + moveX;              y = this.scaleImgY + moveY;              if(x >= 0 || y >= 0 || x <= 2*tempX || y <= 2*tempY){                return;              }            }            ctx.clearRect(0 , 0 , canvasW , canvasH);            ctx.drawImage(img , x , y , imgW , imgH);            ctx.drawImage(waterMarkCanvas ,               canvasW - waterMarkCanvas.width ,              canvasH - waterMarkCanvas.height ,              waterMarkCanvas.width , waterMarkCanvas.height);            this.scaleImgX = x;            this.scaleImgY = y;        },        handleWaterMark : function(){    //用于处理水印          waterMarkCanvas.width = 200;          waterMarkCanvas.height = 70;          var waterCtx = waterMarkCanvas.getContext("2d");          waterCtx.font = "bold 20px Arial";          waterCtx.lineWidth = 1;          waterCtx.fillStyle = "white";          waterCtx.textAlign = "center";          waterCtx.textBaseline = "middle";          waterCtx.fillText( "~!~ sky ~!~" , 140 , 50 , waterMarkCanvas.width);        },        handleScale : function(){    //用于处理缩放          var isScale = false,            _this = this;          scaleChange.onmousedown = function(){            isScale = true;          }          scaleChange.onmousemove = function(){            if(isScale){    //画图              _this.drawImg();            }          }          scaleChange.onmouseup = function(){            isScale = false;          }        },        handleEffect : function(){  //处理效果变换          var imageData,pixelData;          document.getElementById("greyChange").onclick = function(){    //灰度变换            imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);            pixelData = imageData.data;            for(var i = 0; i < canvasH*canvasW ; i++){              var r = pixelData[4*i + 0],                g = pixelData[4*i + 1],                b = pixelData[4*i + 2],                grey = r*0.3+g*0.59+b*0.11;//此为灰度图像的算法              pixelData[4*i + 0] = grey;              pixelData[4*i + 1] = grey;              pixelData[4*i + 2] = grey;            }            copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);          }          document.getElementById("blackChange").onclick = function(){    //黑度变换            imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);            pixelData = imageData.data;            for(var i = 0; i < canvasH*canvasW ; i++){              var r = pixelData[4*i + 0],                g = pixelData[4*i + 1],                b = pixelData[4*i + 2],                grey = (function(n){    //黑度图像就只有黑白两色                  if(n > 127){                    return 255;                  }else{                    return 0;                  }                })(r*0.3+g*0.59+b*0.11);              pixelData[4*i + 0] = grey;              pixelData[4*i + 1] = grey;              pixelData[4*i + 2] = grey;            }            copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);          }          document.getElementById("reverChange").onclick = function(){    //反向变换            imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);            pixelData = imageData.data;            for(var i = 0; i < canvasH*canvasW ; i++){              var r = pixelData[4*i + 0],                g = pixelData[4*i + 1],                b = pixelData[4*i + 2];              pixelData[4*i + 0] = 255 - r;              pixelData[4*i + 1] = 255 - g;              pixelData[4*i + 2] = 255 - b;            }            copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);          }          document.getElementById("blurChange").onclick = function(){    //模糊处理            imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);            pixelData = imageData.data;            var pixelTmpData = pixelData;  //作为一个备份数据            var r = 3 , totalNum = (2*r + 1)*(2*r + 1);  //去上下左右四个方向各3个像素点的平均值            for(var i = r ; i < canvasH - r ; i++){              for(var j = r ; j < canvasW - r; j++){                var totalR,totalG,totalB;                totalR = totalG = totalB = 0;                for(var m = -r ; m <= r ; m++){                  for(var n = -r ; n <= r ; n++){                    var pixeY = i + m , piexX = j + n,                      pixe = canvasW*pixeY + piexX;                    totalR += pixelTmpData[4*pixe + 0];                    totalG += pixelTmpData[4*pixe + 1];                    totalB += pixelTmpData[4*pixe + 2];                  }                }                var p = i*canvasW + j;                pixelData[4*p + 0] = totalR/totalNum;                pixelData[4*p + 1] = totalG/totalNum;                pixelData[4*p + 2] = totalB/totalNum;              }            }            copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);          }          document.getElementById("mosaicChange").onclick = function(){  //马赛克处理            imageData = ctx.getImageData(0 , 0 , canvasW , canvasH);            pixelData = imageData.data;            var pixelTmpData = pixelData;  //作为一个备份数据            var size = 8,total = size*size;            for(var i = 0 ; i < canvasH ; i += size){              for( var j = 0 ; j < canvasW ; j += size){                var totalR,totalG,totalB;                totalR = totalG = totalB = 0;                for(var y = 0 ; y < size ; y++){                  for(var x = 0 ; x < size ; x++){                    var py = i + y,                      px = j + x,                      pixe = px + py*canvasW;                    totalR += pixelTmpData[4*pixe + 0];                    totalG += pixelTmpData[4*pixe + 1];                    totalB += pixelTmpData[4*pixe + 2];                  }                }                var newR = totalR/total,                  newG = totalG/total,                  newB = totalB/total;                for(var dy = 0 ; dy < size ; dy++){                  for(var dx = 0 ; dx < size ; dx++ ){                    var py = i + dy,                      px = j + dx,                      pixe = px + py*canvasW;                    pixelData[4*pixe + 0] = newR;                    pixelData[4*pixe + 1] = newG;                    pixelData[4*pixe + 2] = newB;                  }                }              }            }            copyCtx.putImageData(imageData,0,0,0,0,canvasW,canvasH);          }                  },        handleCanvasMove:function(){    //处理canvans移动          var isCanvasMove = false,            lastX,lastY;          canvas.onmousedown = function(e){            e.preventDefault();            isCanvasMove = true;            lastX = e.clientX - canvas.getBoundingClientRect().left;            lastY = e.clientY - canvas.getBoundingClientRect().top;          }          canvas.onmousemove = function(e){            e.preventDefault();            if(!isCanvasMove || scaleChange.value <= 1) return;            var x = e.clientX - canvas.getBoundingClientRect().left,              y = e.clientY - canvas.getBoundingClientRect().top;            var moveX = (x - lastX),              moveY = (y - lastY);            toolFunc.drawImg(moveX,moveY);            lastX = x;            lastY = y;          }          canvas.onmouseup = function(e){            e.preventDefault();            isCanvasMove = false;          }          canvas.onmouseout = function(e){            e.preventDefault();            isCanvasMove = false;          }        }      };    }  </script></html>

效果图为

用的图片是

 

2、图片放大镜

<!DOCTYPE html><html>  <head>    <meta charset="utf-8">    <title>canvas放大镜</title>    <style type="text/css">      *{        margin: 0;        padding: 0;      }    </style>  </head>  <body>    <canvas id="main" width="800" height="600"       style="display: block;margin: 0 auto;border: 1px solid #AAA;">      亲,您的浏览器不支持canvas    </canvas>    <canvas id="magnify" width="200" height="200" style="display: none;"></canvas>    <script>      var canvas = document.getElementById("main"),        ctx = canvas.getContext("2d"),        canvasW = canvas.width,        canvasH = canvas.height,        magnifyCanvas = document.getElementById("magnify"),        mCtx = magnifyCanvas.getContext("2d"),        magnifyR = 100;      var img = new Image();      img.src = "magnify.jpg";      img.onload = function(){        ctx.drawImage(this , 0 , 0 , canvasW , canvasH);        handleEvent();      }      function handleEvent(){        var isShow = false;        canvas.onmousedown = function(e){          e.preventDefault();          draw(e);        }        canvas.onmouseup = function(e){          e.preventDefault();          draw(e);        }        canvas.onmousemove = function(e){          e.preventDefault();          if(!isShow) return;          draw(e);        }        canvas.onmouseout = function(e){          e.preventDefault();          draw(e);        }                function draw(event){          isShow = (event.type == "mousedown" || event.type == "mousemove");          ctx.clearRect(0 , 0 , canvas.width , canvas.height);          ctx.drawImage(img , 0 , 0 , canvasW , canvasH);          if(!isShow) return;          var x = event.clientX - canvas.getBoundingClientRect().left,            y = event.clientY - canvas.getBoundingClientRect().top;          mCtx.save();          mCtx.lineWidth = 3;          mCtx.strokeStyle = "skyblue";          mCtx.beginPath();          mCtx.arc(100,100,90,0,Math.PI*2);          mCtx.stroke();          mCtx.clip();          mCtx.drawImage(img , 2*x - 90 , 2*y - 90 ,               180 , 180,              0 , 0 , magnifyCanvas.width, magnifyCanvas.height);          mCtx.closePath();          mCtx.restore();          ctx.drawImage(magnifyCanvas, (x-(magnifyCanvas.width/2)) , (y-(magnifyCanvas.height/2)) ,            magnifyCanvas.width , magnifyCanvas.height);        }      }                </script>  </body></html>

用的图片是