站内搜索: (仅支持单关键字)
用HTML5 Canvas制作摆动的树
下载源代码
〖 作者:cyclegtx 〗〖 发布日期:2014-07-05 〗
根据工作的需要,制作一个摆动的树做为页面的背景。为了增加页面的交互性,我又为背景中的树增加了鼠标(触控)事件,使他能够根据鼠标(触控)做出相应的动作,当手指做上下或者左右滑动的时候树会跟着摆动。先看看最终效果。
Step1完成HTML页面,新建一个Tree类
完成HTML页面后新建一个Tree类用来记录树的各个属性。其中x,y为树根部的坐标值,branchLen,branchWidth分别是树枝的长度与宽度,depth为树枝的层数,canvas用来接页面中的canvas元素(默认是ID为canvas的元素)。
<html>
<meta charset="utf-8" />
<head>
<style>
body {
margin: 0;
background: #7ACFFA;
}
#canvas {
position: absolute;
top: 0; left: 0;
}
</style></head><body>
<canvas id="canvas" width="1" height="1"></canvas>
<script type='text/javascript'>
windowrequestAnimFrame = (function(){
return windowrequestAnimationFrame ||
windowwebkitRequestAnimationFrame ||
windowmozRequestAnimationFrame ||
function( callback ){
windowsetTimeout(callback, 1000 / 60);
};
})();
var canvas = documentgetElementById('canvas');
var ctx = canvasgetContext('2d');
canvaswidth = windowinnerWidth;
canvasheight = windowinnerHeight;
function Tree(x,y,branchLen,branchWidth,depth,canvas){
thiscanvas = canvas || documentgetElementById('canvas');
thisctx = thiscanvasgetContext('2d');
thisx = x||0;
thisy = y||0;
thisbranchLen = branchLen||0;
thisbranchWidth = branchWidth||0;
var depth = depth || 5;
}
</script>
</body></html>
Step2添加drawRoot方法,用来绘制树干
首先在drawRoot中画第一个枝干。drawRoot的参数意义同上。并且在Tree类的构造函数中运行drawRoot并把Tree接受到的参数传入。最后new一个Tree类,使树根位于屏幕的底部正中心,树枝长100px,树枝宽度为8px,树枝层数为8层(暂时用不上)。
var atree = new Tree(canvaswidth/2-4,canvasheight,100,8,8,canvas);
在drawRoot中我们需要用lineTo()画出树枝。树枝的起始的坐标值(x,y)已经给出,结束的坐标值(toX,toY)需要进行计算。第一个画的是树干,由于树干垂直于地面所以结束坐标toX等于初始坐标x,而结束坐标toY等于初始y减去树干长度branchLen(注意坐标的0,0点在canvas的左上角)。
var toX = x;var toY = y-branchLen;
function Tree(x,y,branchLen,branchWidth,depth,canvas){
thiscanvas = canvas || documentgetElementById('canvas');
thisctx = thiscanvasgetContext('2d');
thisx = x||0;
thisy = y||0;
thisbranchLen = branchLen||0;
thisbranchWidth = branchWidth||0;
var depth = depth || 5;
thisdrawRoot(thisx,thisy,thisbranchLen,thisbranchWidth);
}
TreeprototypedrawRoot = function(x,y,branchLen,branchWidth){
var toX = x;
var toY = y-branchLen;
thisctxsave();
thisctxstrokeStyle="rgba(37, 141, 194, 093)";
thisctxbeginPath();
thisctxlineCap = "butt";
thisctxlineJoin="round";
thisctxlineWidth = branchWidth;
thisctxmoveTo(x,y);
thisctxlineTo(toX,toY);
thisctxclosePath();
thisctxstroke();
thisctxrestore();
}
var atree = new Tree(canvaswidth/2-4,canvasheight,100,8,8,canvas);
运行代码:
Step3添加drawBranch方法,用来绘制树枝
drawBranch同样是根据初始与结束坐标画出一条直线代表树枝。与树干不同的是树枝不再是垂直与地面而是与树干保持一定的角度,而且树枝的初始值是树干的结束点(toX,toY)。所以在drawBranch中我们加入新参数angle用来表示树枝与树干的垂直夹角α,这样就可以根据α算出toX与toY。请看图。
这样我们在画完树干后再分别画两个不同角度的树枝,一个是30°一个-30°。并将传给树枝的宽度branchWidth减小一个像素,使其与树干粗细不同。
TreeprototypedrawRoot = function(x,y,branchLen,branchWidth){
var toX = x;
var toY = y-branchLen;
thisctxsave();
thisctxstrokeStyle="rgba(37, 141, 194, 093)";
thisctxbeginPath();
thisctxlineCap = "butt";
thisctxlineJoin="round";
thisctxlineWidth = branchWidth;
thisctxmoveTo(x,y);
thisctxlineTo(toX,toY);
thisctxclosePath();
thisctxstroke();
thisctxrestore();
thisdrawBranch(toX,toY,branchLen,branchWidth-1,30);
thisdrawBranch(toX,toY,branchLen,branchWidth-1,-30);
}
TreeprototypedrawBranch = function(x,y,branchLen,branchWidth,angle){
var angle = angle || 0;
var radian = (90-angle)(MathPI/180);
var toX = x+Mathcos(radian)branchLen;
var toY = y-Mathsin(radian)branchLen;
thisctxsave();
thisctxstrokeStyle="rgba(37, 141, 194, 093)";
thisctxbeginPath();
thisctxlineCap = "butt";
thisctxlineJoin="round";
thisctxlineWidth = branchWidth;
thisctxmoveTo(x,y);
thisctxlineTo(toX,toY);
thisctxclosePath();
thisctxstroke();
thisctxrestore();
}
运行代码:
Step4修改drawBranch函数,重复画树枝
在drawBranch函数的最后再次调用两次drawBranch
thisdrawBranch(toX,toY,branchLen,branchWidth-1,angle+30);
thisdrawBranch(toX,toY,branchLen,branchWidth-1,angle-30);
使其调用自己完成递归,注意这里传入的角度是在之前的角度的基础上在增加或者减少30度。
为了使递归停下来我们需要一个停止条件,就是之前一直没有用到的depth参数。我们在每次画下一层之前使其减1表示已经完成了一层树枝的绘制,直至depth减小到0表示绘制完所有的层数。
function Tree(x,y,branchLen,branchWidth,depth,canvas){
thiscanvas = canvas || documentgetElementById('canvas');
thisctx = thiscanvasgetContext('2d');
thisx = x||0;
thisy = y||0;
thisbranchLen = branchLen||0;
thisbranchWidth = branchWidth||0;
var depth = depth || 5;
thisdrawRoot(thisx,thisy,thisbranchLen,thisbranchWidth,depth);
}
TreeprototypedrawRoot = function(x,y,branchLen,branchWidth,depth){
var toX = x;
var toY = y-branchLen;
var depth = depth||5;
thisctxsave();
thisctxstrokeStyle="rgba(37, 141, 194, 093)";
thisctxbeginPath();
thisctxlineCap = "butt";
thisctxlineJoin="round";
thisctxlineWidth = branchWidth;
thisctxmoveTo(x,y);
thisctxlineTo(toX,toY);
thisctxclosePath();
thisctxstroke();
thisctxrestore();
depth--;
if(depth>0){
thisdrawBranch(toX,toY,branchLen,branchWidth-1,30,depth);
thisdrawBranch(toX,toY,branchLen,branchWidth-1,-30,depth);
}
}
TreeprototypedrawBranch = function(x,y,branchLen,branchWidth,angle,depth){
var angle = angle || 0;
var radian = (90-angle)(MathPI/180);
var toX = x+Mathcos(radian)branchLen;
var toY = y-Mathsin(radian)branchLen;
thisctxsave();
thisctxstrokeStyle="rgba(37, 141, 194, 093)";
thisctxbeginPath();
thisctxlineCap = "butt";
thisctxlineJoin="round";
thisctxlineWidth = branchWidth;
thisctxmoveTo(x,y);
thisctxlineTo(toX,toY);
thisctxclosePath();
thisctxstroke();
thisctxrestore();
depth--;
if(depth>0){
thisdrawBranch(toX,toY,branchLen,branchWidth-1,angle+30,depth);
thisdrawBranch(toX,toY,branchLen,branchWidth-1,angle-30,depth);
}
}
运行代码:
由于树之间角度过大,而且所有树枝长度都相等,看起来并不像一棵树。所以我们需要在Tree的构造函数中加入几个参数用来调整树的姿态。
function Tree(x,y,branchLen,branchWidth,depth,canvas){
thisbranchLenFactor = 08;
thisrootLenFactor = 12;
thisbranchAngle = 20;
}
branchLenFactor:画每一层树枝的时候乘在branchLen上面,用来控制树枝长度。rootLenFactor:画树根的时候乘在branchLen上面,用来控制树根长度。branchAngle: 用来控制树枝之间的角度
TreeprototypedrawRoot = function(x,y,branchLen,branchWidth,depth){
var toX = x;
var toY = y-branchLenthisrootLenFactor;
var depth = depth||5;
thisctxsave();
thisctxstrokeStyle="rgba(37, 141, 194, 093)";
thisctxbeginPath();
thisctxlineCap = "butt";
thisctxlineJoin="round";
thisctxlineWidth = branchWidth;
thisctxmoveTo(x,y);
thisctxlineTo(toX,toY);
thisctxclosePath();
thisctxstroke();
thisctxrestore();
depth--;
if(depth>0){
thisdrawBranch(toX,toY,branchLenthisbranchLenFactor,branchWidth-1,thisbranchAngle,depth);
thisdrawBranch(toX,toY,branchLenthisbranchLenFactor,branchWidth-1,-thisbranchAngle,depth);
}
}
TreeprototypedrawBranch = function(x,y,branchLen,branchWidth,angle,depth){
var angle = angle || 0;
var radian = (90-angle)(MathPI/180);
var toX = x+Mathcos(radian)branchLen;
var toY = y-Mathsin(radian)branchLen;
thisctxsave();
thisctxstrokeStyle="rgba(37, 141, 194, 093)";
thisctxbeginPath();
thisctxlineCap = "butt";
thisctxlineJoin="round";
thisctxlineWidth = branchWidth;
thisctxmoveTo(x,y);
thisctxlineTo(toX,toY);
thisctxclosePath();
thisctxstroke();
thisctxrestore();
depth--;
if(depth>0){
thisdrawBranch(toX,toY,branchLenthisbranchLenFactor,branchWidth-1,angle+thisbranchAngle,depth);
thisdrawBranch(toX,toY,branchLenthisbranchLenFactor,branchWidth-1,angle-thisbranchAngle,depth);
}
}
运行代码:(查看效果)
这么多要求。又不要这又不要那的。本来我有很多代码。但是怕不符合你要求,还是不提供给你为好。
因学习网页前端制作,所以需要一些源码。1可以只有html+css的小项目(或者是简单的案例,含js也可以),例如只有几个简单的页面也可以。2或者是一些小游戏,不要太复杂的。3也可以是有关这方面的书籍(pdf格式的)。4相关手册文档也可以。5相关视频(html+css不需要视频了,html5跟css3的除外)。注意:1如果是提供下载链接的,请先附上预览图,不要给那些已经失效的链接。2如果是提供源码,请不要给那些没有良好书写习惯的代码(代码没有缩进,书写不规范,不便于阅读)。3给下载链接的,请不要给那些乱七八糟的网站(广告满天飞,下载链接很隐蔽)。4不要发表个人看法,提供素材便可。不知道你是做开发还是想直接使用分享位置的功能
做开发的话, h5需要服务器使用ssl的加密链接,才能使用精准定位,否则定位是根据ip返回的,只精确到城市
<script>
var x=documentgetElementById("demo");
function getLocation()
{
if (navigatorgeolocation)
{
navigatorgeolocationgetCurrentPosition(showPosition);
}
else{xinnerHTML="Geolocation is not supported by this browser";}
}
function showPosition(position)
{
xinnerHTML="Latitude: " + positioncoordslatitude +
"<br />Longitude: " + positioncoordslongitude;
}
</script>
手机上使用地图功能, 打开 百度地图 或者其它地图的官网, 都可以直接使用, 只不过功能没有app的强大
欢迎分享,转载请注明来源:表白网
评论列表(0条)