做自由落体运动的JSF组件,使用javascript打造富有个性的漂亮组件——QFaces
2010-09-14 13:44:06 来源:WEB开发网QFaces.facesMakeFrame(id)
这个函数可以给任意组件id添加一个边框,包括div,table,可见的,不可见的等,甚至button,input...这个函数相对简单得多,但是很方便,效果也非常好,在QFaces组件库下可以直接调用,里面捆绑了8张小png作为组件边框,这是我在photoshop中做的图,然后切割而成的,可以很方便的替换,共4个角4个边。如果单独使用,那么需要指定这些图片的位置。并约束一下左上角及右下角的宽高就可以了,。单用CSS也可以做出圆角及阴影效果,但是再怎么做也没有photoshop做出来的效果好。
函数原形:
QFaces.accDisplay = function(id, action, direction, G)
QFaces.accDisplay = function(id, action, direction, G) {
var mydiv = QFaces.getComponent(id);
if (mydiv.locked) {
return;
} else {
mydiv.locked = true; // 锁定source,避免快速无限点击。
}
// 这里表示了从原始宽高度的0倍 -> 运行到原始宽高 -> 然后跳回原来的0.8倍 -> 再回到原来的宽高度。
// 配合自由落体 (S = v0t * 1/2att),看起来就是一个弹跳过程。
var stepArr = new Array();
if (action == "show" || action == null) {
stepArr[0] = 0;
stepArr[1] = 1.2;
stepArr[2] = 0.8;
stepArr[3] = 1;
} else if (action == "hide") {
stepArr[0] = 1;
stepArr[1] = 1.2;
stepArr[2] = 0;
}
// 初始化变量.高度与G的比例 250xp : 0.006S
var size = QFaces.getSize(id);
var stretchObj = new StretchObject();
stretchObj.source = mydiv;
stretchObj.action = (action == null ? "show" : action); // 确定方向
stretchObj.originalLeft = mydiv.offsetLeft;
stretchObj.originalWidth = size[0];
stretchObj.originalHeight = size[1];
stretchObj.stepArr = stepArr;
stretchObj.interval = 10;
// 以一个比率动态改变加速度大小,避免大区块的动画时间过长
// stretchObj.G = 0.006;
stretchObj.G = (stretchObj.originalHeight * 0.006 / 250);
if (direction == null || direction == "height" || direction == "both") {
stretchObj.displayHeight = true;
}
if (direction == "width" || direction == "both") {
stretchObj.displayWidth = true;
}
if (G != null) {stretchObj.G = G;} // 如果用户指定了加速度
stretchObj.init(); // 初始化
travel(stretchObj); // Start display
function travel(obj) {
// 累计单步的执行时间,并计算距离。
obj.stepTimeUsed += obj.interval;
obj.stepDistance = obj.v0 * obj.stepTimeUsed + 0.5 * obj.G * obj.stepTimeUsed * obj.stepTimeUsed;
// 设置source的位置,高宽度。
obj.setSize(obj.stepWidth + obj.stepDistance, obj.stepHeight + obj.stepDistance);
// 运行完毕后解锁source,并跳出。
if (obj.isOver()) {
obj.setSize(obj.originalWidth * obj.stepArr[obj.stepArr.length - 1], obj.originalHeight * obj.stepArr[obj.stepArr.length - 1]);
// 如果是收缩,则清理数据后隐藏,并且设回原始位置
if (obj.action == "hide") {
obj.source.style.left = obj.originalLeft + "px";
obj.source.style.width = "";
obj.source.style.height = "";
obj.source.style.display = "none";
}
obj.source.locked = false;
return;
}
// 单步运行完毕
if (obj.isStepOver()) {
obj.stepOver();
}
QFaces.setTimeout(travel, obj.interval, obj);
}
function StretchObject() {
this.source = null; // 绑定的界面控件
this.action = null;
this.originalLeft = null; // 原始的位置偏移
this.originalWidth = null; // 原始宽度
this.originalHeight = null; // 原始高度
this.displayWidth = false;
this.displayHeight = false;
this.stepArr = null; // 要运行的数组
this.v0 = null;
this.v1 = null;
this.step = 1;
this.stepWidth = 0; // 步宽,每次方向改变时都会改变。
this.stepHeight = 0; // 同上
this.stepTimeTotal = 0; // 每次落下或弹起所需要的总时间。
this.stepTimeUsed = 0; // 每次落下或弹起的时间累计。
this.stepDistance = 0; // 在stepTimeUsed下所运行的距离
this.G = 0.006; // 重力加速度,为什么不是9.8米/秒?因为这里不是地球 ————是QFaces星球
this.interval = 10;
this.isOver = function() {
return (this.step > this.stepArr.length - 1);
}
this.isZoomOut = function() {
return (this.stepArr[this.step] > this.stepArr[this.step - 1]);
}
this.isStepOver = function() {
if (this.stepTimeUsed >= this.stepTimeTotal) {return true;}// 这里防止无限止伸缩。
var currentHeight = this.stepHeight + this.stepDistance;
if (this.isZoomOut()) {
return currentHeight >= this.originalHeight * this.stepArr[this.step];
} else {
return currentHeight <= this.originalHeight * this.stepArr[this.step];
}
}
this.setSize = function(width, height) {
if (this.displayWidth && width >= 0)
this.source.style.width = width + "px";
if (this.displayHeight && height >= 0)
this.source.style.height = height + "px";
if (this.displayWidth && width >= 0) {// 重新设置source的位置偏移。
this.source.style.left = (this.originalLeft + (this.originalWidth - width) * 0.5) + "px";
}
}
this.calculateStepTimeTotal = function() {
if (this.stepArr[this.step] != null) {
var nextS = Math.abs(this.originalHeight * (this.stepArr[this.step] - this.stepArr[this.step - 1]));
if (this.isZoomOut()) { // 下降过程 s = 0.5gtt;
this.stepTimeTotal = Math.sqrt(2 * nextS / this.G);
} else {// G = (v1 - v0)/t
this.stepTimeTotal = Math.abs((this.v0 - this.v1) / this.G);
}
} else {
this.stepTimeTotal = 0;
}
}
this.stepOver = function() {
var isZoomOut_previous = this.isZoomOut();
this.stepWidth = this.originalWidth * this.stepArr[this.step];
this.stepHeight = this.originalHeight * this.stepArr[this.step];
this.setSize(this.stepWidth, this.stepHeight);
this.step += 1; // 进入下一阶段
this.stepDistance = 0;
this.stepTimeUsed = 0;
// 特别情况(渐缩):如果前一阶段是下降,并且整个过程是渐缩 。 (s = v0t + 0.5gtt)
if (this.action == "hide") {
if (isZoomOut_previous) {
var zoomInS = Math.abs(this.originalHeight * (this.stepArr[this.step] - this.stepArr[this.step - 1]));
var zoomInT = Math.sqrt(2 * zoomInS / this.G);
this.v0 = this.G * zoomInT; // 用整段最长距离计算从最大位置缩回none时的初速度,瞬速。
this.v0 = this.v0 * -1; // 上升过程,v0必须是负的
this.v1 = 0;
}
} else {// 正常渐展开的过程。
if (isZoomOut_previous) {
this.v0 = this.v1 * -1; // 在落地返弹瞬间,速度达最大,并且末速度变成反弹之后的始速度
this.v1 = 0; // 下一阶段的反弹末速度为0
} else {// 从上升到下降
// 计算下一下降过程需要经过的距离。
var tempS = Math.abs(this.originalHeight * (this.stepArr[this.step] - this.stepArr[this.step - 1]));
var tempT = parseInt(Math.sqrt((2 * tempS / this.G))); // 计算下降需要经过的时间。
var tempGT = this.G * tempT; // 计算末速度。
this.v0 = 0;
this.v1 = tempGT;
}
}
// 计算下一段所需要的时间
this.calculateStepTimeTotal();
}
this.init = function() {
this.source.style.display = "block";
this.source.style.overflow = "hidden";
this.source.style.position = "absolute";
this.source.style.zIndex = QFaces.zIndex++;
this.stepWidth = this.originalWidth * this.stepArr[this.step - 1];
this.stepHeight = this.originalHeight * this.stepArr[this.step - 1];
this.originalLeft = this.source.offsetLeft; // 必须保存原始偏移。
if (this.displayWidth)
this.source.style.width = this.stepWidth + "px";
if (this.displayHeight)
this.source.style.height = this.stepHeight + "px";
var s = this.originalHeight * (this.stepArr[this.step] - this.stepArr[this.step - 1]);
if (this.isZoomOut()) { // 加速
this.v0 = 0;
this.v1 = this.G * parseInt(Math.sqrt((2 * s / this.G)));
} else { // 减速
this.v0 = this.G * parseInt(Math.sqrt(Math.abs(2 * s / this.G))) * -1;
this.v1 = 0;
}
// 计算下一级所需要的时间.
this.calculateStepTimeTotal();
}
}
}
更多精彩
赞助商链接