今天闲着没事,就用Dtree写了一直想写的树状结构,虽然网上代码很多,但大多数都解释的不太清楚。
所以我决定把它的使用详细的解释一遍。
看具体实例:
目录的结构:(注意:img目录和test.html文件必须在同一级目录下,且名字为img) (如果不想使用img作为目录名就请自行到dtree.js中更改!)
test.html的代码如下:
<!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>js+css实现树状结构</title> <!-- css文件(*必须)--> <link type="text/css" rel="Stylesheet" href=/blog_article/"css/dtree.css" /> <!--js文件(*必须)--> <script type="text/javascript" src=/blog_article/"js/dtree.js"> </script> </head> <body> <script type="text/javascript"> d = new dTree("d");//创建新的d对象 d.config.useCookies = false; //不使用cookies //d.config.useStatusText = true; //状态栏显示文本 d.config.closeSameLevel = false; //不关闭同一层次其他节点 //d.add(id,pid,name,url,title,target); //id:编号 pid:父节点 name:名称 url:url地址 title:标题 target:跳转框架 mainFrame表示在新的页面打开 //root结点 d.add(0, -1, "张成金","http://www.baidu.com","张成金"); //一级结点 d.add(1, 0, "张成金", "http://www.baidu.com", "张成金", "mainFrame"); d.add(2, 0, "张成金", "http://www.baidu.com", "张成金", "mainFrame"); d.add(3, 0, "张成金", "http://www.baidu.com", "张成金", "mainFrame"); d.add(4, 0, "张成金", "http://www.baidu.com", "张成金", "mainFrame"); d.add(5, 0, "张成金", "http://www.baidu.com", "张成金", "mainFrame"); d.add(6, 0, "张成金", "http://www.baidu.com", "张成金", "mainFrame"); d.add(7, 0, "张成金", "http://www.baidu.com", "张成金", "mainFrame"); //二级结点 d.add(11, 1, "张成金", "http://www.baidu.com", "张成金"); d.add(12, 1, "张成金", "http://www.baidu.com", "张成金"); d.add(21, 2, "张成金", "http://www.baidu.com", "张成金"); d.add(22, 2, "张成金", "http://www.baidu.com", "张成金"); d.add(31, 3, "张成金", "http://www.baidu.com", "张成金"); d.add(32, 3, "张成金", "http://www.baidu.com", "张成金"); d.add(41, 4, "张成金", "http://www.baidu.com", "张成金"); d.add(42, 4, "张成金", "http://www.baidu.com", "张成金"); d.add(43, 4, "张成金", "http://www.baidu.com", "张成金"); d.add(44, 4, "张成金", "http://www.baidu.com", "张成金"); d.add(45, 4, "张成金", "http://www.baidu.com", "张成金"); d.add(51, 5, "张成金", "http://www.baidu.com", "张成金"); d.add(52, 5, "张成金", "http://www.baidu.com", "张成金"); d.add(61, 6, "张成金", "http://www.baidu.com", "张成金"); d.add(62, 6, "张成金", "http://www.baidu.com", "张成金"); d.add(63, 6, "张成金", "http://www.baidu.com", "张成金"); d.add(64, 6, "张成金", "http://www.baidu.com", "张成金"); d.add(65, 6, "张成金", "http://www.baidu.com", "张成金"); d.add(66, 6, "张成金", "http://www.baidu.com", "张成金"); d.add(71, 7, "张成金", "http://www.baidu.com", "张成金"); document.write(d);//输出 d.openAll();//把所有结点都打开 </script> </body> </html>
效果图:
项目下载:
http://download.csdn.net/detail/wyzhangchengjin123/5133342
<完>
DTD已声明
IE
document.documentElement.scrollHeight 浏览器所有内容高度 ,document.body.scrollHeight 浏览器所有内容高度
document.documentElement.scrollTop 浏览器滚动部分高度,document.body.scrollTop 始终为0
document.documentElement.clientHeight 浏览器可视部分高度,document.body.clientHeight 浏览器所有内容高度
FF
document.documentElement.scrollHeight 浏览器所有内容高度 ,document.body.scrollHeight 浏览器所有内容高度
document.documentElement.scrollTop 浏览器滚动部分高度,document.body.scrollTop 始终为0
document.documentElement.clientHeight 浏览器可视部分高度,document.body.clientHeight 浏览器所有内容高度
Chrome
document.documentElement.scrollHeight 浏览器所有内容高度, document.body.scrollHeight 浏览器所有内容高度
document.documentElement.scrollTop 始终为0,document.body.scrollTop 浏览器滚动部分高度
document.documentElement.clientHeight 浏览器可视部分高度,document.body.clientHeight 浏览器所有内容高度
DTD未声明
IE
document.documentElement.scrollHeight 浏览器可视部分高度,document.body.scrollHeight 浏览器所有内容高度
document.documentElement.scrollTop 始终为0,document.body.scrollTop 浏览器滚动部分高度
document.documentElement.clientHeight 始终为0,document.body.clientHeight 浏览器可视部分高度
FF
document.documentElement.scrollHeight 浏览器可视部分高度, document.body.scrollHeight 浏览器所有内容高度
document.documentElement.scrollTop 始终为0,document.body.scrollTop 浏览器滚动部分高度
document.documentElement.clientHeight 浏览器所有内容高度,document.body.clientHeight 浏览器可视部分高度
Chrome
document.documentElement.scrollHeight 浏览器可视部分高度,document.body.scrollHeight 浏览器所有内容高度
document.documentElement.scrollTop 始终为0,document.body.scrollTop 浏览器滚动部分高度
document.documentElement.clientHeight 浏览器所有内容高度,document.body.clientHeight 浏览器可视部分高度
浏览器所有内容高度即浏览器整个框架的高度,包括滚动条卷去部分+可视部分+底部隐藏部分的高度总和
浏览器滚动部分高度即滚动条卷去部分高度即可视顶端距离整个对象顶端的高度。
综上
1、document.documentElement.scrollTop和document.body.scrollTop始终有一个为0,所以可以用这两个的和来求scrollTop
2、scrollHeight、clientHeight 在DTD已声明的情况下用documentElement,未声明的情况下用body
3、document.documentElement.scrollTop在未声明的情况下始终为0,所以可以用来判断是否声明了DTD;
所以,判断滚动条是否已拉到页面最底部,可以用如下代码
var marginBot = 0;
if (document.documentElement.scrollTop){
marginBot = document.documentElement.scrollHeight - (document.documentElement.scrollTop+document.body.scrollTop)- document.documentElement.clientHeight;
} else {
marginBot = document.body.scrollHeight - document.body.scrollTop- document.body.clientHeight;
}
if(marginBot<=0) {
//do something
}
}
本文链接
简介
光线追踪(ray tracing)(也叫raytracing或者光束投射法)是一个在二维(2D)屏幕上呈现三维(3D)图像的方法。为了尝试光线追踪算法,并且尽可能得保证javascript代码精炼,我做了一些尝试。
射线与球体相交检测
最开始尝试了射线与球体的相交检测(不计算交点),只判断相交还是未相交。代码如下所示:
var Vector3 = function (x, y, z) { this.x = x; this.y = y; this.z = z; };Vector3.prototype ={
dot: function (v) { return this.x * v.x + this.y * v.y + this.z * v.z; },
sub: function (v) { return new Vector3(this.x - v.x, this.y - v.y, this.z - v.z); },
normalize: function () { return this.divideScalar(this.length()); },
divideScalar: function (s) { return new Vector3(this.x/s, this.y/s, this.z/s); },
length: function () { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z); },
sqrDistanceToline:function(a,b){
var ab = b.sub(a), ac = this.sub(a), bc = this.sub(b);
var e = ac.dot(ab.normalize());
var f = ac.length();
return f * f - e * e;
}
} .csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }
其中sqrDistanceToline为计算点到直线之间的距离的平方(开跟号性能损耗大)。使用如下:
ball.p.sqrDistanceToline(v, camera.p) < sqrBallR其中v是屏幕上的点的坐标,camera.p为视点的坐标,ball.p为球体中心坐标,sqrBallR为球体半径的平方。当上面返回true时,判定为相交;反之亦然。
相交测试
for (var y = 0; y < canvas.height; y++) {for (var x = 0; x < canvas.width; x++) {
var v = new Vector3(-canvas.width / 2 + x, canvas.height - y, 0);
var cv = new Vector3(camera.p.y * v.x / (camera.p.y - v.y), 0, camera.p.z * v.y / (v.y - camera.p.y));
if (cv.z > -planeLength && cv.z < 0) {
if (ball.p.sqrDistanceToline(v, camera.p) < sqrBallR) {
pixels[i] = pixels[i + 1] = pixels[i + 2] = 111;
} else {
pixels[i] = pixels[i + 1] = pixels[i + 2] = (Math.ceil(cv.x / sideLength) + Math.ceil(cv.z / sideLength)) % 2 === 0 ? 148 : 0;
}
pixels[i + 3] = 255 * (planeLength - Math.abs(cv.z)) / planeLength;
}
i += 4;
}
}
由于没有获取交点坐标,无法计算视点到球体上点的距离,所以无法进行球体深度渲染。所以得到了以下的图像:
获取交点
所以现在目的很明确,不仅要判定相交不相交,还需要找到交点的坐标。当然,上面的方法不是一无是处,可以进行一些初步坐标的筛选(如果性能好于找交点计算一个数量级的话,这个待测试)。那么怎么获取射线与球体的交点呢?该点要满足以下两个条件:
1.交点在在光线上
x=S+dt
2.交点在球上
|x-C|=r
C 表示球心,r 表示半径,光线起点是 S,方向是 d(单位向量),交点 x。
所以得到:
简化 ,
那么 ,
所以
最后得到:
所有小球的代码如下所示:
var Ball = function (p, r) {this.p = p;
this.r = r;
this.sqrR = this.r * this.r;
}
Ball.prototype = {
intersect: function (p1, p2) {
var v = p1.sub(this.p);
var a0 = v.sqrLength() - this.sqrR;
var np = p2.sub(p1).normalize();
var dotV = np.dot(v);
if (dotV <= 0) {
var discr = dotV * dotV - a0;
if (discr >= 0) {
return p1.add(np.multiplyScalar(-dotV - Math.sqrt(discr)));
}
}
return null;
}
}.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, "Courier New", courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }
拿到了交点坐标,现在可以做深度渲染: