`
知海匠库
  • 浏览: 1099 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

canvas入门里,你没注意到的那些知识

阅读更多

与看各种文章相比,我更喜欢数学里的逻辑;与学习各种日新月异的框架相比,我更喜欢基础扎实带给人的那种踏实;与拼凑页面页面来回跳转相比,我更喜欢动画,图形在页面中表现的直观。

也许你和我一样,冲着对H5的好奇,冲着对图形的热爱,学了一下canvas,没有熟练,只是简单入了个门,或许你在入门的门槛上就绊倒了,同学不哭,站起来继续撸。我把我入门两天的积累写下来,有些门槛,绊倒了数百次,有些应该也适合你。下文的ctx指的是canvas创建的2d图形化实例,代码:

var canvas = document.querySelector('#test');  //test是Html中一个canvas元素的ID,其宽为600,高为400;
var ctx = canvas.getContext('2d');

说件重要的事

2d上下文(画布)坐标开始于<canvas>元素的左上角,其顶点为坐标原点,x轴正方向指向屏幕右侧,Y轴正方向指向屏幕下方。所以x值越大越靠右,Y值越大越靠下。这和我们传统的坐标轴是有很大区别的,下面一张图,也许能看出。Y轴反向也许很好理解,但顺时针正0度在坐标轴的那个位置,就值得我们好好记住了,使用arc,熟悉这个常识很重要。

四个基本方法

描边:stroke与strokeStyle

ctx.strokeStyle = 'red';
 ctx.arc(200,200,50,0,PI*2,false);
 ctx.stroke();

lineTo,moveTo方法,很基础,这里特别说一下arc(x,y,r,startAngle,endAngle,direction)画圆的方法,这个方法接受6个参数,前五个是必须的,分别是圆心位置(x坐标,y坐标),然后是圆的半径r,再然后是起始位置角和终止位置角,这两个很重要,结合前面那张图理解更,我们可知,上面这段代码绘制的第一个点是(0,50),终止位置也是(0,50)。后面direction是一个可选参数,默认为false,表示顺时针绘制,为true时,为逆时针绘制。

特别说明:

  • 红宝书上说绘制路径,都应该以beginPath()方法开始,但实践证明,这并不需要,你只需要在stroke这个方法来结束这段路径的绘制,但加了也不坏事,所以还是加上吧;
  • 只调用一次lineTo(0,50)方法,你是看不到一条直线绘制出来的,因为(0,0)并不是默认的起点,除非你先用moveTo()方法设置一个起点,这个简单的道理叫两点确定一条直线;
  • closePath()并不是一个与beginPath对照使用的方法,其作用是绘制闭合路径,比如下图所示。可以看到我们只调用了两次lineTo方法,但最后绘制除了三条线,最后这一条线就是closePath作用出来的。但需要注意的是,closePath需在stroke使用前调用。

填充:fillStyle与fill

ctx.fillStyle = 'red'
ctx.arc(200,200,50,0,PI/3,false);
ctx.fill();

与描边对应的就是填充,但这个方法很不讲究,通常来讲,只有封闭区间才有资格填充,但fill这个方法不需要,只要你的路径不是一条直线,那它就能被填充,也就是不在同一条直线上的三点,能确定一个面,这个方法真的很牛逼,我是必须服气的。

绘制文本:stokeText与fillText

以上两个方法都能写出一个字,但推荐的用法是fillText,因为其写出来的是实心字,而stokeText写出来的是描边空心字,绝大多数艺术字会采用这种写法。当然,你愿意的话也可以两者结合着用。

ctx.fillStyle = 'red'
ctx.font= 'bold 12px Arial';
ctx.fillText('Test',300,200);

ctx.strokeStyle = 'red'
ctx.font= 'bold 12px Arial';
ctx.strokeText('Test',400,200);

绘制图像:drawImage

相信很多入门的,都看不到这个地方,canvas不就是绘制图像的嘛,啊,不准确,canvas是绘制图形的。具体说来就是drawImage,它不只能把图片绘制到画布上,他还能绘制canvas图形,这个在星空,雨滴等案列中应用最多,也是canvas离屏优化用的最多的,看下面这个示例。

var cache = document.createElement('canvas');

cache.width = 50;

cache.height = 50;

var cacheCtx = cache.getContext('2d'); //这是一块虚拟画布,因为未添加到dom节点中;

cacheCtx.beginPath();
cacheCtx.strokeStyle = 'red';
cacheCtx.moveTo(5,5);
cacheCtx.lineTo(20,40);
cacheCtx.lineTo(40,20);
cacheCtx.closePath();
cacheCtx.stroke();

ctx.drawImage(cache,50,50);
ctx.drawImage(cache,50,100);
ctx.drawImage(cache,100,50);
ctx.drawImage(cache,100,100);

通过上例,我们就能看出drawImage在离屏优化中的应用。为什么这样可以,因为,像上面一样,我们要在一块画布上,画四个相同的三角形,这在浏览器表现上,你看不出任何卡顿,那如果你是要在屏幕上绘制一千个或万个这样的图形,且每一帧还要有规律的变换他们的位置,这时你就能明显感觉出浏览器的卡顿,因为你一直在操作dom中的元素,使浏览器一直在不停的重新绘制,渲染网页。但如果你在每一帧绘制下一个状态前,在js中,通过在虚拟的canvas中先绘制好下一帧的背景状态,然后通过drawImage这个方法,来更新浏览器中的画布状态,这样网页在一帧中就只需要渲染一次,而不是时时在渲染,这就达到了离屏优化的目的,所以这也是drawImage用的最多的场景。

过完以上知识,就算是复习一下入门知识了,至于为什么没提fillRect与strokeRect,其实那就是stroke与fill提供给绘制矩形的一个语法糖。

奇妙的变换

也许你和我一样,不习惯自己的坐标系是从左上角开始的,我们更习惯坐标原点在左下角或者正中心。

坐标原点变换 translate方法

原点变换到画布中心:ctx.translate(WIDTH/2,HEIGHT/2),WIDTH与HEIGHT分别指画布的宽与高,为了将坐标变换表现得更明显,我在同一块区域,画了两块大小相似的画布,然后让一块使用原始坐标系,一块采用translate变换后的,具体看代码,和结果图;

<div class="red">
    <canvas id="test" width="600px" height="400px"></canvas>
    <canvas id="testa" width="598px" height="398px"></canvas>
</div>

var ctx = document.querySelector('#test').getContext('2d');
var crx = document.querySelector('#testa').getContext('2d');

ctx.beginPath();
ctx.strokeStyle = 'blue';
ctx.arc(0,0,5,0,PI*2,false);
ctx.moveTo(0,0);
ctx.lineTo(0,150);
ctx.moveTo(0,0);
ctx.lineTo(150,0);
ctx.stroke();

crx.beginPath();
crx.translate(300,200);
crx.arc(0,0,5,0,PI*2,false);
crx.strokeStyle = 'red';
crx.moveTo(0,0);
crx.lineTo(0,150);
crx.moveTo(0,0);
crx.lineTo(150,0);
crx.stroke();

坐标系旋转变换 rotate方法

也许你接触canvas很久了,但rotate方法始终没有机会用,只记得红宝书上在绘制钟表时针,分针时,提到了rotate的用法,但只要你熟悉,用法就能千奇百怪。API明确的说rotate(angle),是指围绕原点图像旋转angle弧度。所以,你需要记住两点。第一:图像是围绕原点旋转;第二:与其说是图像旋转,不如说是整个坐标系旋转了。看示例,还是和上面一样,有对比,才有说服力:

ctx.beginPath();
ctx.strokeStyle = 'blue';
ctx.translate(300,200);
ctx.arc(0,0,5,0,PI*2,false);
ctx.moveTo(0,0);
ctx.lineTo(0,150);
ctx.moveTo(0,0);
ctx.lineTo(150,0);
ctx.stroke();
ctx.moveTo(0,0);
ctx.lineTo(0,-150);
ctx.stroke();

crx.beginPath();
crx.strokeStyle = 'red';
crx.translate(300,200);
crx.rotate(PI/3); //旋转60*
crx.arc(0,0,5,0,PI*2,false);
crx.moveTo(0,0);
crx.lineTo(0,150);
crx.moveTo(0,0);
crx.lineTo(150,0);
crx.stroke();
crx.moveTo(0,0);
crx.lineTo(0,-150);
crx.stroke();

与上个图相比,我将两块画布的中心都先变换到了画布的中心,作为对比,红色画笔的做了旋转变换,在分别绘制了正x,正y轴以后,在stoke方法结束一段绘制以后,又绘制了负y轴,可以看到,上一段绘制路径的rotate仍然起作用,所以rotate是对画布坐标系做了变换,而不是狭义上的绘制图像,这个区别很重要。后面在上一段代码,不用sin,cos计算,就能绘制一个正多边形,这里以6边形为例。

ctx.beginPath();
ctx.translate(300,200);
ctx.strokeStyle = 'red';
var a=0;
for(var i=1;i<7;i++){
    ctx.lineTo(0,150);
    ctx.rotate(PI/3);
    a =a + PI/3 ;
}
ctx.closePath();
ctx.stroke();
ctx.lineTo(0,0);
ctx.stroke();

不重要,但很点题的API

绘制一个普通的图形,也许上面的API也已足够,但要让你的图形有亮点,你可能还需要多了解一些,我个人觉得非常有用的两个就是阴影的绘制(shadow)与渐变色的添加(createLinearGradient)。在用canvas做星星背景时,或者飞行的流星周围的闪光,这些都是用shadow做出来的特效。而消逝的流星,头部亮,尾部暗的效果就是用渐变色做的,在以后的系列中,会结合实例多讲一些。

分享到:
评论

相关推荐

    HTML 5 CANVAS游戏开发实战

    标题中提到的“HTML 5 CANVAS游戏开发实战”涉及到的知识点包括了HTML 5技术、CANVAS元素以及游戏开发方面的实战应用。HTML 5是最新版本的超文本标记语言,它引入了诸多新的特性来增强网页的表现性能和实现更丰富的...

    js+canvas实现转盘效果(两个版本)

    它涉及到以下几个关键知识点: 1. **Canvas元素**:首先需要一个`&lt;canvas&gt;`标签来定义一个画布区域,这是在HTML文档中创建画布的一个标准方式。 2. **绘图上下文(context)**:通过获取Canvas元素的2D绘图上下文`...

    从入门到精通HTML5——PDF——网盘链接

     1.3.6 编写文件的注意事项 8  1.4 编写第一个HTML文件 8  1.4.1 HTML文件的编写方法 8  1.4.2 手工编写页面 9  1.4.3 使用可视化软件制作页面 10  1.4.4 使用浏览器浏览HTML文件 14  1.4.5 使用HTML开发的...

    《Unity 5.x从入门到精通》配套光盘资源

    通过研究这些资源,读者不仅能巩固理论知识,还能提升实战技能,从而真正从入门到精通Unity 5.x。同时,不断更新的Unity版本(如6.x、2019.x、2020.x等)也带来了新特性,保持对新版本的学习也是持续进阶的重要步骤...

    Qt5入门教程

    ### Qt5 入门教程知识点概述 #### 一、Meet Qt5 - **1.1 Preface** - 介绍Qt5的历史背景及其在跨平台应用开发中的地位。 - 强调Qt5相较于Qt4的主要改进之处。 - **1.2 Qt5 Introduction** - 定义Qt5的核心组件...

    html 入门教程 html手册

    通过阅读“HTML语言入门教程1.doc”,你可以系统地了解HTML的基础知识,而“使用须知.txt”可能包含了一些实践中的注意事项和技巧,帮助你在学习过程中少走弯路。记住,实践是检验学习效果的最好方式,动手创建自己...

    HTML5从入门到精通》-中文学习教程

    HTML5作为最新的HTML版本,从入门到精通的学习过程涵盖了丰富的知识点,包括基本概念、新增特性、标签和API等。根据提供的文件信息,以下是对相关知识点的详细说明: HTML5简介: HTML5是HTML的第五次重大修订,...

    【入门】Android自定义控件——验证码

    这篇博文"【入门】Android自定义控件——验证码"旨在引导开发者如何创建一个专用于显示和交互的验证码控件。验证码通常用于验证用户身份,防止自动化程序进行恶意操作,如注册、登录等。 验证码控件的基本要素包括...

    J2ME 2D小游戏入门之旅.rar_j2me_j2me小游戏_java 2d_小游戏_小游戏 java

    Java Micro Edition(J2ME)是...总之,通过这个入门教程,你可以了解到J2ME环境的设置,2D图形编程基础,以及如何利用这些知识来创建简单的移动游戏。不断练习和探索,你将能够熟练地开发出富有创意的J2ME 2D小游戏。

    qunee入门基础教程

    整体来看,Qunee入门基础教程为初学者提供了从环境搭建到基础使用,再到图形元素操作、图元容器管理、Graph组件应用以及样式的定制等全方位的知识点。通过这些知识点的学习,开发者能够快速上手Qunee,轻松构建出...

    《J2me手机游戏编程入门》书带源码

    《J2ME手机游戏编程入门》是一本专为初学者设计的书籍,旨在引导读者进入移动游戏开发的世界。J2ME(Java 2 Micro Edition)是Java平台的一个子集,主要用于开发嵌入式设备和移动设备上的应用程序,尤其是早期的智能...

    unity 5.x 从入门到精通

    Unity 5.x 是一款强大的跨平台游戏开发引擎,被广泛应用于制作2D和3D游戏、虚拟现实(VR)和增强...不过要注意,Unity版本更新频繁,更高级的Unity 2019及以后版本可能会有新的特性和改进,所以适时更新知识是必要的。

    WPF入门经典教程

    根据给定的文件信息,以下是对...通过以上对WPF入门经典教程的关键知识点的解析,我们了解到WPF不仅仅是一种UI框架,更是一套完整的应用开发平台,它提供了丰富的控件和工具来帮助开发者构建美观且功能强大的应用程序。

Global site tag (gtag.js) - Google Analytics