您的位置:首页 > Web前端 > JavaScript

【CSON原创】javascript实现3D房间

2012-01-31 16:11 218 查看
功能说明:

1.鼠标点击房间内家具则视觉焦点移动到该家具。

2.鼠标点击空白处则视觉移动相应距离。

3.鼠标滚轮控制缩放比例大小。

兼容IE 5 6 7 8 9 10 firefox chrome

(注明:效果参考过cloudgamer的文章3D ROOM/article/4592048.html,并以自己的思路实现。)

效果预览:

由于页面太大,就不直接在这里展示了给出下载地址:点击下载

静态效果图:

View Code

<!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>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>无标题文档</title>
<style>
body{text-align:center;}
#container{position:relative; background-color:black; width:1200px; height:600px; overflow:hidden; cursor:pointer; margin:0 auto;}

</style>
</head>

<body>
<div id="s"></div>
<div id="container">
</div>
</body>
<script>
var room = (function() {

var _room = function(id, options) {
this.init(id, options);

}
_room.prototype = (function() {
var containerPos; //容器位置
var times = 0; //缩放倍数
var scrollable = true; //是否可滚动缩放
var timeId2;
var Tween = {            //缓动对象
linear: function(t, b, c, d) {
return c * t / d + b;
},
easeIn: function(t, b, c, d) {
return c * (t /= d) * t + b;
},
easeOut: function(t, b, c, d) {
return c * ((t = t / d - 1) * t * t + 1) + b;
}

};
var $ = function(id) { return document.getElementById(id); }
var emptyFunction=function(){};

var getContainerPos = function(container) {//获取容器位置
var left = 0;
var top = 0;
while (container.offsetParent) {
left += container.offsetLeft;
top += container.offsetTop;
container = container.offsetParent;

}
return [left, top];

}

var updatePos = function(elem, x, y, scale) {//根据元素的x y坐标 更新元素位置,缩放比和大小
elem._x = x;
elem._y = y;

elem.scale = scale;
if (scale > 1.05) {        //缩放比大于1.05则消失
elem.style.display = 'none';
}
else {
elem.style.display = 'block';
}
elem.style.left = this.centerX + scale * x + 'px';
elem.style.top = this.centerY - scale * y + 'px';
elem.style.width = elem.initWidth * scale + 'px';
elem.style.height = elem.initHeight * scale + 'px';

};

var changeInTween = function(startTime, marginX, marginY, duration) {

var self = this;
var arr=self.arr;
window.clearTimeout(timeId2);
return function() {
var time = new Date().getTime() - startTime;
var distantX = Tween[self.tweenType](time, 0, marginX, duration);
var distantY = Tween[self.tweenType](time, 0, marginY, duration);

if (time <= duration) {
for (var i = 0; i < arr.length; i++) {
var img = arr[i];
updatePos.call(self, img, img.initX + distantX, img.initY + distantY, img.scale); //更新所有元素位置

}
timeId2 = window.setTimeout(arguments.callee, 50);
}
else {
for (var i = 0; i < arr.length; i++) {
var img = arr[i];
img.initX = img._x;
img.initY = img._y;

}
window.clearTimeout(timeId2);
bindClickHandler.call(self);
bindHandlerForAllImg.call(self);

}
}

}

var clickHandler = function() {
var self = this;
return function(eve) {
removeClickHandler();
removeHandlerForAllImg(self.arr);
eve = eve || window.event;
var containerLeft = containerPos[0];
var containerTop = containerPos[1];
var pageX = eve.pageX || eve.clientX + document.documentElement.scrollLeft - document.documentElement.clientLeft;
var pageY = eve.pageY || eve.clientY + document.documentElement.scrollTop - document.documentElement.clientTop;
var marginX = (pageX - containerLeft - self.centerX) * (-1); //鼠标在容器的X坐标
var marginY = (pageY - containerTop - self.centerY); //鼠标在容器的Y坐标

var startTime = new Date().getTime();

changeInTween.call(self, startTime, marginX, marginY, self.moveDuration)();

}

}

var bindClickHandler = function() {//绑定鼠标事件处理程序
$('container').onclick = clickHandler.call(this);
}
var removeClickHandler = function() {//删除鼠标事件处理程序
$('container').onclick = emptyFunction;
}
//是否达到最大值
var hasToMax = function(currentScale, maxScale, minScale, detail) {
return (currentScale >= maxScale && detail < 0) || (currentScale <= minScale && detail > 0) || (currentScale > minScale && currentScale < maxScale)
}

var ScrollHandler = function(self) {

return function(eve) {//绑定鼠标滚动时处理程序,动态改变房子内所有元素缩放比

eve = eve || window.event;
var arr = self.arr;
if (navigator.userAgent.indexOf("Firefox") > 0) {
//如果已到达最大值,只能向负方向滚动缩小比例,如果已到最小值,则只能向正方向滚动扩大比例,如果处于中间值,则正负方向都可以滚动
if (hasToMax(self.currentScale, self.maxScale, self.minScale, eve.detail)) {
times += eve.detail / 3;
scrollable = true;
}
else {
scrollable = false;

}

}
else {
if (hasToMax(self.currentScale, self.maxScale, self.minScale, eve.wheelDelta)) {
times += eve.wheelDelta / 120;
scrollable = true;
}
else {
scrollable = false;

}
}

if (scrollable) {//如果可以滚动缩放
self.currentScale = 0;
for (var i = 0; i < arr.length; i++) {
var newScale = arr[i].initScale + times * 0.02; //更新缩放比scale
(newScale > self.currentScale) && (self.currentScale = newScale); //获取最近图像(最大图像)当前缩放比

updatePos.call(self, arr[i], arr[i]._x, arr[i]._y, newScale);

}
}
eve.preventDefault ? eve.preventDefault() : eve.returnValue = false;
}

};

var bindScrollHandler = function() {    //绑定鼠标滚动处理程序

if (navigator.userAgent.indexOf("Firefox") < 0) {
document.onmousewheel = ScrollHandler(this);

}
else {
document.addEventListener("DOMMouseScroll", ScrollHandler(this), false);
}
}
var removeScrollHandler = function() {//取消鼠标滚动处理程序
if (navigator.userAgent.indexOf("Firefox") < 0) {
document.onmousewheel = emptyFunction;

}
else {
document.removeEventListener("DOMMouseScroll", ScrollHandler, false);
}
}

var setImgPositionInTween = function(img, xMargin, yMargin, scaleMargin, target) {//以缓动方式改变元素位置
var startTime = img.startTime;
var duration = this.selectedDuration; //缓动总耗时
var tweenType = this.tweenType;
var time = new Date().getTime() - startTime; //缓动经过时间

var bX = img.initX;
var dX = xMargin;

var bY = img.initY;
var dY = yMargin;

var bScale = img.initScale;
var dScale = scaleMargin;

var newX = Tween[tweenType](time, bX, dX, duration);
var newY = Tween[tweenType](time, bY, dY, duration);
var newScale = Tween[tweenType](time, bScale, dScale, duration);
updatePos.call(this, img, newX, newY, newScale);

}

var bindHandlerForImage = function(img) {//为图片点击绑定事件处理程序
var self = this;
img.onclick = function(eve) {
eve = eve || window.event;
var enhance; //是否放大(否则缩小)
var target = eve.target || eve.srcElement;
//如果该图片的缩放比已经为1,或点击的是容器,或timeId不为undefined(之前的选择动画还没结束)则返回
if (target.initScale == 1 || target == self.container || typeof timeId != 'undefined') {
return;
}
removeClickHandler(); //选中图片期间,取消鼠标移动处理程序
removeScrollHandler();  //选中图片期间,取消鼠标滚动处理程序

var scaleMargin = 1 - target.scale; //所选中图片的缩放比距离1的差距
var newX = target.initWidth / 2 * (-1); //被选中的图片的新X坐标,处于容器正中央
var newY = target.initHeight / 2; //被选中的图片的新Y坐标,处于容器正中央
var xMargin = newX - img._x; //到新位置X方向所要移动的位移
var yMargin = newY - img._y; //到新位置Y方向所要移动的位移

var arr = self.arr;
for (var i = 0; i < arr.length; i++) {//用现在的xy坐标和scale重新设置initX,initY和initScale
arr[i].initX = arr[i]._x;
arr[i].initY = arr[i]._y;
arr[i].initScale = arr[i].scale;
}
times = 0;
target.scale >= 1 ? enhance = false : enhance = true; //如果所选中scale大于1,则需要缩小,小于1,则要放大
timeId = window.setTimeout(function() {

for (var i = 0; i < arr.length; i++) {
var ele = arr[i];
if (typeof arr[i].startTime == 'undefined') {
ele.startTime = new Date().getTime();

}

setImgPositionInTween.call(self, ele, xMargin, yMargin, scaleMargin, target); //缓动方式改变元素位置

}

if ((enhance && target.scale >= 1) || (!enhance && target.scale < 1)) {

for (var i = 0; i < arr.length; i++) {
var ele = arr[i];
ele.startTime = undefined;
ele.initScale = ele.scale;
ele.initX = ele._x;
ele.initY = ele._y;

}
window.clearTimeout(timeId);
timeId = undefined;
bindClickHandler.call(self);
bindScrollHandler.call(self);
}
else {
window.setTimeout(arguments.callee, 20);
}
}, 20);

}

}
var removeHandlerForAllImg=function(arr){//移除所有图片选择处理程序
for(var i=0;i<arr.length;i++){
arr[i].onclick=emptyFunction;
}

}
var bindHandlerForAllImg=function(){//绑定所有图片选择处理程序
for(var i=0;i<this.arr.length;i++){
bindHandlerForImage.call(this,this.arr[i]);
}

}

return {
init: function(id, options) {//初始化
options = options || {};
this.container = $(id || 'container'); //容器
this.arr = []; //保存所有元素
this.centerX = this.container.clientWidth / 2; //原点坐标的left
this.centerY = this.container.clientHeight / 2; //原点坐标的top
this.maxScale = options.maxScale || 1.5; //最近图像最大缩放比
this.minScale = options.minScale || 0.7; //最近图像最小缩放比
this.selectedDuration = options.selectedDuration || 1000; //选中图片时,视觉移向被选中图片所需要的时间
this.moveDuration = options.moveDuration || 1000; //点击视觉移动需要的时间
this.tweenType = options.tweenType || 'easeOut';
this.currentScale = 1; //最近图像当前缩放比
containerPos = getContainerPos(this.container); //获取容器位置
bindScrollHandler.call(this); //绑定鼠标滚动处理程序
bindClickHandler.call(this); //绑定鼠标移动处理程序

},
addTweenType: function(type, func) {//添加缓动方式
(typeof func == 'function' || typeof func == 'object') && (Tween[type] = func);

},
addElem: (function() {//为房子添加元素 参数:x坐标 y坐标 缩放比 图片地址 元素id

var setImgHover = function(img) {//鼠标在元素上显示白框
img.onmouseover = function(eve) {
eve = eve || window.event;
var target = eve.target || eve.srcElement;
target.style.border = '1px white solid';
}

}
var setImgOut = function(img) {//鼠标离开元素白框消失
img.onmouseout = function(eve) {
eve = eve || window.event;
var target = eve.target || eve.srcElement;
target.style.border = 'none';
}

}
return function(x, y, scale, src, id) {
var elem = new Image();
var arr = this.arr;
var container = this.container;
var self = this;

elem.onload = function() {    //元素加载处理程序
container.appendChild(elem);
elem.id = id;
elem.style.position = 'absolute';
elem.style.zIndex = Math.floor(scale * 1000);
elem.initWidth = elem.clientWidth;
elem.initHeight = elem.clientHeight;
elem.initScale = scale;
elem.initX = x;
elem.initY = y;

updatePos.call(self, elem, x, y, scale); //更新元素位置
arr.push(elem);
bindHandlerForImage.call(self, elem);
setImgHover(elem);
setImgOut(elem);

}
elem.src = src;
}
})()
}

})();
return _room;

})();

var r=new room();

/*    草    */
r.addElem(350,-60,1,'grass.gif','grass1');
r.addElem(-600,-60,1,'grass.gif','grass2');
r.addElem(350,-60,0.7,'grass.gif','grass3');
r.addElem(-600,-60,0.7,'grass.gif','grass4');

/*    门    */
r.addElem(-225,200,0.65,'door.gif','door');

/* 灯 */
r.addElem(-400,600,0.63,'x-light.jpg','xlight');
r.addElem(-99,600,0.63,'light.gif','light');

/* 方桌 */
r.addElem(-480,-73,0.63,'table1.gif','table1');

/* 圆桌 */
r.addElem(600,0,0.6,'chair3.gif','chair2');
r.addElem(100,42,0.59,'chair1.gif','chair1');
r.addElem(180,-74,0.59,'table2.gif','table2');
r.addElem(360,24,0.57,'chair2.gif','chair2');

/* 钢琴 */
r.addElem(-850,246,0.56,'piano.gif','piano');

/* 书桌 */
r.addElem(600,240,0.5,'booktable.gif','booktable');

/* 电视 */
r.addElem(-206,79,0.4,'tv.gif','tv');

</script>
</html>


欢迎转载,请标明出处:/article/5223731.html

 

    

  

  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: