canvas小结

前段时间在公司没什么事干,研究了一下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()才可以把路径闭合,比如绘制下面一个三角形

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title>canvas小试牛刀</title>
 6     <style>
 7         canvas { border: 1px solid black; }
 8     </style>
 9 </head>
10 <body onload = "draw();">
11 <canvas id="tutorial" width="450" height="250"></canvas>
12 <script>
13     function draw(){
14         var canvas = document.getElementById(‘tutorial‘);
15
16         if(canvas.getContext) {
17             var ctx = canvas.getContext(‘2d‘);
18
19             //            绘制一个三角形
20             ctx.beginPath();
21             ctx.moveTo(50, 50);
22             ctx.lineTo(100, 50);
23             ctx.lineTo(75, 100);
24 //            ctx.fillStyle = "rgba(0,0,255,0.2)";
25             ctx.closePath();//闭合路径
26             ctx.stroke();//默认描边的颜色是黑色
27 }
28 }
29
30 </script>
31 </body>
32 </html>

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

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

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

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

2关于moveTo与translate()

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

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title>canvas小试牛刀</title>
 6     <style>
 7         canvas { border: 1px solid black; }
 8     </style>
 9 </head>
10 <body onload = "draw();">
11 <canvas id="tutorial" width="450" height="250"></canvas>
12 <script>
13     function draw(){
14         var canvas = document.getElementById(‘tutorial‘);
15
16         if(canvas.getContext) {
17             var ctx = canvas.getContext(‘2d‘);
18
19             //            绘制一个笑脸
20              ctx.beginPath();
21             ctx.arc(75,75,50,0,2*Math.PI,false);
22
23             ctx.moveTo(110,75);
24             ctx.arc(75,75,35,0,Math.PI,false);
25
26             ctx.moveTo(65,65);
27             ctx.arc(60,65,5,0,2*Math.PI,true);
28
29             ctx.moveTo(95,65);
30             ctx.arc(90,65,5,0,2*Math.PI,true);
31             ctx.stroke();
32 }
33 }
34
35 </script>
36 </body>
37 </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()的次数,先来段代码帮助大家理解

 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title>移动,旋转,缩放,变形</title>
 6 </head>
 7 <body>
 8 <canvas id="myCanvas" width="500" height="500"></canvas>
 9 <script>
10     var canvas = document.getElementById(‘myCanvas‘);
11     var ctx = canvas.getContext(‘2d‘);
12
13 //    save resore
14     ctx.fillRect(0,0,150,150);
15     ctx.save();
16
17     ctx.fillStyle = "#09f";
18     ctx.fillRect(15,15,120,120);
19     ctx.save();
20
21     ctx.fillStyle = "#fff";
22     ctx.globalAlpha = 0.5;
23     ctx.fillRect(30,30,90,90);
24
25     ctx.restore();
26     ctx.fillRect(45,45,60,60);
27
28     ctx.restore();
29     ctx.fillRect(60,60,30,30);
30 </script>
31 </body>
32 </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

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

时间: 2024-08-29 23:37:54

canvas小结的相关文章

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

该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解Android 卷Ⅰ,Ⅱ,Ⅲ>中的相关知识,另外也借鉴了其他的优质博客,在此向各位大神表示感谢,膜拜!!! 前言 上文我们很详细的分析了ListView的使用.优化.及ListView的RecycleBin机制,读者如果对ListView不太清楚,那么请参看我的上篇博文.不过呢,Google Material

【HTML】canvas学习小结

1. 绘制基本图形 1.1 绘制线 canvas.getContext('2d') 获取上下文 ctx.beginPath() 开始绘制新路径 ctx.closePath() 结束当前路径 ctx.save() 保存当前上下文 ctx.restore() 恢复至上次保存的上下文 ctx.moveTo(x,y) 移动绘制点至x,y ctx.lineTo(x,y) 从当前点绘制到x,y的线 ctx.lineWidth 设置线的宽度 ctx.strokeStyle 设置线的颜色 ctx.fill()

今天写动态canvas柱状图小结

<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <title>Title</title> <style> #main{ margin-top:100px; text-align: center; } #c1{ background: pink; } </style></head><

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

自然状态下,坐标系以屏幕左上角为原点,向右是x正轴,向下是y正轴.现在要使坐标系的原点平移至任一点O(x,y),且旋转a角度,如何实现? 交待下我的问题背景,已知屏幕上有两点p1和p2,构成直线l.我要以两点的中点mid(x,y)为坐标原点,线段l的中垂线为一个轴,l为另外一个轴,做一个坐标系.切割出一个边长为d的正方形.示意图如下所示: double d = Math.sqrt((p2.x-p1.x)*(p2.x - p1.x)+(p2.y-p1.y)*(p2.y-p1.y)); //p1.p

[JavaScript]创建一个canvas画板-小结(1)

创建一个canvas画板 项目链接:GitHub 项目预览:Github Pages 项目描述:通过MDN提供的教程和API,创建一个拥有基本功能(包括绘画,橡皮擦,保存等)的canvas画板. 在教程的学习过程中,掌握canvas的基本用法,以及需要注意的一些地方. 开始创建一块画板 首先我们要在HTML中创建一个canvas <canvas id="canvas" width="300" height="300"></can

Android基础入门教程——8.3.16 Canvas API详解(Part 1)

Android基础入门教程--8.3.16 Canvas API详解(Part 1) 标签(空格分隔): Android基础入门教程 本节引言: 前面我们花了13小节详细地讲解了Android中Paint类大部分常用的API,本节开始我们来讲解 Canvas(画板)的一些常用API,我们在Android基础入门教程--8.3.1 三个绘图工具类详解 中已经列出了我们可供调用的一些方法,我们分下类: drawXxx方法族:以一定的坐标值在当前画图区域画图,另外图层会叠加, 即后面绘画的图层会覆盖前

Android基础入门教程——8.1.1 Android中的13种Drawable小结 Part 1

Android基础入门教程--8.1.1 Android中的13种Drawable小结 Part 1 标签(空格分隔): Android基础入门教程 本节引言: 从本节开始我们来学习Android中绘图与动画中的一些基础知识,为我们进阶部分的自定义 打下基础!而第一节我们来扣下Android中的Drawable!Android中给我们提供了多达13种的 Drawable,本节我们就来一个个撸一遍! Drawable资源使用注意事项 Drawable分为两种: 一种是我们普通的图片资源,在Andr

有关于OpenGL、OpenGL ES、WebGL的小结

转自原文 有关于OpenGL.OpenGL ES.WebGL的小结 一.   OpenGL简介 OpenGL(全写Open Graphics Library)是个定义了一个跨编程语言.跨平台的编程接口的规格,它用于三维图西象(二维的亦可).OpenGL是个专业的图形程序接口,是一个功能强大,调用方便的底层图形库. 关于其他的介绍我就不说了.这边我说一下有OpenGL的资源网站: OpenGL官网:http://www.opengl.org/resources/libraries/glut/ Ne

Android中自定义常用的三个对象解析(Paint,Color,Canvas)

Paint,Color,Canvas Paint:画笔对象,画图用的"笔" Color:颜色,相当于调料 Canvas:画布,现实中的纸板 Paint 画笔 常用的方法就是设置和获取到画笔的样式: paint.setStyle(); 设置画笔的风格,空心的或者是实心的 paint.setColor(); 设置画笔的颜色 paint.setStrokeWidth(); 设置边框线的宽度 paint.setAlpha(); 设置画笔的Alpha值 paint.setAntiAlias();