又到了樱花的季节,教大家使用canvas画出飞舞的樱花树效果。

废话少说,先看效果。

演示效果地址:http://suohb.com/work/tree4.htm

查看演示效果

第一步,我们先画出一棵树的主体。

我画树的使用的原理是,定义一个起始点,从这个点开始,向一个角度移动一段距离。得到另一个点。

画出一条线连接两个点。

以新得到的点,依旧向这个角度,移动一段距离。得到第三个点,连写第二第三个点。

以此类推。一定步长之后,就得到一条射线。

我们根据自然界中的真实树的情况,这条线越来越细,直到最细地方结束。

<body bgcolor="#000000">
<canvas id="tree"></canvas>
<script>
var treeCanvas = document.getElementById("tree");
treeCanvas.width = window.innerWidth;
treeCanvas.height = window.innerHeight ;
var tCxt = treeCanvas.getContext("2d");
var rootTop = 450 ;//树起始位置
var treeColor = "#FFF" ;//树颜色 function drawTree(x,y,deg,step){
var x1 = x + Math.cos(deg) * step ;//越细的枝干越短,所以以步长来做
var y1 = y + Math.sin(deg) * step ;
tCxt.beginPath();
tCxt.lineWidth = step/3;//树干越来越细
tCxt.moveTo(x,y);
tCxt.lineTo(x1,y1);
tCxt.strokeStyle = treeColor ;
tCxt.stroke();
step -- ;
if(step > 0){
drawTree(x1,y1,deg,step);
}
} drawTree(treeCanvas.width/2,rootTop,-Math.PI/2,30);
</script>
</body>

树干出来之后,要做分叉,每个分叉其实就是向另一个方向的树干。

而且分叉要比主干细一些。我们在第二阶段树干位置,每三步向左右分叉。

if(step > 0){
drawTree(x1,y1,deg,step);
if(step%3 == 1)
drawTree(x1,y1,deg+0.5 ,Math.round(step/1.13));//右分叉
if(step%3 == 0)
drawTree(x1,y1,deg-0.5, Math.round(step/1.13));//左分叉
}

这样一棵树的主干基本上就已经完成了。

我们在树的末端几个节点,画一个粉色的半透明的圆。当做樱花。

为了保证所有樱花不是千篇一律的一个角度,我们随机一个起始角度。

function drawTree(x,y,deg,step){
var x1 = x + Math.cos(deg) * step ;//越细的枝干越短,所以以步长来做
var y1 = y + Math.sin(deg) * step ;
tCxt.beginPath();
tCxt.lineWidth = step/3;//树干越来越细
tCxt.moveTo(x,y);
tCxt.lineTo(x1,y1);
tCxt.strokeStyle = treeColor ;
tCxt.stroke();
if(step < 5 ){//在末端五个节点,画一个半圆,作为樱花效果
var r = 2+Math.random()*2
tCxt.fillStyle = flowerColor ;
tCxt.arc(x1+Math.random()*3,y1+Math.random()*3,r,0,Math.PI)
tCxt.fill();
}
step -- ;
if(step > 0){
drawTree(x1,y1,deg,step);
if(step%3 == 1)
drawTree(x1,y1,deg+0.5 ,Math.round(step/1.13));//右分叉
if(step%3 == 0)
drawTree(x1,y1,deg-0.5, Math.round(step/1.13));//左分叉
}
}

这个时候,如果没有特别的要求的,基本算是已经完成了。

之后再要做的就是精益求精,对现在效果做出微调。

1、树干都是直线,在计算下一个点的时候,做一些偏移。

2、樱花树形态比较扁平。给X轴方向上偏移稍微大点,Y轴稍微偏小一点。

3、至少做两种花瓣颜色,一种稍微深一些,一种浅一些。

4、在新建一个canvas层,做一些飘落樱花的效果。

5、在分叉,画花瓣等地方多使用一些随机数,树形状不能太单一

最终效果如下:

完整代码如下:

<!doctype html>
<html>
<head>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" />
<style type="text/css">
canvas{
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body bgcolor="#000000">
<canvas id="tree"></canvas>
<canvas id="flower"></canvas>
<script>
//两个canvas
var tree = document.getElementById("tree");
tree.width = window.innerWidth;
tree.height = window.innerHeight ;
var tCxt = tree.getContext("2d");
var flower = document.getElementById("flower");
flower.width = window.innerWidth;
flower.height = window.innerHeight ;
var cxt = flower.getContext("2d"); var flowerList = [];//樱花列表
var rootTop = 450 ;//树起点
var flowerColor = "rgba(255,192,203,.3)" ;//花色
var flowerColorDeep = "rgba(241,158,194,.5)" ;//花色深
var treeColor2 = "rgba(255,192,203,.5)" ;//树枝颜色
var treeColor = "#FFF" ;//树干颜色
var fallList = [];//飘落樱花列表
var g = 0.01 ;//重力加速度
var gWind = 0.005;//风力加速度
var limitSpeedY = 1;//速度上限
var limitSpeedX = 1 ;//速度上限 cxt.shadowColor= "#FFF" ;
cxt.shadowBlur = 10 ; function drawTree(x,y,deg,step,type){
var deg1 = step%2 == 0 ? 0.1 : -0.1 ;
var x1 = x + Math.cos(deg+deg1) * (step+4) * 0.8 ;//以步长来判断枝干长度 x轴偏移大一些
var y1 = y + Math.sin(deg+deg1) * (step-1) * 0.8 ;//以步长来判断枝干长度 Y轴压缩一些
tCxt.beginPath();
tCxt.lineWidth = step/3;
tCxt.moveTo(x,y);
tCxt.lineTo(x1,y1);
tCxt.strokeStyle = (step > 5 ) ? treeColor : treeColor2 ;//细纸条都换成花的颜色
tCxt.stroke();
if(step > 20){//树干相交的位置有间隙,以一个圆填充
tCxt.fillStyle = treeColor ;
tCxt.arc(x,y,step/6,0,Math.PI*2);
tCxt.fill();
}
if(step < 3 || (step < 23 && Math.random() > 0.1)){
//末梢位置 画花瓣
var color = [flowerColorDeep,flowerColor,flowerColor][Math.round(Math.random()+0.2)] ;
var r = 2+Math.random()*2
tCxt.fillStyle = color ;
tCxt.arc(x1+Math.random()*3,y1+Math.random()*3,r,0,Math.PI)
tCxt.fill();
flowerList.push({x:x,y:y,sx:(Math.random()-0.5),sy:0,color:color,r:r,deg:deg});//保存下画樱花的位置
}
step -- ;
if(step > 0){
drawTree(x1,y1,deg,step,type);
if(step%3 == 1 && step > 0 && step < 30)
drawTree(x1,y1,deg+0.2 + 0.3 * Math.random(),Math.round(step/1.13));//右分叉
if(step%3 == 0 && step > 0 && step < 30)
drawTree(x1,y1,deg-0.2 - 0.3 * Math.random(),Math.round(step/1.13));//左分叉
}
} drawTree(tree.width/2,rootTop,-Math.PI/2,30,1);//执行 var len = flowerList.length ;
function step(){
if(Math.random() > 0.3) fallList.push(flowerList[Math.floor(Math.random()*len)]);//随机取出一个,花瓣复制到飘落花瓣的列表中 cxt.clearRect(0,0,tree.width,tree.height);
for(var i = 0 ;i < fallList.length ; i ++){
if(fallList[i].sy < limitSpeedY) fallList[i].sy += g ;
fallList[i].sx += gWind ;
fallList[i].x += fallList[i].sx ;
fallList[i].y += fallList[i].sy ;
if(fallList[i].y > rootTop){//飘到树根的花瓣移除
fallList.splice(i,1);
i -- ;
continue ;
}
cxt.beginPath();
cxt.fillStyle = fallList[i].color ;
fallList[i].deg += fallList[i].sx*0.05 ;//跟速度相关的旋转花瓣
cxt.arc(fallList[i].x,fallList[i].y,fallList[i].r,fallList[i].deg,fallList[i].deg+Math.PI*1.3);
cxt.fill();
}
requestAnimationFrame(step);
}
requestAnimationFrame(step);
</script>
</body>
</html>

查看演示效果

更多特效,请关注我的微信公众号。

樱花的季节,教大家用canvas画出飞舞的樱花树的更多相关文章

  1. 撩妹技能 get,教你用 canvas 画一场流星雨

    开始 妹子都喜欢流星,如果她说不喜欢,那她一定是一个假妹子. 现在就一起来做一场流星雨,用程序员的野路子浪漫一下. 要画一场流星雨,首先,自然我们要会画一颗流星. 玩过 canvas 的同学,你画圆画 ...

  2. 情人节,教大家使用css画出一朵玫瑰花。

    情人节到了,给大家来一朵高端的玫瑰花. 在网上看到的一个canvas实现的玫瑰花,效果很好,但是代码被压缩过,也没有注释,看的云里雾里的. 今天我教大脚用CSS来实现一朵玫瑰花. 先看效果 首先我们画 ...

  3. 教你用SVG画出一条龙

    先看demo,九十七度 其实使用svg画出这条龙很简单,关键不在于怎么使用svg,而在于你的美术功底,哈哈. 好吧,当然基础是不能忽略的,先看下这条龙的代码: <svg id="lon ...

  4. 手对手的教你用canvas画一个简单的海报

    啦啦啦,首先说下需求,产品想让用户在我们app内,分享一张图片到微信.qq等平台.图片中包含用户的姓名.头像.和带着自己信息的二维码.然后,如何生成这张海报呢~~~首先我们老大告诉我有一个插件叫htm ...

  5. 公告栏添加时钟——利用canvas画出一个时钟

    前言 最近在学习HTML5标签,学到Canvas,觉得很有趣.便在慕课网找了个demo练手.就是Canvas时钟. 对于canvas,w3shcool上是这么描述的: HTML5 <canvas ...

  6. 4种方法生成二维码 (js 控制canvas 画出 二维码)

    随着网络的迅速发展 发展 发展,二维码的应用将会越来越多.同时很多只是很平凡的二维码,请拿起你的手 把这个二维码 设计起来吧.下面分享了几个非常好的二维码设计.  二维码原理: 二维条码/二维码可以分 ...

  7. 用canvas 画出圆形图片

    /** * 把图片处理成圆形,如果不是正方形就按最小边一半为半径处理 * @param {object} imgObj 图片(img)对象 * @param {number} imgType 设置生成 ...

  8. WPF在圆上画出刻度线

    思路 我们可以使用Ellipse先画出一个圆当背景,然后用Canvas再叠加画上刻度线,就能得到如下的效果 我们先用Ellipse画一个橙色的圆,然后将Canvas的宽度和高度绑定到Ellipse的宽 ...

  9. [示例] Firemonkey 画出 1 点像素的线

    说明:在 Firemonkey 在移动平台 Android & iOS 要直接在 Canvas 画出 1 点像素的线,似乎有点困难,不过利用一点小技巧,还是能达到这个要求的,首先要建立一个 B ...

随机推荐

  1. node Express安装与使用(一)

    首先放上官网地址 http://www.expressjs.com.cn/ 学会查阅官方手册,它是最好的资料. 1.Express安装 首先确定你已经安装了 Node.js,然后去你创建的项目目录下( ...

  2. CSS3 3D变形效果

    CSS3 3D变形效果 CSS3 transform3D变形 transform的含义是:改变,使-变形:转换 三维变换使用基于二维变换的相同属性,如果您熟悉二维变换,你们发现3D变形的功能和2D变换 ...

  3. webapi 发布接口报405错误(angularjs2.0)

    参考链接:http://www.cnblogs.com/shenbin/p/5680976.html web访问接口报405错误,以前的jQuery访问方式访问接口没有问题. 但是换成angularj ...

  4. Ubuntu纯字符界面的一些设置

    由于Ubuntu的纯字符界面不支持中文显示,所以进行了一些配置,为了更好的显示 1. 把环境语言配置为英文 在用户目录下的".bashrc"文件的结尾处添加以下内容,然后重新登录 ...

  5. C++虚表(V-Table)解析

    C++中的虚函数的作用主要是实现了多态,本人通过代码验证的方式了解虚表的结构及在多种继承方式下通过虚表访问子类函数.验证结果如下: 1)无虚函数覆盖的一般继承:可以通过子类的虚表访问父类的函数 2)虚 ...

  6. ubuntu通过虚拟域名访问不了 502 / 网络错误

    ##之前把虚拟机的lamp环境搭建好,但是通过自己windows在浏览器访问一直不能正常运行. 简单说明一下我的相关设置: 1.设置windows的ip映射 C:\Windows\System32\d ...

  7. JSP 学习二

    在基于昨天对JSP学习的基础上,今天我们来学习JSP的指令和JSP 对中文的处理. 一.JSP指令简介 JSP 指令是为JSP引擎而设计,它并不直接产生任何可见的输出,而只是告诉引擎如何处理JSP页面 ...

  8. BZOJ 1033: [ZJOI2008]杀蚂蚁antbuster(模拟)

    坑爹的模拟题QAQ DEBUG多了1kb QAQ 按题意做就行了 注意理解题意啊啊啊啊 尼玛输出忘换行wa了3次QAQ CODE: #include<cstdio>#include< ...

  9. EF CodeFirst下数据库更新

    用EF Code first模式来开发系统,可使用Migrations命令来让数据库自动更新 1.在VS->工具->库程序包管理器->程序包管理控制台 中执行 Enable-Migr ...

  10. 深度神经网络(DNN)的正则化

    和普通的机器学习算法一样,DNN也会遇到过拟合的问题,需要考虑泛化,这里我们就对DNN的正则化方法做一个总结. 1. DNN的L1&L2正则化 想到正则化,我们首先想到的就是L1正则化和L2正 ...