canvas学习之API整理笔记(一)


Posted in Javascript onDecember 29, 2016

其实canvas本身很简单,就是去学习它的API,多看实例,多自己动手练习,多总结。但是canvas的API实在是有点多,对于初学者来说,可能学到一半就止步不前了。我也有这种感觉,在学习的过程中,编写实例,用到了其中很多的属性和方法,但是回头来看的时候总觉得什么也没用。所以决定系统性的记录一下它常用到的API,方便以后查阅,也顺便造福一下大家。

开始之前

假设html代码中有一个canvas标签:

<canvas id="canvas">你的浏览器不支持canvas!</canvas>

如果你的浏览器是IE8及以下,那么很遗憾,上面那段文字会被渲染出来!而且下面的方法也都不能使用了;所以请使用支持canvas的浏览器来使用后面的方法。

//获取canvas容器
var can = document.getElementById(‘canvas');
//创建一个画布
var ctx = can.getContext(‘2d');

另外我们可以还可以得到容器的宽和高度

var canWid = can.width; //canvas 的宽度
var canHei = can.height; //canvas 的高度

canvas只是一个容器,本身没有绘制的能力,所以我们要得到一个画布ctx,使之具有绘制各种图形的能力。下文所有的方法都是ctx的方法。

绘制

绘制一个矩形:

//填充矩形(x, y是横纵坐标,原点在canvas的左上角)
ctx.fillRect(x, y, width, height);
//边框矩形,默认1px 黑色。 
ctx.strokeRect(x, y, width, height);
//清除指定的矩形区域,变为透明
ctx.clearRect(x, y, width, height); //绘制动态效果时,常用来清除整个画布

绘制路径:

//新建路径,beginPath是绘制新图形的开始
ctx.beginPath()
//路径(线)的起点,一般在上面这条命令后执行
ctx.moveTo(x, y) 
//线的终点
ctx.lineTo(x, y) 
//绘制圆形
ctx.arc(x, y, r, start, end, true/false) //x, y圆心,r半径,start和end是开始和结束角度,false表示顺时针(默认),true表示逆时针。
//绘制弧线
ctx.arcTo(x1, y1, x2, y2, r); //当前端点、(x1,y1)和(x2,y2)这三个点连成的弧线,r是半径。
//闭合路径,不是必须的,如果线的终点跟起点一样,会自动闭合。
ctx.closePath()
//通过线条绘制轮廓(边框)
ctx.stroke() 
//通过路径填充区域(实心)
ctx.fill()

说明:

  1. fill()和stroke()函数表示绘图结束。如果要继续绘制,需要重新新建路径(beginPath())。
  2. 如果lineTo()最后的路径没有封闭,fill()函数会自动封闭路径,而stroke()函数不会。

例:绘制一个三角形

ctx.beginPath();
ctx.moveTo(75, 50); //路径起点
ctx.lineTo(100, 75);
ctx.lineTo(100, 25);
ctx.fill(); //自动将路径闭合,并默认填充黑色。

样式

颜色

ctx.fillStyle = 'red' //针对fill()有效的颜色,还可以取值:'#fff'、'rgba(0, 0, 0, 0.5)'等。
ctx.strokeStyle = 'red' //针对stroke()有效的颜色,取值同上。
ctx.globalAlpha = 0.5; //透明度

线段端点

ctx.lineWidth = 2; //线条宽度
ctx.lineCap = 'butt(默认)'、'round(圆弧)'、'square(方形)' //线段端点显示的样式
var ctx = document.getElementById('canvas').getContext('2d');
var lineCap = ['butt','round','square'];
ctx.strokeStyle = 'black';
for (var i=0;i<lineCap.length;i++){
 ctx.lineWidth = 15;
 ctx.lineCap = lineCap[i];
 ctx.beginPath();
 ctx.moveTo(25+i*50,10);
 ctx.lineTo(25+i*50,140);
 ctx.stroke();
}

效果如下图:

canvas学习之API整理笔记(一)

线段连接处

ctx.lineJoin = 'miter(默认)'、round(圆角)、`bevel(横线)`   //两线段连接处所显示的样子

var ctx = document.getElementById('canvas').getContext('2d');
var lineJoin = ['round','bevel','miter'];
ctx.lineWidth = 10;
for (var i=0;i<lineJoin.length;i++){
 ctx.lineJoin = lineJoin[i];
 ctx.beginPath();
 ctx.moveTo(10,50+i*40);
 ctx.lineTo(50,10+i*40);
 ctx.lineTo(90,50+i*40);
 ctx.lineTo(130,10+i*40);
 ctx.lineTo(170,50+i*40);
 ctx.stroke();
}

效果如下图:

canvas学习之API整理笔记(一)

虚线

ctx.setLineDash([4, 2]) //设置虚线,参数为数组,第一个值为实现宽度,第二个值为空白的宽度
ctx.lineDashOffset = 0; //虚线起始偏移量
var can = document.getElementById('canvas');
var ctx = can.getContext('2d');
var offset = 0;
function draw() {
 offset++; 
 if (offset > 16) { 
 offset = 0; 
 }
 ctx.clearRect(0,0, can.width, can.height); 
 ctx.setLineDash([6, 2]); 
 ctx.lineDashOffset = -offset; 
 ctx.strokeRect(10,10, 100, 100);
}
setInterval(draw, 20);

效果如下图:

canvas学习之API整理笔记(一)

渐变

var bg = ctx.createLinearGradient(x1, y1, x2, y2); //定义线性渐变,渐变的起点 (x1,y1) 与终点 (x2,y2)。
var bg1 = ctx.createRadialGradient(50, 50, 0, 50, 50, 100); //定义径向渐变
bg.addColorStop(0, 'red'); //定义好,之后开始上色
bg.addColorStop(0.5, 'blue');
bg.addColorStop(1, 'rgba(0, 0, 0, 0.6)');
var bg = ctx.createLinearGradient(0, 0, 0, 200); //线性渐变
bg.addColorStop(0, 'black');
bg.addColorStop(0.6, '#fff');
ctx.fillStyle = bg;
ctx.fillRect(10, 10, 100, 100);

效果如下图:

canvas学习之API整理笔记(一)

var bg1 = ctx.createRadialGradient(100, 100, 0, 100, 100, 50); //径向渐变
bg1.addColorStop(0, '#FF5F98');
bg1.addColorStop(0.75, '#FF0188');
bg1.addColorStop(1, 'rgba(255,1,136,0)');
ctx.fillStyle = bg1;
ctx.fillRect(0,0,150,150);

效果如下图:

canvas学习之API整理笔记(一)

文字

var ctx = document.getElementById('canvas').getContext('2d');
ctx.shadowOffsetX = 2; //X轴阴影距离,负值表示往上,正值表示往下
ctx.shadowOffsetY = 2; //Y轴阴影距离,负值表示往左,正值表示往右
ctx.shadowBlur = 2; //阴影的模糊程度
ctx.shadowColor = "rgba(0, 0, 0, 0.5)"; //阴影颜色
ctx.font = "30px Times New Roman"; //设置字体和字体大小
ctx.fillStyle = "Black";
ctx.fillText("Sample String", 15, 30); //实体文字
ctx.strokeStyle = 'red';
ctx.strokeText('Hello world', 15, 100); //边框文字

效果如下图:

canvas学习之API整理笔记(一)

文字的属性出了上面的列出的以外,还有以下一些属性:

ctx.font = '20px Times New Roman';
ctx.textAlign = 'center'; //start, end, left, right or center
ctx.textBaseline = 'middle' //top, hanging, middle, alphabetic, ideographic, bottom
ctx.direction = 'inherit' //ltr, rtl, inherit

图像

var img = new Image();
img.src= './images/background.jpg';
ctx.drawImage(img, 0, 0); //img为图像,(0, 0)为起始坐标

这里的img可以是一个img对象,也可以是一个img元素。

<img id="img" src="./images/background.jpg" style="display:none;">
ctx.drawImage(document.getElementById('img'), 0, 0);

另外,绘制图片的时候还可以对图片进行缩放,类似于css中的background-size:

ctx.drawImage(img, 0, 0, w, h);   //w、h指定图片的宽高,则会同比例缩放。

变形

慢慢的从这里开始,就要开始涉及到复杂的绘制了。而开始复杂的绘制之前,我们得先了解一个概念:canvas绘图的状态。

状态

canvas 的状态就是当前画面应用的所有样式和变形的一个快照。另外,用来操作这个状态的有两个方法:save()和restore()。

save()用来保存当前状态,restore()用来恢复刚才保存的状态。他们都可以多次调用。

ctx.fillStyle = 'black';
ctx.fillRect(20, 20, 150, 150);
ctx.save(); //保存当前状态
ctx.fillStyle= '#fff';
ctx.fillRect(45, 45, 100, 100);
ctx.restore(); //恢复到刚才保存的状态
ctx.fillRect(70, 70, 50, 50);

效果如下图:

canvas学习之API整理笔记(一)

位移(translate)

ctx.translate(x, y);   //更改canvas的原点

var ctx = document.getElementById('canvas').getContext('2d');
for(var i = 1; i< 4; i++) {
 ctx.save(); //使用save方法保存状态,让每次位移时都针对(0,0)移动。
 ctx.translate(100*i, 0);
 ctx.fillRect(0, 50, 50, 50);
 ctx.restore();
}

效果如下图:

canvas学习之API整理笔记(一)

旋转

ctx.rotate(Math.PI * 2)     //参照原点顺时针旋转360度

ctx.translate(75,75); //把原点移动到(75, 75);
for (var i=1; i<6; i++){ // 从里到外一共6圈
 ctx.save();
 ctx.fillStyle = 'rgb('+(50*i)+','+(255-50*i)+',255)';
 for (var j=0; j<i*6; j++){ // 每一圈有i*6个圆点
 ctx.rotate(Math.PI*2/(i*6));
 ctx.beginPath();
 ctx.arc(0,i*12.5,5,0,Math.PI*2,true);
 ctx.fill();
 }
 ctx.restore();
}

效果如下图:

canvas学习之API整理笔记(一)

缩放

ctx.scale(x, y);     //基于原点缩放,x、y是两个轴的缩放倍数

var ctx = document.getElementById('canvas').getContext('2d');
ctx.fillStyle = 'red';
ctx.scale(0.8, 1.2);
ctx.beginPath();
ctx.arc(75, 75, 60, 0, Math.PI * 2);
ctx.fill();

本来绘制的是一个半径为60的圆形,但是经过缩放之后,实际效果如下:

canvas学习之API整理笔记(一)

动画

元素的位置移动,就形成了动画。

一帧一帧的来渲染这个元素,而且这个元素每一帧的位置都不一样,我们的眼睛看到的就是动画了。实现起来也很方便,js提供了两个方法:setTimeout 和setInterval都可以实现,但是一个有逼格的程序员实现动画是不会用这两个方法的,而是用requestAnimationFrame这个方法。有什么区别呢?下面简单做个比较。

  • setInterval(myFun, 10); 意思是隔一毫秒执行一个myFun函数,但是这样就有一个问题了,比如我myFun函数里面绘制的东西比较耗时,而10ms之内还没有完全绘制出来,但是这段代码强制1ms之后又开始绘制下一帧了,所以就会出现丢帧的问题;反之,如果时间设置太长,就会出现画面不流畅、视觉卡顿的问题。
  • requestAnimationFrame(myFun); 如果我们这样写,又是什么意思呢?意思是根据一定的时间间隔,会自动执行myFun函数来进行绘制。这个”一定的时间间隔”就是根据浏览器的性能或者网速快慢来决定了,总之,它会保证你绘制完这一帧,才会绘制下一帧,保证性能的同时,也保证动画的流畅。

结语

这些API已经包含了大部分常用的了,结合requestAnimationFrame函数已经可以绘制很多酷炫的效果了。但是光看这些API很简单,但是想要在绘制游戏或者动画中用起来得心应手还需要看大量的实例,自己实践总结的。

本文就到这里,感谢各位看官~

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
js中split函数的使用方法说明
Dec 26 Javascript
使用JS或jQuery模拟鼠标点击a标签事件代码
Mar 10 Javascript
Javascript实现颜色rgb与16进制转换的方法
Apr 18 Javascript
javascript实现根据3原色制作颜色选择器的方法
Jul 17 Javascript
jquery插件jquery.nicescroll实现图片无滚动条左右拖拽的方法
Aug 10 Javascript
jQuery手指滑动轮播效果
Dec 22 Javascript
JavaScript实现构造json数组的方法分析
Aug 17 Javascript
小试小程序云开发(小结)
Jun 06 Javascript
vue 使用鼠标滚动加载数据的例子
Oct 31 Javascript
原生js实现购物车功能
Sep 23 Javascript
微信小程序视频弹幕发送功能的实现
Dec 28 Javascript
JS实现刷新网页后之前浏览位置保持不变示例详解
Aug 14 Javascript
Javascript Function.prototype.bind详细分析
Dec 29 #Javascript
jQuery自定义插件详解及实例代码
Dec 29 #Javascript
canvas快速绘制圆形、三角形、矩形、多边形方法介绍
Dec 29 #Javascript
JavaScript获取短信验证码(周期性)
Dec 29 #Javascript
JavaScript实现同一个页面打开多张图片
Dec 29 #Javascript
Javascript 对cookie操作详解及实例
Dec 29 #Javascript
前端 Vue.js 和 MVVM 详细介绍
Dec 29 #Javascript
You might like
一个很不错的PHP翻页类
2009/06/01 PHP
浅析php fwrite写入txt文件的时候用 \r\n不能换行的问题
2013/08/06 PHP
php中smarty区域循环的方法
2015/06/11 PHP
PHP内置加密函数详解
2016/11/20 PHP
JS 动态获取节点代码innerHTML分析 [IE,FF]
2009/11/30 Javascript
javascript中运用闭包和自执行函数解决大量的全局变量问题
2010/12/30 Javascript
最佳JS代码编写的14条技巧
2011/01/09 Javascript
Javascript图像处理—平滑处理实现原理
2012/12/28 Javascript
浅析Javascript中“==”与“===”的区别
2014/12/23 Javascript
jquery中EasyUI使用技巧小结
2015/02/10 Javascript
jQuery实现图片左右滚动特效
2020/04/20 Javascript
jquery对复选框(checkbox)的操作汇总
2016/01/13 Javascript
JS获取当前页面名称的简单实例
2016/08/19 Javascript
Angular2 环境配置详细介绍
2016/09/21 Javascript
ThinkJS中如何使用MongoDB的CURD操作
2016/12/13 Javascript
Vue插件写、用详解(附demo)
2017/03/20 Javascript
详解Windows下安装Nodejs步骤
2017/05/18 NodeJs
实例详解JavaScript中setTimeout函数的执行顺序
2017/07/12 Javascript
JS二级菜单不同实现方法分析【4种方法】
2018/12/21 Javascript
Webpack中loader打包各种文件的方法实例
2019/09/03 Javascript
vue实现列表滚动的过渡动画
2020/06/29 Javascript
深入解析Python中的变量和赋值运算符
2015/10/12 Python
python实现kMeans算法
2017/12/21 Python
详解tensorflow训练自己的数据集实现CNN图像分类
2018/02/07 Python
python程序快速缩进多行代码方法总结
2019/06/23 Python
pandas的连接函数concat()函数的具体使用方法
2019/07/09 Python
Python 实现遥感影像波段组合的示例代码
2019/08/04 Python
django日志默认打印request请求信息的方法示例
2020/05/17 Python
HTML5 Canvas实现平移/放缩/旋转deom示例(附截图)
2013/07/04 HTML / CSS
Sephora丝芙兰菲律宾官方网站:购买化妆品和护肤品
2017/04/05 全球购物
TripAdvisor斯洛伐克:阅读评论、比较价格和酒店预订
2018/04/25 全球购物
WWE美国职业摔角官方商店:WWE Shop
2018/11/15 全球购物
在职证明书模板
2015/06/15 职场文书
孩子满月酒答谢词
2015/09/30 职场文书
python实现语音常用度量方法的代码详解
2021/05/25 Python
TS 类型收窄教程示例详解
2022/09/23 Javascript