前段时间在公司没什么事干,研究了一下canvas,在实际开发中还没正式应用过,但是已经深深感觉到其魅力之处。下面写一写我认为canvas中比较重要的点,如有理解错误,欢迎指正。

首先canvas是h5中的新增一个元素,先创建一个h5文件,然后像写一个div一样,在页面初始化一个canvas,由于之后canvas的操作都是由js完成,为了操作方便,赋予canvas一个id值,给width和height作为canvas的宽高。话不多说,上代码先

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<canvas id="drawing" width="200" height="200"> A draw of something</canvas>
<script>
var drawing = document.getElementById('drawing'); //确定浏览器支持canvas元素
if(drawing.getContext) {
var context = drawing.getContext("2d");
}
</script>
</body>
</html>

  上面就是初始化一个包含canvas元素的最基础写法啦,然后我们就要动手画了。

  canvas画图我给分为了两种,一种是canvas自身创建,另外一种就是canvas中引用了img,先说canvas自身创建。canvas自身创建方式首先有两种,一种是描边即stroke,另外一种是填充fill,两种方式均可以定义使用的样式,包括描边或填充的色值、效果(如渐变)等;另外canvas自身创建可以使用canvas提供的现有的图形矩形和弧形也可以通过定义路径来形成图形。比较规则的直线或可以通过lineTo()方法,不规则的曲线可以通过贝塞尔曲线来完成。

  下面讲一下绘制图形过程中,比较重要的几个概念。

  1.beginPath()

beginPath()即开始或重置一条路径,我们在实际应用中,会经常用到。我们在单纯使用arc或rect相关方法,并不涉及到路径时可以不用beginPath(),但是当我们使用如lineTo(),贝塞尔曲线等这种使用路径的方法绘制图形时,则必须要使用beginPath();当然了,有beginPath(),就有closePath();如果我们使用的是stroke()方法,调用了beginPah(),就要相应地调用closePath()才可以把路径闭合,比如绘制下面一个三角形

 <!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>canvas小试牛刀</title>
<style>
canvas { border: 1px solid black; }
</style>
</head>
<body onload = "draw();">
<canvas id="tutorial" width="450" height="250"></canvas>
<script>
function draw(){
var canvas = document.getElementById('tutorial'); if(canvas.getContext) {
var ctx = canvas.getContext('2d'); // 绘制一个三角形
ctx.beginPath();
ctx.moveTo(50, 50);
ctx.lineTo(100, 50);
ctx.lineTo(75, 100);
// ctx.fillStyle = "rgba(0,0,255,0.2)";
ctx.closePath();//闭合路径
ctx.stroke();//默认描边的颜色是黑色
}
} </script>
</body>
</html>

当前代码运行完毕之后的效果是这样的

如果我们去掉closePath(),效果是这样

因为我们在代码中实际只绘制了两条直线,closePath()帮我们把最后一个点连接到起点以达到闭合路径的作用,当然,也可以不调用closePath(),选择自行写代码闭合也是完全可以的。而当我们把closePath()和stroke()分别注掉,把fillStyle()放出来,再加上ctx.fill(),效果是这样的

所以在使用填充的时候closePath()就没什么卵用了,使用填充的时候,会自动闭合路径,另外友情提示一下,虽然是自动闭合,但是所谓自动闭合就是最后一个点与起点的连线,所以说,如果你的图形是曲线或是不规则的还是自己闭合吧

2关于moveTo与translate()

moveTo()是把坐标移动到某一点,其主要作用是避免出现不必要的线,嗯,来个例子吧,比较直观一点

 <!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>canvas小试牛刀</title>
<style>
canvas { border: 1px solid black; }
</style>
</head>
<body onload = "draw();">
<canvas id="tutorial" width="450" height="250"></canvas>
<script>
function draw(){
var canvas = document.getElementById('tutorial'); if(canvas.getContext) {
var ctx = canvas.getContext('2d'); // 绘制一个笑脸
ctx.beginPath();
ctx.arc(75,75,50,0,2*Math.PI,false); ctx.moveTo(110,75);
ctx.arc(75,75,35,0,Math.PI,false); ctx.moveTo(65,65);
ctx.arc(60,65,5,0,2*Math.PI,true); ctx.moveTo(95,65);
ctx.arc(90,65,5,0,2*Math.PI,true);
ctx.stroke();
}
} </script>
</body>
</html>

上面代码运行后的效果是这样

如果我去掉第一个moteTo()方法即

ctx.moveTo(110,75);

效果会是这样,

两个路径的终点和起点之间会连在一起,多出没用的线。就像我们在用笔画一个笑脸时,先画了一个圆作为头,此时笔尖先不要动,我们接下来要画嘴巴那个半圆,如果我们的笔尖这个时候不提起,那我们只能在当前点连接到嘴巴半圆的起点多出了没用的线,当然,如果你的这个嘴巴起点是在外面圆上一点,就没什么所谓了。综上,其实moveTo()的作用就相当于我们在画画时提笔换下笔位置的作用是一样的。

然后就是translate了,translate的作用更霸道一点,相当于变换原点,啥意思呢,还是比如你在画画,一开始从左上角画,接下来你要画右下角的东西了,但是你懒,自己希望保持当前优雅的姿势不想动,可是现在直接这么画又太费劲,那咋整,把纸挪一下,让右下角的位置到你面前就好啦,translate()的作用就是这个,变换原点是啥意思呢,就是一开始默认都以(0,0)作为原点,不管是moveTo还是直接画圆画矩形都是以(0,0)作为参考点,而translate(),比如说translate(30,40),当前的(30,40)就相当于(0,0),(32,45)此时应该写成(2,5),跟物理里面的相对位置是一样的,懂否?

3、save() restore()

虽然最后明白了是干啥的,但是后来我在练习中save()了好多次而restore()很少,总体来说save()次数并不受限制,但是restore()的次数一定要小于等于save()的次数,先来段代码帮助大家理解

 <!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>移动,旋转,缩放,变形</title>
</head>
<body>
<canvas id="myCanvas" width="500" height="500"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d'); // save resore
ctx.fillRect(0,0,150,150);
ctx.save(); ctx.fillStyle = "#09f";
ctx.fillRect(15,15,120,120);
ctx.save(); ctx.fillStyle = "#fff";
ctx.globalAlpha = 0.5;
ctx.fillRect(30,30,90,90); ctx.restore();
ctx.fillRect(45,45,60,60); ctx.restore();
ctx.fillRect(60,60,30,30);
</script>
</body>
</html>

❑ save:用来保存Canvas的状态。save之后,可以调用Canvas的平移、放缩、旋转、错切、裁剪等操作。

❑ restore:用来恢复Canvas之前保存的状态。防止save后对Canvas执行的操作对后续的绘制有影响。

save和restore要配和使用(restore可以比save少,但不能多),如果restore调用次数比save多,会引发Error。

好吧,我承认上面的三句话是我摘抄过来的,因为感觉这三句写的真的不错啊。。。然后我们结合我附的代码来理解一下,先看下上面那段代码运行之后的效果

其实矩形1,2,3不使用save()和restore()依然可以被绘制出来,但是4,5是使用了2,1的填充状态绘制出来的。当我们操作canvas时默认是对所有的元素进行操作,但是有时候我们可能只是这一步或是只是这一个路径或图形需要这个操作,完成这个操作之后,我们希望回到之前的状态再进行下一步的绘制,那么这个时候就是restore()出场了,当然我们自己手动恢复也是可以的,比如说画完矩形3之后,填充颜色是白色,透明度是0.5,我们回到上一步则会变成填充颜色是“#09f“,透明度为1,而在绘制矩形4时仅对矩形的坐标和大小进行了重新定义,并没有对填充方式定义,所以矩形4和矩形2的填充方式是相同的,换句话说,我们是想复用矩形2的状态才使用restore(),如果想用新的方式,那么restore()就没什么卵用。所以综上,我认为,可以常save(),万一能用上呢?

别打我,你敢说你写代码不是常save?

关于绘制图形就说这么多,但是并不是只有这么多,我只是挑一些当时让我有些迷惑的内容来讲一下,更多的内容大家自己摸索就好。

下面说下。。。嗯 ,引用img

好像没啥可说。。。看教程就没啥问题了。。。。

还有一些其他酷炫的效果,比如什么旋转移动变形缩放啥的,还有什么组合啊之类的还有很多,但是我。。。。懒得写了。。。。其实基本按照教程来就没问题的

附个教程链接https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial

如果以后在项目中应用了,会再补充使用体验,请期待吧~

canvas小结的更多相关文章

  1. Android开发之漫漫长途 XIV——RecyclerView

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  2. Android开发之漫漫长途 XV——RecyclerView

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  3. Canvas:技术小结

    Canvas:技术小结 资料 [教程:MDN官方中文教程] https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial [ ...

  4. Android canvas rotate():平移旋转坐标系至任意原点任意角度-------附:android反三角函数小结

    自然状态下,坐标系以屏幕左上角为原点,向右是x正轴,向下是y正轴.现在要使坐标系的原点平移至任一点O(x,y),且旋转a角度,如何实现? 交待下我的问题背景,已知屏幕上有两点p1和p2,构成直线l.我 ...

  5. 今天写动态canvas柱状图小结

    <!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...

  6. 【HTML】canvas学习小结

    1. 绘制基本图形 -----上下文---------------------------------------------------------- canvas.getContext('2d') ...

  7. canvas的api小结

    HTML <canvas id="canvas"></canvas> Javascript var canvas=document.getElementBy ...

  8. 前台图片Canvas压缩上传小结

    需求来源:之前有个提交审核表单的业务,表单中含有大量附件图片,大约有20多张吧,为了省事,采用的同步上传,一次需要上传很多照片,本来单张图片限制为200KB,这样子总图片大小约为5MB左右,想想也可以 ...

  9. HTML5学习总结——canvas绘制象棋(canvas绘图)

    一.HTML5学习总结——canvas绘制象棋 1.第一次:canvas绘制象棋(笨方法)示例代码: <!DOCTYPE html> <html> <head> & ...

随机推荐

  1. RBAC中 permission , role, rule 的理解

    Role Based Access Control (RBAC)——基于角色的权限控制 permission e.g. creating posts, updating posts role A ro ...

  2. httpie 取代 curl

    接口测试有人喜欢postman(for windows or mac) 如果长期用linux工作,可能更喜欢命令的方式,比如curl最近深入了解了下django-rest-framwork,他们推荐了 ...

  3. shell语法

    基本语法列表 #linux组成:内核+工具 #linux启动: . getty:提示登录名和密码,输入之后调用login . login:login验证用户名和密码,然后调用shell . shell ...

  4. 解决mysql Table ‘xxx’ is marked as crashed and should be repaired的问题。

    解决mysql Table 'xxx' is marked as crashed and should be repaired的问题. 某个表在进行数据插入和更新时突然出现Table 'xxx' is ...

  5. selenium 3.0 beta2 初体验

    经过漫长的等待,终于迎来了selenium 3.0 从selenium 1.0 至今,差不多有十多年的历史.这个月终于迎来了selenium3.0 那么selenium3.0 为我们带来了什么? 看一 ...

  6. Web项目使用Oracle.DataAccess.dll 类库连接oracle数据库

    首先我用的工具是oracle 32位免安装版+Oracle.DataAccess.dll 32位  文件版本4.121.1.0+vs2013 +win7 64位 Oracle.DataAccess.d ...

  7. Mosquitto搭建Android推送服务(三)Mosquitto集群搭建

    文章钢要: 1.进行双服务器搭建 2.进行多服务器搭建 一.Mosquitto的分布式集群部署 如果需要做并发量很大的时候就需要考虑做集群处理,但是我在查找资料的时候发现并不多,所以整理了一下,搭建简 ...

  8. 相机变换与Ray-Casting

    p { margin-bottom: 0.1in; direction: ltr; line-height: 120%; text-align: justify; orphans: 0; widows ...

  9. iOS打包测试

    iOS开发中,怎么打包为ipa格式的软件包以及怎么安装到手机终端上. (我的开发环境为Xcode6.1.1 )作为个人开发者(当然我的开发者帐号为个人开发者帐号,而不是企业开发者帐号),对于自己来说, ...

  10. javascript 框架、根基技巧、布局、CSS、控件 JavaScript 类库

    预筹备之 JavaScript 今朝支流的 JavaScript 框架排名中,jQuery 和 Ext 可算是佼佼者,得到了用户的普遍好评.海内的一些框架许多也是模仿 jQuery 对 JavaScr ...