再探canvas(小球实例)
之前学习过canvas的一些使用,也用过canvas绘制过时钟, 但是很久不用,有些遗忘了,这里做一个简单的回顾。
在web页面创建一个canvas画布非常简单,如下即可:
<canvas id = "parabolic" width="" height=""></canvas>
注意:canvas元素是一个内联元素。
当然我们也可以修改它的style,如下所示:
#parabolic {
display: block;
background: #ccc;
margin: 200px auto;
}
这样,我们就可以在页面上得到一个灰色的300px的画布了。
由于我们必须在确保使用<canvas>时所有的页面已经完全加载,所以在js中需要添加:
window.addEventListener("load", function() {
// Your code ...
},false);
接下来我们就可以获得这个canvas元素了:
var myCanvas = document.getElementById("parabolic");
然后,为了可以在canvas上画图,我们就得先获取到2d环境:
var parabolic = myCanvas.getContext("2d");
ok! 大功告成,一旦获得了2d环境,我们就可以利用canvas的API进行画图了。
比如最简单的 fillStyle用于设置绘制的颜色, fillRect可以绘制矩形。
parabolic.fillStyle = "#0000ff";
parabolic.fillRect(, , , );
这就会绘制一个颜色是蓝色的在画布中的位置为(20,40)的宽为50,高为100的矩形。如下:
而如果使用strokeStyle和strokeRect就会画出一个同样大小的矩形,只是外层是边框,没有完全填充:
在Canvas的API中还有一个rect方法,这个和strokeRect有什么区别呢? 其实并没有区别,知识,我们得用两步来完成,如下:
parabolic.beginPath();
parabolic.strokeStyle = "blue";
parabolic.rect(, , , );
parabolic.stroke();
效果如下所示:
于是可以总结区别:
- fillStyle是填充的样式,stroke是绘制的样式
- fillRect是填充矩形,必须喝fillStyle配合使用; strokeRect是绘制矩形,必须和strokeStyle配合使用。
到这里,其实我们就已经可以总结出规律了,基本上就是下面两种方式:
方式一:
- 先确定样式 (fillStyle)
- 再填充路径 (fillReact)
方式二:
- 先确定样式 (fillStyle)
- 在确定路径(react)
- 最后进行填充 (fill)
而 clearRect()的作用是清除选择矩形中的像素
parabolic.fillStyle = "#0000ff";
parabolic.fillRect(, , , );
parabolic.clearRect(,,,);
最终的效果如下所示:
即我们清除了上面一半的矩形,只剩下下面的矩形了。
如果我们想要绘制一条线,使用lineTo就可以了,如下所示:
parabolic.beginPath();
parabolic.lineWidth = "";
parabolic.strokeStyle = "red";
parabolic.moveTo(, );
parabolic.lineTo(, );
parabolic.stroke();
首先,要确定line的宽度,否则最后就什么都看不到了,我们这里是在绘制路径,所以要用stroke, 因为无法填充,所以如果使用fill是得不到结果的。
moveTo是指将起点移动到的位置,而lineTo是你画的这条线要截至的位置, 之前一直在描述这个路径是怎么样的,最后必须要使用stroke()才能将之绘制出并展示出来。 注意:在每次绘制路径前,我们最好使用 beginPath(), 这是一个好的习惯。
根据上图,可判断canvas的原点是在左上方的,向右为x轴正方向,向下为y轴正方向。
如果我们希望制作一个封闭的路径,那么使用closePath往往可以达到我们想要的效果:
parabolic.beginPath();
parabolic.lineWidth = "";
parabolic.strokeStyle = "red";
parabolic.moveTo(, );
parabolic.lineTo(, );
parabolic.lineTo(, );
parabolic.closePath();
parabolic.stroke();
即我们先从(50, 50)绘制到 (70, 100),然后接着到(90, 50),这时如果stroke我们可以得到一个v形,但是如果我们使用了closePath()方法,这个路径就可以自动闭合了,如下:
显然,这里的基本思路也是 样式 -> 路径 -> 填充 只是调用不同的api而已,其他并没有什么区别。
哈哈,在canvas中还有一个比较有意思的就是 arc()方法了, 它可以画弧线,接收六个参数,分别是圆心的x、y坐标,半径,起始和终止的弧度,还有一个可选的true/false即顺时针还是逆时针(true是逆时针),如下:
parabolic.beginPath();
parabolic.strokeStyle = "red";
parabolic.arc(, , , , Math.PI, true);
parabolic.stroke();
我们将绘制弧形的函数进行简单的封装,就可以做出下面的小丑的样式了,
window.addEventListener("load", function() {
var myCanvas = document.getElementById("parabolic");
var parabolic = myCanvas.getContext("2d"); // 将绘制圆形的函数进行封装,可以减少代码的重复使用
function paintArc(style, color, x, y, r, start, end, bool) {
parabolic.beginPath();
parabolic[style+"Style"] = color;
parabolic.arc(x, y, r, start, end, bool);
parabolic[style]();
}
paintArc("fill", "blue", , , , , Math.PI, false);
paintArc("fill", "blue", , , , , Math.PI, false);
paintArc("fill", "blue", , , , , Math.PI, true);
paintArc("fill", "blue", , , , , Math.PI, true);
paintArc("stroke", "red", , , , , Math.PI, true);
paintArc("stroke", "red", , , , , *Math.PI, true);
paintArc("fill", "green", , , , , *Math.PI, true);
paintArc("stroke", "red", , , , , *Math.PI, true);
paintArc("fill", "green", , , , , *Math.PI, true);
paintArc("fill", "yellow", , , , , *Math.PI, true);
paintArc("fill", "pink", , , , , Math.PI, false ); },false);
最终效果如下所示:
除此之外,我们还可以看到 quadraticCurveTo() 的二次贝塞尔曲线的API,使用起来也不难。
二次贝塞尔曲线需要两个点,一个是终点,另外一个是控制点,我们从官网上盗图得到:
这样,我们就可以得到了,如下所示:
parabolic.beginPath();
parabolic.moveTo(, );
parabolic.strokeStyle = "red";
parabolic.quadraticCurveTo(, , , );
parabolic.closePath();
parabolic.stroke();
效果如下:
这里封闭是因为我们使用了closePath方法。
三次贝塞尔曲线和二次贝塞尔曲线的区别并不大,只是多了一个控制点,如下所示:
下面我们使用贝塞尔曲线就可以绘制处nike的标志了,
window.addEventListener("load", function() { var myCanvas = document.getElementById("parabolic");
var parabolic = myCanvas.getContext("2d");
parabolic.beginPath();
parabolic.moveTo(, );
parabolic.bezierCurveTo(, , , , , );
parabolic.bezierCurveTo( , , , , , );
parabolic.fill(); },false);
最终效果如下所示:
这个曲线是贝塞尔曲线的方程,博友写过一篇博客,就是讲解了关于二次贝塞尔曲线和三次贝塞尔曲线的。
在API中,我们还可以发现有一个rotate()方法,使用如下:
drawCurve();
function drawCurve() {
parabolic.beginPath();
parabolic.moveTo(, );
parabolic.rotate(*Math.PI/);
parabolic.bezierCurveTo(, , , , , );
parabolic.stroke();
}
注意:rotate一定要在 绘制之前, 否则是不起效果的, 可以看到我们一般使用 角度*Math.PI/180 的方式进行旋转
我们还可以使用 rotate的api,如下所示:
drawCurve();
function drawCurve() {
parabolic.beginPath();
parabolic.moveTo(, );
parabolic.scale(0.5, 0.5);
parabolic.bezierCurveTo(, , , , , );
parabolic.stroke();
}
最终效果如下:
不难看出,这时候两边是不一样高的,因为这里的缩放并没有对画布进行缩放, 而只是对最终我们要绘制的路径进行了缩放。即把我们输入的值进行了缩放, 而之前的moteTo里的值始终不改变。
当然,之前说过,原点默认是在左上方的,但是我们可以使用translate(x, y)方法,将目前处于(0,0)的原点移到(x,y),
我们还可以在canvas画布中添加字体:
parabolic.beginPath();
parabolic.font = "25px Arial";
parabolic.fillText("e瞳网", , );
其中,font可以设置字体的大小,样式,而fillText()方法可以填充字体, 我们还可以使用strokeText()方法来填充。
最后需要介绍的就是 save()方法和 restore()方法了
其中,前者可以保存当前环境的状态,而后者可以返回之前保存的状态。
最后,使用canvas练习了一个小的例子,但是对于计时器目前还没有完全的了解。
可以肯定的是,计时器被输出时是一个数字, 在相同的环境下, 被调用一次, 计时器的这个数字就会加1, 另外, 计时器setInterval(func, time)中的第二个参数一般情况下我们最好不要设置太高,控制台16ms以上是最好的,因为一般的浏览器刷新率为16ms一次,所以这个速度是比较合适的。
另外,在下面的这个例子中,我使用了这篇博文介绍的贝塞尔函数的计算用于控制小球的运动轨迹,效果如下:
代码在我的github上。
再探canvas(小球实例)的更多相关文章
- 【再探backbone 02】集合-Collection
前言 昨天我们一起学习了backbone的model,我个人对backbone的熟悉程度提高了,但是也发现一个严重的问题!!! 我平时压根没有用到model这块的东西,事实上我只用到了view,所以昨 ...
- 再探jQuery
再探jQuery 前言:在使用jQuery的时候发现一些知识点记得并不牢固,因此希望通过总结知识点加深对jQuery的应用,也希望和各位博友共同分享. jQuery是一个JavaScript库,它极大 ...
- [老老实实学WCF] 第五篇 再探通信--ClientBase
老老实实学WCF 第五篇 再探通信--ClientBase 在上一篇中,我们抛开了服务引用和元数据交换,在客户端中手动添加了元数据代码,并利用通道工厂ChannelFactory<>类创 ...
- 再探ASP.NET 5(转载)
就在最近一段时间,微软又有大动作了,在IDE方面除了给我们发布了Viausl Studio 2013 社区版还发布了全新的Visual Studio 2015 Preview. Visual Stud ...
- c++再探string之eager-copy、COW和SSO方案
在牛客网上看到一题字符串拷贝相关的题目,深入挖掘了下才发现原来C++中string的实现还是有好几种优化方法的. 原始题目是这样的: 关于代码输出正确的结果是()(Linux g++ 环境下编译运行) ...
- ViewPager+Fragment再探:和TAB滑动条一起三者结合
Fragment前篇: <Android Fragment初探:静态Fragment组成Activity> ViewPager前篇: <Android ViewPager初探:让页面 ...
- h5 canvas 小球移动
h5 canvas 小球移动 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...
- Spark Streaming揭秘 Day7 再探Job Scheduler
Spark Streaming揭秘 Day7 再探Job Scheduler 今天,我们对Job Scheduler再进一步深入一下,对一些更加细节的源码进行分析. Job Scheduler启动 在 ...
- 再探java基础——break和continue的用法
再探java基础——break和continue的用法 break break可用于循环和switch...case...语句中. 用于switch...case中: 执行完满足case条件的内容内后 ...
随机推荐
- 【转】快速开发移动医疗App!开源框架mHealthDroid
原文地址:http://www.csdn.net/article/2014-12-12/2823096-mHealhDroid mHealthDroid是一款开源的移动框架,主要用于帮助开发者快速而又 ...
- owinAuthorize
Nuget包获取 Install-Package Microsoft.AspNet.WebApi.Owin -Version 5.1.2 Install-Package Microsoft.Owin. ...
- SQLServer如何在批量插入后,获取批量插入的自增列的值
解决方法如下: Use the OUTPUT functionality to grab all the INSERTED Id back into a table. 使用output 功能获取所有插 ...
- [Violet]樱花
题目链接 洛谷 狗粮版 前置技能 初中基础的因式分解 线性筛 \(O(nlog)\)的分解质因数 唯一分解定理 题解 首先来分解一下式子 \[\frac{1}{x}+\frac{1}{y}=\frac ...
- JAVA学习必须掌握的框架,不看后悔
Web应用,最常见的研发语言是Java和PHP. 后端服务,最常见的研发语言是Java和C/C++. 大数据,最常见的研发语言是Java和Python. 可以说,Java是现阶段中国互联网公司中,覆盖 ...
- Jmeter_实现Excel文件导出到本地
一般而言,对于页面的“导出”操作,主要经历如下两个操作:①根据数据库的内容,将文件导出到应用服务器上:②将服务器上的文件下载到本地电脑: Jmeter同LoadRunner类似,只能记录服务端与客户端 ...
- 深度学习之 TensorFlow(三):TensorFlow 源代码解析
分析一下 TensorFlow 的文件结构.这里的源代码版本是 TensorFlow1.7.0 . 目录结构如下: 其中的核心目录是 tensorflow 目录,最重要的源代码保存在这里,目录结构如下 ...
- numpy常用功能总结、python格式化输入输出
#coding:utf-8 #author:徐卜灵 ##################### #由于在各大公司笔试的时候总是会遇到一些格式化输入输出数据,今天就来总结一下. #结合numpy来处理数 ...
- 老男孩Day10作业:主机管理程序
一.作业需求: 1, 运行程序列出主机组或者主机列表 2,选择指定主机或主机组 3,选择主机或主机组传送文件(上传/下载) 4,充分使用多线程或多进程 5,不同主机的用户名,密码,端口可以不同 6,可 ...
- 有关unixODBC:Data source name not found, and no default driver specified的问题
还是昨天测试postgresql的有关Mirroring Controller的功能时出的问题(真TM是个坑). 首先说下环境: 操作系统平台:RHEL6 x86_64 unixODBC版本:2.3. ...