canvas总结

什么是canvas

HTML5 <canvas> 元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成.
<canvas> 标签只是图形容器,您必须使用脚本来绘制图形。

创建一个canvas

一个画布在网页中是一个矩形框,通过 <canvas> 元素来绘制.
注意: 默认情况下 <canvas> 元素没有边框和内容。你也可以添加。

使用如下代码,你就在页面中创建出来一个宽200px、高100px的canvas,如果没有指定宽高,canvas的默认宽高为300px * 150px,通常我们需要给canvas一个id以便在脚本中引用。

<canvas id="myCanvas" width="200" height="100"></canvas>

我们也可以动态创建canvas,使用一下代码,我们在页面中创建出了一个id为layer的canvas,指定了其宽高。

var canvas = document.createElement('canvas');
canvas.id = "layer";
canvas.width = 200;
canvas.height = 100;
document.body.appendChild(canvas);

canvas操作

我们可以使用canvas绘制线条、矩形、圆形、文本、图像,可以对图形、文本进行颜色填充以及渐变填充。详细内容可查看基础教程,其中我们用到的比较多的应该是绘制图像,绘制图像会在下面专门讲解。

canvas属性中的宽高和css中宽高的区别

我们先看一个例子
我们使用属性中的宽高创建一个canvas,其宽高为300px,我们在其中画一条线,从(0,0)点到(300,300)点。我们可以看出该图显示正常不会被拉伸。

<canvas id="layer" width="300" height="300">浏览器不支持Canvas,请升级或改用其它浏览器!</canvas>
<script type="text/javascript">
    var canvas = document.getElementById("layer"),
    ctx = canvas.getContext('2d');
    ctx.moveTo(0,0);
    ctx.lineTo(300,300);
    ctx.stroke();
</script>
属性宽高

接着我们给canvas设置一下style中宽高

 #layer {
       width: 150px;
       height: 300px;
}

效果如下,使用style时图像会被拉伸(变形)


设置style

这是什么原因???我们需要搞清楚两个概念:
1.画布的宽和高(ps新建画布的宽和高);
2.画布所在画板的宽和高(例如ps打开后的窗口);

默认的画板、画布的宽和高是属性中设置的宽高(例子中即为300*300)。但在画布上设置style属性的话,相当于把画板的宽和高改变了,而画布的宽和高还是默认值,所以 画布会出现拉伸的情况,此例中设置的画板的宽150和高300,相当于将画布的宽度缩小一倍,所以实际上画出来的是黑色的那条。 直接设置宽和高相当于是同时修改了画板和画布的宽和高(两者一致),所以在画布上画的图形不会出现拉伸(如红色那条线)。

image.png

canvas绘制图像

绘制图像主要使用的是drawImage方法
drawImage() 方法在画布上绘制图像、画布或视频。
drawImage() 方法也能够绘制图像的某些部分,以及/或者增加或减少图像的尺寸。
语法:
1.在画布上定义图像:
context.drawImage(img,x,y);
2.在画布上定位图像,并规定图像的宽度和高度:
context.drawImage(img,x,y,width,height);
3.剪切图像,并在画布上定位被剪切的部分:
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

参数值:

参数 描述
img 规定要使用的图像、画布或视频。
sx 可选。开始剪切的 x 坐标位置。
sy 可选。开始剪切的 y 坐标位置。
swidth 可选。被剪切图像的宽度。
sheight 可选。被剪切图像的高度。
x 在画布上放置图像的 x 坐标位置。
y 在画布上放置图像的 y 坐标位置。
width 可选。要使用的图像的宽度。(伸展或缩小图像)
height 可选。要使用的图像的高度。(伸展或缩小图像)

以上基础内容查看w3c教程

绘制图像中的填坑

1.绘制图像时,canvas中没有图像

var drawimg = document.getElementById("drawimg");
var image=document.getElementById("image");
var context = drawimg.getContext("2d");
context.drawImage(image,10,10); 

原因是图片是异步加载,在之前的代码中,执行js代码的时候图片有可能还没有加载成功,就调用了drawImage()方法,所以图片就无法显示。所以在使用drawImage()方法时,务必保证所绘图像已经加载好了。通常我们会将其放在图片加载onload回调函数中确保这一点。

image.onload=function(){
   context.drawImage(devBgImg,imgX,imgY,imgWidth,imgHeight);
};

//例子
var img = new Image();
img.src ='devmonitor/res/main.jpg'; 
img.onload=function(){
ctx.drawImage(img,0,0,img.width,img.height,imgX,imgY,
      canvas.width*imgScale,canvas.height*imgScale);
};

canvas像素操作

语法
context.getImageData(x,y,width,height);

参数 描述
x 开始复制的左上角位置的 x 坐标。
y 开始复制的左上角位置的 y 坐标。
width 将要复制的矩形区域的宽度
height 将要复制的矩形区域的高度

getImageData() 方法返回 ImageData 对象,该对象拷贝了画布指定矩形的像素数据。

ImageData对象中存储着canvas对象真实的像素数据,它包含以下几个只读属性:

width
无符号长整型(unsigned long),使用像素描述 ImageData 的实际宽度。
height
无符号长整型(unsigned long),使用像素描述 ImageData 的实际高度。
data
Uint8ClampedArray类型的一维数组,包含着RGBA格式的整型数据,范围在0至255之间(包括255)。

imageData.data;
一维数组,存储了从canvas中获取的每个像素的RGBA值。该数组为每个像素点保存了四个值——红、绿、蓝和alpha透明度。
imageData.data并不是一个真正的数组,而是一个类数组的对象-------Uint8ClampedArray,data是个一维数组!data的元素始终依次是red,green,blue,alpha,red,green,blue。。。一直重复到最后一个。所以,data的length始终是像素个数*4.而在循环data的时候,也是以4为步长。

imageData.data图示
综合例子我们可以对canvas中像素进行操作
翻转颜色
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById("tulip");
ctx.drawImage(img,0,0);
var imgData=ctx.getImageData(0,0,c.width,c.height);
// 反转颜色(步长为4)
for (var i=0;i<imgData.data.length;i+=4)
  {
  imgData.data[i]=255-imgData.data[i];
  imgData.data[i+1]=255-imgData.data[i+1];
  imgData.data[i+2]=255-imgData.data[i+2];
  imgData.data[i+3]=255;
  }
ctx.putImageData(imgData,0,0);
灰度处理

例子中仅仅是用红绿和蓝的平均值。你也可以用加权平均,例如x = 0.299r + 0.587g + 0.114b这个公式。

var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById("tulip");
ctx.drawImage(img,0,0);
var imgData=ctx.getImageData(0,0,c.width,c.height);
// 反转颜色(步长为4)
for (var i=0;i<imgData.data.length;i+=4)
  {
      var avg = (data[i] + data[i +1] + data[i +2]) / 3;
      data[i]     = avg; // red
      data[i + 1] = avg; // green
      data[i + 2] = avg; // blue
  }
ctx.putImageData(imgData,0,0);
颜色选择器:
//创建image对象
var img = new Image();
img.src = 'haorooms.jpg';
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
//img加载完成后画到canvas上
img.onload = function() {
  ctx.drawImage(img, 0, 0);
  img.style.display = 'none';
};
//获取颜色RGBA值的函数
function pick(event) {
  //layerX和layerY属性表示Canvas内部坐标系中的坐标
  var x = event.layerX;
  var y = event.layerY;
  var pixel = ctx.getImageData(x, y, 1, 1);
  var data = pixel.data;
  console.log(data);
  //获取到RGBA值的字符串
  var rgba = 'rgba(' + data[0] + ',' + data[1] +
             ',' + data[2] + ',' + (data[3] / 255) + ')';
  //自定义操作例如将字符串显示在某dom上或者return返回值等
  //
}
//为canvas绑定mousemove事件
canvas.addEventListener('mousemove', pick);

这篇文章中有对像素操作的多个应用介绍

canvas和图片相互转换

//此处image应确保加载完成
function convertImageToCanvas(image) {
    var canvas = document.createElement("canvas");
    canvas.width = image.width;
    canvas.height = image.height;
    canvas.getContext("2d").drawImage(image, 0, 0);
    return canvas;
}
// Converts canvas to an image
function convertCanvasToImage(canvas) {
    var image = new Image();
    image.src = canvas.toDataURL("image/png");
    return image;
}

更新中.......
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容

  • 1 Canvas接口元素定义 1.1 getContext()方法 为了在canvas上绘制,你必须先得到一个画布...
    Kevin_Junbaozi阅读 1,301评论 1 2
  • 一、简介 HTML5 中的定义:“它是依赖分辨率的位图画布,你可以在 canvas 上面绘制任何图形,甚至加载照片...
    destiny0904阅读 10,529评论 1 4
  •   HTML5 添加的最受欢迎的功能就是 元素。这个元素负责在页面中设定一个区域,然后就可以通过 JavaScri...
    霜天晓阅读 3,006评论 0 2
  • 一:canvas简介 1.1什么是canvas? ①:canvas是HTML5提供的一种新标签 ②:HTML5 ...
    GreenHand1阅读 4,676评论 2 32
  • 一、图形的组合方式 globalAlpha是一个介于0和1之间的值(包括0和1),用于指定所有绘制的透明度。默认值...
    空谷悠阅读 1,267评论 0 0