canvas基础第二节

一、图形的组合方式

globalAlpha是一个介于0和1之间的值(包括0和1),用于指定所有绘制的透明度。默认值为0。如果所有后续操作都要基于相同的透明度,就可以先把globalAlpha设置为适当值,然后绘制,最后在把它设置回默认值0.

//绘制一个红色的矩形

context.fillStyle="red";

context.fillRect(10,10,50,50);

//修改全局透明度

context.globalAlpha=0.5;

//绘制蓝色矩形

context.fillStyle="blue";

context.fillRect(30,30,50,50);

//重置全局透明度

context.globalAlpha=0;

//这个例子中蓝色矩形会呈现半透明效果,透过它可以看到下面的红色矩形。

globalCompositionOperation表示绘制后的图形怎样与先绘制的图形结合。这个属性的值是字符串,可能的值如下:

source-over(默认值):后绘制的图形位于先绘制的图形上方。

source-in:后绘制的图形与先绘制的图形重叠的部分可见,两者其他部分完全透明。

source-out:后绘制的图形与先绘制的图形不重叠的部分可见,先绘制的图形完全透明。

source-atop:后绘制的图形与先绘制的图形重叠的部分可见,先绘制图形不受影响。

destination-over:后绘制的图形位于先绘制的图形下方,后绘制的图形只有之前透明像素下的部分才可见,被遮挡的部分不可见。

destination-in:后绘制的图形位于先绘制的图形下方,两者不重叠的部分完全透明。就是显示重叠的部分的形状,显示先绘制的图形的颜色。

destination-out:后绘制的图形擦除与先绘制的图形重叠的部分。

destination-atop:后绘制的图形位于先绘制的图形下方,在两者不重叠的地方,先绘制的图形会变透明。

lighter:后绘制的图形与先绘制的图形重叠部分的值相加,使该部分变亮。(叠加的是颜色额)

copy:后绘制的图形完全替代与之重叠的先绘制图形。

xor:后绘制的图形与先绘制的图形重叠的部分执行“异或”操作;图像异或,相异为1,相同为0.即重叠部分不显示,不重叠部分显示。

//画目标图

context.beginPath();

context.fillStyle="red";

context.fillRect(100,50,100,300);

//画源图

context.beginPath();

context.globalCompositeOperation="destination-out";

//context.globalCompositeOperation="xor";

context.fillStyle="blue";

context.arc(250,200,100,0, Math.PI*2);

目标图像:已经放到画布中的绘图

源图像:打算放置到画布中的绘图

在使用globalCompositionOperation的情况下一定要多测一些浏览器,因为不同的浏览器对这个属性的实现仍然存在较大的差别。


二、使用图片

//第一种写法:第一个参数:图片对象;第二个参数是开始画的x坐标;第三个参数:开始画的y的坐标;

//context.drawImage(img,0,0);

//第二种写法:第一个参数:图片对象;第二个参数:是开始画的x坐标;第三个参数:开始画的y的坐标;第四个参数:图片绘制到canvas上的宽度;第五个参数:图片绘制到canvas上的高度;

//context.drawImage(img,0,0,200,200);

//第三种写法(裁剪):第一个参数:图片对象;第二三个参数在原图上要裁剪的起始x、y的坐标;第四、五个参数:在原图上要裁剪的宽和高;第六、七个参数:要放到canvas画布上的起始x、y坐标;第八九个参数:要到canvas画布上的宽和高;

context.drawImage(img,100,100,100,100,50,50,300,300);

var  canvas=document.getElementById("myCanvas");

var   context=canvas.getContext("2d");

var   img= newImage();

img.src="img/20150821130732_anQeR.jpeg";

img.onload=function(){

context.drawImage(img,100,100,100,100,50,50,300,300);

}

综合使用drawImage( )和其他方法,可以对图像进行各种基本操作。而操作的结果可以通过toDataURL( )方法获得。不过有一个例外,即图像不能来自其他域。如果图像来自其它域,调用toDataURL( )会抛出错误。

canvas提供了toDataURL的接口,可以方便的将canvas画布转化成base64编码的image。目前支持的最好的是png格式,jpeg格式的现代浏览器基本也支持,但是支持的不是很好。

//我们创建一个画布,在上面做一些绘图,然后试着把它保存为本地图片。

var  can = document.getElementById('canvas');


var  ctx = can.getContext('2d');

var   imgA = new Image();

imgA.src ='http://www.html5party.com/wp-content

/uploads/2013/09/css_yangshijiance.png';

imgA.onload = function() {

ctx.drawImage(imgA, -25, 0, imgA.width, imgA.height);

ctx.restore();

};

var   imgB = new Image();

imgB.src = 'http://www.html5party.com/wp-content

/uploads/2013/09/canvas_chroma.png';

imgB.onload = function() {

ctx.globalAlpha = 0.1

ctx.drawImage(imgB, -100, -75, imgB.width, imgB.height);

ctx.restore();

};

function toImage(returnType) {

var dataURL = document.getElementById('canvas').toDataURL("image/png");

// The returnType argument specifies how to get the

// the image.  'obj' will set the source to an image element.

// 'window' will open a new window and display the image.

// 'download' will prompt the user to save the image.

switch(returnType) {

case 'obj':

var imgObj = new Image();

imgObj.src = dataURL;

document.getElementById('graphics').appendChild(imgObj);

break;

case 'window':

window.open(dataURL, "Canvas Image");

break;

case 'download':

dataURL = dataURL.replace("image/png", "image/octet-stream");

document.location.href = dataURL;

break;

}

}

理想的状态是页面上有三个点击链接:

1、Image Tag

点击会有一张图片插入在网页中。

2、New Window

打开一个新的窗口,并显示一个PNG格式的图片

3、Download

下载保存一张PNG个格式的图片

很不幸,点击并没有反映,为什么呢?笔者做了许多试验,原因出在图片渲染上,canvas上如果添加图片,toDataURL()将失效,获取不到canvas信息。通过简单几步来验证这个问题。

把js脚本中图片渲染的部分去除,A和B图。为了便于观察,在画布上画一个简单的矩形,填充颜色:

ctx.fillStyle = 'Red';

ctx.strokeStyle = 'Green';

ctx.beginPath();

ctx.rect(20, 20, 100, 100);

ctx.stroke();

ctx.fill();

这样画布上便显示为一个红色矩形,格式为PNG



三、裁剪

var  canvas=document.getElementById("myCanvas");

var  context=canvas.getContext("2d");

//绘制一个三角形

context.beginPath();

context.moveTo(200,200);

context.lineTo(250,200);

context.lineTo(225,150);

context.closePath();

context.stroke();

//调用裁剪

context.clip();

var  img= newImage();

img.src="img/20150821130732_anQeR.jpeg";

img.onload=function() {

context.drawImage(img,0,0);

}

//你上面画的是什么形状,裁剪出来的就是什么形状


四、使用图像数据

var  canvas=document.getElementById("myCanvas");

var   context=canvas.getContext("2d");

//getImageData()取的原始图像数据

//有四个参数:第一二个参数,开始获取像素的x,y坐标,第三四个参数,获取像素点的宽高。

//var  ImageData=context.getImageData(0,0, img.width, img.height);

这里返回的对象是getImageData()的实例,每个getImageData()对象都有三个属性:width、height、data。

width和height表示访问像素区域大小

//其中data属性是一个数组,保存着图像中每一个像素的数据。

//在data数据中,每一个像素用4个元素来保存,分别代表红、绿、蓝和透明度。

//数组中的每个元素都是介于0和255之间的,能够直接访问到原始图像数据,

//就能够以各种方式来操作这些数据。

var  img= newImage();

img.src="img/20150821130732_anQeR.jpeg";

img.onload=function() {

context.drawImage(img,0,0);

var   ImageData=context.getImageData(0,0, img.width, img.height);

var   data=ImageData.data;

//注意:每次循环控制变量i都递增4,在取得每个像素的红、绿、蓝颜色值后,

//计算出他们的平均值,再把这个平均值设置为每个颜色的值,

//结果就是去掉了每个像素的颜色,只保留了亮度接近的灰度值.(用彩色变黑白)

for(var i=0; i<data.length; i+=4){

var  r=data[i];

var  g=data[i+1];

var  b=data[i+2];

//求rgb的平均值,

var  gray=(r+g+b)/2;

//设置颜色值

data[i]=gray;

data[i+1]=gray;

data[i+2]=gray;

}

//putImageData()方法把图像数据绘制到画布上,有三个参数

//第一个参数,获取ImageData,第二三个参数,要放到画布上的x,y坐标

context.putImageData(ImageData,0,0);

}


五、canvas视频处理

function animation( ){

//video.ended 属性返回音频/视频是否已结束。返回值:布尔值true|false。如果播放已结束,则返回 true。否则返回 false。

if(!video.ended){

//将视频的每一帧,绘制在canvas上

context.drawImage(video,0,0,canvas.width,canvas.height);

window.requestAnimationFrame(animate);

}

}

//当视频可以播放时,进行播放调用循环

//video的oncanplay事件类似于图像的onload,加载完成之后

//oncanplay 事件在用户可以开始播放视频/音频(audio/video)时触发。

//object.oncanplay=function(){myScript};

//object.addEventListener("canplay",myScript);

video.oncanplay=function(e){

video.play( );

window.requestAnimationFrame(animate);

}


六、canvas动画

最原始的你还可以使用window.setTimout()或者window.setInterval()通过不断更新元素的状态位置等来实现动画,前提是画面的更新频率要达到每秒60次才能让肉眼看到流畅的动画效果。

window.requestAnimationFrame()通过递归调用同一方法来不断更新画面以达到动起来的效果,但它优于setTimeout/setInterval的地方在于它是由浏览器专门为动画提供的API,在运行时浏览器会自动优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了CPU开销。

取消该次动画:可以直接调用,也可以通过window来调用,接收一个函数作为回调,返回一个ID值,通过把这个ID值传给window.cancelAnimationFrame()可以取消该次动画。

window.requestAnimationFrame()方法用于告诉浏览器,你想在浏览器的下个重绘 之前来执行一个动画或者执行浏览器通过调用一个特定的函数来更新动画的请求。该方法会在下次重回之前执行一个作为参数的回调函数。

window.requestAnimationFrame 是专门为实现高性能的帧动画而设计的一个API,目前已在多个浏览器得到了支持,包括IE10+,Firefox,Chrome,Safari,Opera等,在移动设备上,ios6以上版本以及IE mobile 10以上也支持requestAnimationFrame,唯一比较遗憾的是目前安卓上的原生浏览器并不支持requestAnimationFrame,不过对requestAnimationFrame的支持应该是大势所趋了,安卓版本的chrome 16+也是支持requestAnimationFrame的。

例子window.requestAnimationFrame = window.requestAnimationFrame || window.mozRequestAnimationFrame ||window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;


七、实现多个小球随机运动,用面向对象的方法

var   canvas=document.getElementById("myCanvas");

var   context=canvas.getContext("2d");

//圆是一个类,就是对象只有一个,就是圆

functionCircle(x,y,r,speedX,speedY,color) {

//所有的属性

this.r=r;

this.x=x;

this.speedX=speedX;

this.speedY=speedY;

this.y=y;

this.color=color;

}

//在原型上写方法,

//第一个方法,画圆

Circle.prototype.draw=function() {

context.beginPath();

context.fillStyle=this.color;

context.arc(this.x, this.y, this.r,0, Math.PI*2);

context.fill();

}

//第二个方法,运动

Circle.prototype.move=function() {

//这里改变x递加的值,可以改变运动速度

this.x+=this.speedX;

this.y+=this.speedY;

if(this.x>=canvas.width-this.r||this.x<=this.r) {

this.speedX*= -1;

}

if(this.y>=canvas.height-this.r||this.y<=this.r) {

this.speedY*= -1;

}

}

//进行实例化操作

//实现同时出现多个小球,需要同时实例化出多个对象

//储存new出来的实例化对象数组

var   arr=[ ];

//来很多个小球

for(var  i=0; i<100; i++) {

//设置一个随机的半径

var   R=randomNum(30,5);

//随机位置

var   X=randomNum(canvas.width-R, R);

var    Y=randomNum(canvas.height-R, R);

//随机速度

var   speedX=randomNum(8,1);

var    speedY=randomNum(8,1);

//随机颜色

var     COLOR="rgb("+randomNum(255,0)+","+randomNum(255,0)+","+randomNum(255,0)+")";

//将对像实例化

var    newCircle= newCircle(X, Y, R, speedX, speedY, COLOR);

arr.push(newCircle)

}

moveCircle();

//定义一个执行动画的函数

function    moveCircle() {

//先清理画布

context.clearRect(0,0, canvas.width, canvas.height);

//循环执行实例化对象的数组

for(var  i=0; i<arr.length;i++){

arr[i].draw();

arr[i].move();

}

//执行动画

window.requestAnimationFrame(moveCircle);

}

//定义一个随机数的函数

functionrandomNum(max,min) {

returnparseInt(Math.random()*(max-min+1)+min);

}


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

推荐阅读更多精彩内容

  • 一:canvas简介 1.1什么是canvas? ①:canvas是HTML5提供的一种新标签 ②:HTML5 ...
    GreenHand1阅读 4,661评论 2 32
  • 一、canvas简介 1.1 什么是canvas?(了解) 是HTML5提供的一种新标签 Canvas是一个矩形区...
    J_L_L阅读 1,492评论 0 4
  • 一、canvas简介 1.1 什么是canvas?(了解) 是HTML5提供的一种新标签 Canvas是一个矩形区...
    Looog阅读 3,936评论 3 40
  • 啥是canvas? HTML5 标签用于绘制图像(通过脚本,通常是 JavaScript)。不过, 元素本身...
    kiaizi阅读 760评论 0 4
  • 最基本的使用创建一个画布所有的操作都在画布的context上面canvas是基于状态而不是基于对象的,比如说颜色都...
    亲爱的孟良阅读 1,647评论 0 4