Html5---鸟巢
来源:互联网 发布:南通网络推广 编辑:程序博客网 时间:2024/05/01 08:43
由于昨天晚上陪老婆看房子去了,就没有写,今天一定补上。
这次我们来利用CanvasRenderingContext2D的一些API一个鸟巢。涉及的知识点和技艺包括:三次贝赛尔曲线的绘制,CanvasRenderingContext2D的translate和rotate 等api.
第一步:椭圆绘制:
在CanvasRenderingContext2D开放的一些曲线绘制API当中,有绘制线段、矩形和圆形的,没有绘制椭圆的,所以需要自己去封装一个绘制椭圆的方法,如:
function drawEllipse(x, y, w, h) { //您的代码 }
其中,x,y为椭圆的左上角的坐标(不是中心坐标),w和y分别为长轴和短轴。在实现这个方法之前,很容易就可以想到以下面几种预选方案:
A,根据椭圆笛卡儿坐标第方程绘制;
B,根据椭圆极坐标方程绘制;
C,利用四条贝赛尔曲线绘制。
第一种和第二种方式都是基于点的,以不断地连接椭圆上的所有点来拟合一个完整的椭圆,这样会带来大量的计算和重复调用CanvasRenderingContext2D的API。在Canvas性能优化中很重要的一点就是尽量少地调用CanvasRenderingContext2D的API.比如下面两份代码的对比,第二段代码的性能远远优于第一段。
代码一:
for (var i = 0; i < points.length-1; i++) { var p1 = points[i]; var p2 = points[i + 1]; context.beginPath(); context.moveTo(p1.x, p1.y); context.lineTo(p2.x, p2.y); context.stoke(); }
代码二:
context.beginPath(); for (var i = 0; i < points.length - 1; i++) { var p1 = points[i]; var p2 = points[i + 1]; context.moveTo(p1.x, p1.y); context.lineTo(p2.x, p2.y); } context.stoke();
第 三种,也是性能最好的一种,绘制过程只需要调用4次CanvasRenderingContext2D.bezierCurveTo,这样可以避免复杂的计算和大量重复调用CanvasRenderingContext2D的API。
所以采用第三种方式来绘制椭圆。代码如下所示:
function drawEllipse(x, y, w, h) { var k = 0.55228475; var ox = (w / 2) * k; var oy = (h / 2) * k; var xe = x + w; var ye = y + h; var xm = x + w / 2; var ym = y + h / 2; cxt.beginPath(); cxt.moveTo(x, ym); cxt.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); cxt.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); cxt.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); cxt.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); ctx.stroke(); }
第二步:三次贝赛尔曲线
上面通过绘制4段三次贝赛尔曲线来绘制一个椭圆。要知道以上代码中系数K的由来,可推导如下:
曲线的参数形式为:
B(t)=P_0 〖(1-t)〗^3+3P_1 t〖(1-t)〗^2+3P_2 t^2 (1-t)+P_3 t^2 , t∈[0,1]
第三步:旋转椭圆
绘制完椭圆,需要旋转椭圆来形成鸟巢。这里的旋转不是绕上面的DrawFllipse的前两个参数x,y旋转,而是绕椭圆的中心旋转。所以仅仅使用CanvasRenderingContext2D.rotate是不够的,因为CanvasRenderingContext2D.rotate是绕画布的左上角(0,0)旋转的。所以先要把(0,0)通过CanvasRenderingContext2D.translate到椭圆的中心,然后再DrawEllipse(-a/2,-b/2,a,b)。
以上就是绕中心旋转的核心。这里还可以推广到任意图形或者图片(假设有约定的中心)。
完整的代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head> <title></title></head><body> <canvas id="myCanvas" width="350" height="350" style="border: solid 15px #222; background-color: #111; color: #CCC;">你的浏览器不支持canvas</canvas> <script src="../Scripts/jscex.jscexRequire.min.js" type="text/javascript"></script> <script type="text/javascript"> var canvas; var ctx; var px = 0; var py = 0; function init() { canvas = document.getElementById("myCanvas"); ctx = canvas.getContext("2d"); ctx.strokeStyle = "#fff"; ctx.translate(70, 70); } init(); var i = 0; function drawEllipse(x, y, w, h) { var k = 0.5522848; var ox = (w / 2) * k; var oy = (h / 2) * k; var xe = x + w; var ye = y + h; var xm = x + w / 2; var ym = y + h / 2; ctx.beginPath(); ctx.moveTo(x, ym); ctx.bezierCurveTo(x, ym - oy, xm - ox, y, xm, y); ctx.bezierCurveTo(xm + ox, y, xe, ym - oy, xe, ym); ctx.bezierCurveTo(xe, ym + oy, xm + ox, ye, xm, ye); ctx.bezierCurveTo(xm - ox, ye, x, ym + oy, x, ym); ctx.stroke(); ctx.translate(x + 70, y + 100); px = -70; py = -100; ctx.rotate(10 * Math.PI * 2 / 360); } var ct; var drawAsync = eval(Jscex.compile("async", function (ct) { while (true) { drawEllipse(px, py, 140, 200) $await(Jscex.Async.sleep(200, ct)); } })) function start() { ct = new Jscex.Async.CancellationToken(); drawAsync(ct).start(); } function stop() { ct.cancel(); } </script> <input id="Button2" type="button" value="run" onclick="return start()" /> <input id="Button1" type="button" value="stop" onclick="return stop()" /></body></html>
运行效果如下:
小结:
通过本例子,我们了解了贝塞尔曲线的运用及其拟合椭圆的原理,然后分析了Jscex的各种取消方法和其自身的取消模型。通过这个取消模型,也可以体会到Jscex的优势,Jscex使程序员可以使用线性的思维写程序,而不必关心回调,在一些纪线性混合深度嵌套的场景下,优势特别明显。
- Html5---鸟巢
- 鸟巢
- 鸟巢
- 体验鸟巢
- 真正鸟巢VS奥运鸟巢
- 平淡生活:参观鸟巢
- 参观鸟巢的照片
- 周末游鸟巢
- 【基础排序】鸟巢排序
- 湖南鸟巢专利孵化
- 北京那个没用的鸟巢
- 奥运金银鸟巢全国巡展
- 雨润鸟巢,爱心启程
- 大连为“鸟巢”穿上“防火衣”
- 刘翔退赛像一颗原子弹扔在了鸟巢
- 去鸟巢看奥运时的照片。
- 不到半年“鸟巢”已经变成了这样!
- 鸟巢滑雪--被骗的感觉好爽
- MFC 加载gif动态图片的方法
- Javascript 操作select控件大全(新增、修改、删除、选中、清空、判断存在等)
- tabpanel 刷新另一个标签
- shell script学习笔记5
- IE下载word文件变成zip文件的解决方法
- Html5---鸟巢
- jQuery最佳实践
- semctl()函数
- Shell之basename
- Asp.Net异常Asynchronous operations are not allowed in this context的解决方案
- IOS开发UI篇之──自定义加载等待框(MBProgressHUD)
- DOM4j对xml解析
- 汉字在电脑中是如何存储与编码
- 6.(数组)腾讯面试题: