var Vector3 = function (n, t, i) { this.x = n, this.y = t, this.z = i }, Cube, Ball; Vector3.prototype = { dot: function (n) { return this.x * n.x + this.y * n.y + this.z * n.z }, sub: function (n) { return new Vector3(this.x - n.x, this.y - n.y, this.z - n.z) }, normalize: function () { return this.divideScalar(this.length()) }, divideScalar: function (n) { return new Vector3(this.x / n, this.y / n, this.z / n) }, length: function () { return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z) }, sqrLength: function () { return this.x * this.x + this.y * this.y + this.z * this.z }, multiplyScalar: function (n) { return new Vector3(this.x * n, this.y * n, this.z * n) }, add: function (n) { return new Vector3(this.x + n.x, this.y + n.y, this.z + n.z) }, cross: function (n) { return new Vector3(-this.z * n.y + this.y * n.z, this.z * n.x - this.x * n.z, -this.y * n.x + this.x * n.y) }, round: function () { return new Vector3(Math.round(this.x), Math.round(this.y), Math.round(this.z)) }, distanceTo: function (n) { return Math.sqrt(this.distanceToSquared(n)) }, distanceToSquared: function (n) { var t = this.x - n.x, i = this.y - n.y, r = this.z - n.z; return t * t + i * i + r * r } }, Cube = function (n, t) { this.center = n, this.length = t, this.hLength = t / 2, this.minX = this.center.x - this.hLength, this.maxX = this.center.x + this.hLength, this.minY = this.center.y - this.hLength, this.maxY = this.center.y + this.hLength, this.minZ = this.center.z - this.hLength, this.maxZ = this.center.z + this.hLength }, Cube.prototype.intersect = function (n) { var i = n.direction, r = n.origin, t = [], u = this.getTIntersectPlane(r, i, "z", this.center.z - this.hLength), f = this.getTIntersectPlane(r, i, "z", this.center.z + this.hLength), e = this.getTIntersectPlane(r, i, "x", this.center.x - this.hLength), o = this.getTIntersectPlane(r, i, "x", this.center.x + this.hLength), s = this.getTIntersectPlane(r, i, "y", this.center.y - this.hLength), h = this.getTIntersectPlane(r, i, "y", this.center.y + this.hLength); if (u && t.push(u), f && t.push(f), e && t.push(e), o && t.push(o), s && t.push(s), h && t.push(h), t.length === 1) return t[0].cp; if (t.length === 2) { if (t[0].t > t[1].t) return t[1].cp; if (t[1].t > t[0].t) return t[0].cp } return null }, Cube.prototype.getTIntersectPlane = function (n, t, i, r) { var f, u; return i === "z" && (f = (r - n.z) / t.z, u = n.add(t.multiplyScalar(f)), u.x < this.maxX && u.x > this.minX && u.y < this.maxY && u.y > this.minY) ? { t: f, cp: u } : i === "x" && (f = (r - n.x) / t.x, u = n.add(t.multiplyScalar(f)), u.z < this.maxZ && u.z > this.minZ && u.y < this.maxY && u.y > this.minY) ? { t: f, cp: u } : i === "y" && (f = (r - n.y) / t.y, u = n.add(t.multiplyScalar(f)), u.x < this.maxX && u.x > this.minX && u.z < this.maxZ && u.z > this.minZ) ? { t: f, cp: u } : null }, Cube.prototype.intersectFrontPlane = function (n) { var t = this.getTIntersectPlane(n.origin, n.direction, "z", this.center.z + this.hLength); return t ? t.cp : null }, Ball = function (n, t) { this.p = n, this.r = t, this.sqrR = this.r * this.r }, Ball.prototype = { intersect: function (n) { var r = n.origin.sub(this.p), u = r.sqrLength() - this.sqrR, f = n.direction, t = f.dot(r), i; return t = 0) ? n.getPoint(-t - Math.sqrt(i)) : null } }, Ray3 = function (n, t) { this.origin = n, this.direction = t }, Ray3.prototype = { getPoint: function (n) { return this.origin.add(this.direction.multiplyScalar(n)) } }; .filter_input{width: 150px;min-height: 26px;padding: 3px 10px;font-size: 13px;border-radius: 12px;min-height: 34px;padding: 7px 8px;outline: none;color: #333;background-color: #fff;background-repeat: no-repeat;background-position: right center;border: 1px solid #ccc;box-shadow: inset 0 1px 2px rgba(0,0,0,0.075);-moz-box-sizing: border-box;box-sizing: border-box;transition: all 0.15s ease-in;-webkit-transition: all 0.15s ease-in 0;vertical-align: middle;} .button, .minibutton {position: relative;display: inline-block;padding: 7px 15px;font-size: 13px;font-weight: bold;color: #333;text-shadow: 0 1px 0 rgba(255,255,255,0.9);white-space: nowrap;background-color: #eaeaea;background-image: -moz-linear-gradient(#fafafa, #eaeaea);background-image: -webkit-linear-gradient(#fafafa, #eaeaea);background-image: linear-gradient(#fafafa, #eaeaea);background-repeat: repeat-x;border-radius: 3px;border: 1px solid #ddd;border-bottom-color: #c5c5c5;box-shadow: 0 1px 3px rgba(0,0,0,0.075);vertical-align: middle;cursor: pointer;-webkit-touch-callout: none;-webkit-user-select: none;-khtml-user-select: none;-moz-user-select: none;-ms-user-select: none;user-select: none;-webkit-appearance: none;text-decoration: none;} .button:hover, .button:active, .minibutton:hover, .minibutton:active {color: #fff;text-decoration: none;text-shadow: 0 -1px 0 rgba(0,0,0,0.25);background-color: #3072b3;background-image: -moz-linear-gradient(#599bcd, #3072b3);background-image: -webkit-linear-gradient(#599bcd, #3072b3);background-image: linear-gradient(#599bcd, #3072b3);background-repeat: repeat-x;border-color: #2a65a0;}
简介
本文在光线追踪的基础之上,为了追求渲染速度和效率,去除了光线的反射、去除了透视投影(如我前面两篇干货8和干货9,所以渲染虽然是3D场景,其实不是真实看到的,但不影响实验),进行了一些有趣的尝试。此文将分享这两天尝试的成果:3D雕刻。
3D雕刻,顾名思义--在3D物体上进行雕刻,所以要达到的目的不仅仅是渲染几种常见的几何形状,还包括在几何形状上绘制、绘画等等。本文依旧使用大家熟悉的javascript语言,HTML5 canvas作为显示屏。
在读本文之前,最好可以了解一些下面这些基础知识:
正交投影
线性代数基础
数据结构和算法
javascript基础知识
射线、AABB、面、球体之间碰撞检测算法
透视投影(本文虽然略去了canvas和影像屏的mapping,但是最好了解)
Vector3的几何意义(使用时候要区分什么时候代表点,什么时候代表向量)
Canvas像素操作getImageData/putImageData/跨域、渐变createLinearGradient、绘制文字fillText、图片drawImage/base64等
如果不了解上面相关的内容,可以做一些search,或者通过本文做一些熟悉。
Vector3类
这个类是最常用的类了。最重要的一点就使用的时候理解它是代表点还是向量,以及各个方法的几何意义。
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); },
sqrLength: function () { return this.x * this.x + this.y * this.y + this.z * this.z; },
multiplyScalar: function (s) { return new Vector3(this.x * s, this.y * s, this.z * s); },
add: function (v) { return new Vector3(this.x + v.x, this.y + v.y, this.z + v.z); },
cross: function (v) { return new Vector3(-this.z * v.y + this.y * v.z, this.z * v.x - this.x * v.z, -
- 使用 Toolbar.js 实现超酷的 Tooltip 风格工具栏
- Textillate.js – 实现 CSS3 文本动画的简单插件
- 使用 ThreeSixty 创建 360 度全景图片预览效果
- 实用锦囊:推荐一款非常棒的响应式网页测试工具
- 令人印象深刻的 jQuery 模态框插件 – iLightBox
这个显示速度基本是与鼠标移动同步的,但是绝大多数网站的下拉菜单在显示子菜单时会都有一定的延迟,但是 Amazon 的下拉菜单没有这个延迟,而且子菜单也不会在不应该的时候消失。它是怎样做到这一点的呢?答案是通过探测鼠标移动的方向和轨迹。
想象在鼠标当前的位置和子菜单的左上角和左下角之间画一个三角形。如果鼠标在这个三角形的范围之内移动,那用户很有可能是在把鼠标从主菜单向子菜单里挪,所以不要立刻更新子菜单。但是如果鼠标挪动到这个三角形之外,则可以马上更新子菜单。这就是 Amazon 主页反应速度超快的下拉菜单背后的算法。
如果想把这个菜单逻辑运用到你的网站上,可以使用 Khan Academy 工程师 Ben Kamens 写的 jQuery 插件—— menu-aim。
GitHub 插件下载
- Respond.js – 让IE6-8支持 CSS3 Media Query
- Debuggex – 超好用的正则表达式可视化调试工具
- 前端文摘——网页图片优化的实用工具和技巧分享
- Lazy Line Painter – 有趣的 jQuery 路径动画插件
- Zepto.js – 为现代浏览器而生的轻量JavaScript库
本文链接:实现 Amazon 超快反应速度下拉菜单的 jQuery 插件
编译来源:梦想天空 ◆ 关注Web前端开发技术 ◆ 分享网页设计资源
本文链接
在做表单页面的时候,想判断2个js对象,是不是所有完全相同。
这里是stackoverflow上的解决办法,在这里记录一下。
原文地址: http://stackoverflow.com/questions/1068834/object-comparison-in-javascript
{
var p;
for(p in this) {
if(typeof(x[p])=='undefined') {return false;}
}
for(p in this) {
if (this[p]) {
switch(typeof(this[p])) {
case 'object':
if (!this[p].equals(x[p])) { return false; } break;
case 'function':
if (typeof(x[p])=='undefined' ||
(p != 'equals' && this[p].toString() != x[p].toString()))
return false;
break;
default:
if (this[p] != x[p]) { return false; }
}
} else {
if (x[p])
return false;
}
}
for(p in x) {
if(typeof(this[p])=='undefined') {return false;}
}
return true;
}
本文链接