您的位置:首页 > 其它

【CSON原创】 3D翻转相册发布

2011-03-27 22:57 351 查看

功能说明:


通过鼠标上下左右的移动,翻转呈现相册。支持浏览器IE6 7 8(IE8下会比较卡,IE6 7则不会) firefox chrome


效果图:



























// var util = {
$: function(sId) { return document.getElementById(sId); },
addEventHandler: function(elem, type, handler) {
if (elem.addEventListener) {
elem.addEventListener(type, handler, false);
}
else {
elem.attachEvent("on" + type, handler);
}
},
removeEventHandler: function(elem, type, handler) {
if (elem.removeEventListener) {
elem.removeEventListener(type, handler, false);
}
else {
elem.detachEvent("on" + type, handler);
}
},
getComputedStyle: function(elem) {
if (elem.currentStyle)
return elem.currentStyle;
else {
return document.defaultView.getComputedStyle(elem, null);
}
},

getElementsByClassName: function(className, parentElement) {
var elems = (parentElement || document.body).getElementsByTagName("*");
var result = [];
for (i = 0; j = elems[i]; i++) {
if ((" " + j.className + " ").indexOf(" " + className + " ") != -1) {
result.push(j);
}
}
return result;
}

}
// ]]>
// /*
author:xiaoc support ie 6 7 8 firefox chrome
*/

var shower = (function() {

var defaults = {
containerId: 'phos_container', /* id of photos' container */
imgSize: 50, /* size of imgs */
imgMargin: 60, /* margin between every img */
countEveryRow: 4, /* imgs' count every in row */
times: 1.5 /* the max size of biggest scale*/

},
container = util.$(defaults.containerId),
count = document.getElementsByTagName('img').length,
rowCount = Math.ceil(count / defaults.countEveryRow),
newContainer,
newContainer_width = defaults.countEveryRow * defaults.imgSize + (defaults.countEveryRow - 1) * defaults.imgMargin,
newContainer_height = rowCount * defaults.imgSize + (rowCount - 1) * defaults.imgMargin,
subContainers = [],
imgs = container.getElementsByTagName('img'),
centerPoint;

function _setImgsStyle() {

var imgs = container.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var left,
top,
distant = defaults.imgMargin + defaults.imgSize,
n = (i + 1) % defaults.countEveryRow;
if (n == 0)
left = (defaults.countEveryRow - 1) * distant;
else
left = (n - 1) * distant;

top = Math.floor(i / defaults.countEveryRow) * distant;

imgs[i].style.cssText = 'width:' + defaults.imgSize + 'px;'
+ 'height:' + defaults.imgSize + 'px;'
+ 'position:absolute;'
+ 'left:' + left + 'px;'
+ 'top:' + top + 'px;'
+ 'display:block;';

}
}

function _setImgsPosition(oSubContainer) {
var imgs = document.getElementsByTagName('img');
if (imgs.length > 0) {
for (var i = 0; i < defaults.countEveryRow; i++) {
if (imgs[0]) {
oSubContainer.appendChild(_setImgsStyle(imgs[0], i));
}
else
break;
}

}

return oSubContainer;
}

/* set the style of images' container */

function _setContainerStyle() {
container.style.cssText = 'width:' + newContainer_width + 'px;'
+ 'height:' + newContainer_height + 'px;'
+'position:relative;'
+ 'background-color:black;';

}

/* init the value of center point of screen */
function _initCenterPoint() {
var len = defaults.imgSize + defaults.imgMargin;

centerPoint = {

left: document.documentElement.clientWidth / 2,
top: document.documentElement.clientHeight / 2
}

}

/* attach events for mouse move */
function _attachMouseMoveHandler() {
document.documentElement.onmousemove = function(eve) {
eve = eve || window.event;
var xpercent = ((centerPoint.left - eve.clientX) / centerPoint.left),
ypercent = ((centerPoint.top - eve.clientY) / centerPoint.top),
max_img_size = defaults.times * defaults.imgSize,
_size, _top, _left;

for (var i = 0; i < imgs.length; i++) {
var n = i % defaults.countEveryRow;
var m = Math.floor(i / defaults.countEveryRow);
if (xpercent > 0) {

var xtimes = (1 - n * (1 / defaults.countEveryRow)),
size = xpercent * max_img_size * xtimes + (1 - xpercent) * defaults.imgSize,
xaddleft = ((newContainer_width - max_img_size * xtimes) / 2 - (defaults.imgSize + defaults.imgMargin) * n) * xpercent,
xtop = -((max_img_size * xtimes - defaults.imgSize) / 2) * xpercent;

}
else if (xpercent < 0) {
var xtimes = 1 + (n - (defaults.countEveryRow - 1)) * (1 / defaults.countEveryRow),
size = -xpercent * max_img_size * xtimes + (1 + xpercent) * defaults.imgSize;
xaddleft = ((newContainer_width - max_img_size * xtimes) / 2 - (defaults.imgSize + defaults.imgMargin) * n) * -xpercent,
xtop = -((max_img_size * xtimes - defaults.imgSize) / 2) * -xpercent;

}

_size = size;
_left = (defaults.imgSize + defaults.imgMargin) * n + xaddleft;
_top = m * (defaults.imgSize + defaults.imgMargin) + xtop;

if (ypercent > 0) {

var ytimes = (1 - m * (1 / rowCount)),
size = ypercent * _size * defaults.times * ytimes + (1 - ypercent) * _size,
yaddtop = ((newContainer_width - _size * defaults.times * ytimes) / 2 - _top) * ypercent,
yleft = -((_size * defaults.times * ytimes - _size) / 2) * ypercent;

}
else if (ypercent < 0) {

var ytimes = 1 + (m - (rowCount - 1)) * (1 / rowCount),
size = -ypercent * _size * defaults.times * ytimes + (1 + ypercent) * _size,
yaddtop = ((newContainer_width - _size * defaults.times * ytimes) / 2 - _top) * -ypercent,
yleft = -((_size * defaults.times * ytimes - _size) / 2) * -ypercent;

}

_size = size;
_top = _top + yaddtop;
_left = _left + yleft;

imgs[i].style.width = imgs[i].style.height = _size + 'px';
imgs[i].style.top = _top + 'px';
imgs[i].style.left = _left + 'px';
imgs[i].style.zIndex = Math.ceil(_size);

}
}
}

return {
init: function() {

_setContainerStyle();
_setImgsStyle();
_initCenterPoint();
_attachMouseMoveHandler();

}

}

})();
// ]]>
// shower.init();
// ]]>


实现原理:


根据鼠标的坐标,以及层与层之间缩放的倍数,早鼠标移动时重新计算每层图片的宽度,高度以及位置,形成3D翻转效果。翻转角度和鼠标移动位移占页面一半宽度的比例成正比。


代码分析:


var defaults = {
containerId: 'phos_container', /* id of photos' container */
imgSize: 80,                   /* size of imgs */
imgMargin: 100,                 /* margin between every img */
countEveryRow: 4,              /* imgs' count every in row */
times: 1.5                  /* the max size of biggest scale*/

},


首先指定一个储存默认值的单体,里面包括各种默认参数值,如容器ID,图片尺寸等。最后的times是层与层之间的缩放倍数,times越大,则显得图片和图片在翻转时距离较大。

function _setImgsStyle() {

var imgs = container.getElementsByTagName("img");
for (var i = 0; i < imgs.length; i++) {
var left,
top,
distant = defaults.imgMargin + defaults.imgSize,
n = (i + 1) % defaults.countEveryRow;
if (n == 0)
left = (defaults.countEveryRow - 1) * distant;
else
left = (n - 1) * distant;

top = Math.floor(i / defaults.countEveryRow) * distant;

imgs[i].style.cssText = 'width:' + defaults.imgSize + 'px;'
+ 'height:' + defaults.imgSize + 'px;'
+ 'position:absolute;'
+ 'left:' + left + 'px;'
+ 'top:' + top + 'px;'
+ 'display:block;';

}
}


设置每个图片样式的私有方法,里面通过图片的索引,设置图片在容器的位置,其中使用到cssText来批量设置样式属性。

function _setContainerStyle() {
container.style.cssText = 'width:' + newContainer_width + 'px;'
+ 'height:' + newContainer_height + 'px;'
+ 'position:absolute;'
+ 'left:50%;'
+ 'top:50%;'
+ 'margin-left:' + newContainer_width / -2 + 'px;'
+ 'margin-top:' + newContainer_height / -2 + 'px;'
+ 'background-color:black;';

}


设置容器的样式,注意这里和demo的样式设置并不相同,这里是把容器相对于浏览器可视区域水平垂直局中,而demo中由于页面大小限制并没有这样做。

function _initCenterPoint() {
var len = defaults.imgSize + defaults.imgMargin;

centerPoint = {

left: document.documentElement.clientWidth / 2,
top: document.documentElement.clientHeight / 2
}

}


初始化屏幕中心点对象,该中心点是实现翻转效果的参考点。鼠标相对于该中心点的位移决定翻转的角度大小。

function _attachMouseMoveHandler() {
document.documentElement.onmousemove = function(eve) {
eve = eve || window.event;
var xpercent = ((centerPoint.left - eve.clientX) / centerPoint.left),
ypercent = ((centerPoint.top - eve.clientY) / centerPoint.top),
max_img_size = defaults.times * defaults.imgSize,
_size, _top, _left;

for (var i = 0; i < imgs.length; i++) {
var n = i % defaults.countEveryRow;
var m = Math.floor(i / defaults.countEveryRow);
if (xpercent > 0) {

var xtimes = (1 - n * (1 / defaults.countEveryRow)),
size = xpercent * max_img_size * xtimes + (1 - xpercent) * defaults.imgSize,
xaddleft = ((newContainer_width - max_img_size * xtimes) / 2 - (defaults.imgSize + defaults.imgMargin) * n) * xpercent,
xtop = -((max_img_size * xtimes - defaults.imgSize) / 2) * xpercent;

}
else if (xpercent < 0) {
var xtimes = 1 + (n - (defaults.countEveryRow - 1)) * (1 / defaults.countEveryRow),
size = -xpercent * max_img_size * xtimes + (1 + xpercent) * defaults.imgSize;
xaddleft = ((newContainer_width - max_img_size * xtimes) / 2 - (defaults.imgSize + defaults.imgMargin) * n) * -xpercent,
xtop = -((max_img_size * xtimes - defaults.imgSize) / 2) * -xpercent;

}

_size = size;
_left = (defaults.imgSize + defaults.imgMargin) * n + xaddleft;
_top = m * (defaults.imgSize + defaults.imgMargin) + xtop;

if (ypercent > 0) {

var ytimes = (1 - m * (1 / rowCount)),
size = ypercent * _size * defaults.times * ytimes + (1 - ypercent) * _size,
yaddtop = ((newContainer_width - _size * defaults.times * ytimes) / 2 - _top) * ypercent,
yleft = -((_size * defaults.times * ytimes - _size) / 2) * ypercent;

}
else if (ypercent < 0) {

var ytimes = 1 + (m - (rowCount - 1)) * (1 / rowCount),
size = -ypercent * _size * defaults.times * ytimes + (1 + ypercent) * _size,
yaddtop = ((newContainer_width - _size * defaults.times * ytimes) / 2 - _top) * -ypercent,
yleft = -((_size * defaults.times * ytimes - _size) / 2) * -ypercent;

}

_size = size;
_top = _top + yaddtop;
_left = _left + yleft;

imgs[i].style.width = imgs[i].style.height = _size + 'px';
imgs[i].style.top = _top + 'px';
imgs[i].style.left = _left + 'px';
imgs[i].style.zIndex = Math.ceil(_size);

}
}
}


这里是整个程序最复杂的部分,通过对水平翻转以及垂直翻转两个“分运动”的计算最后得出总体的翻转情况,该实现可以细分为以下几个步骤:

1。获取鼠标x坐标相对于中心点位移占1/2页面宽度的百分比,该百分比映射到翻转角度的变化。

2.首先实现的是水平方向上的翻转,此时需要计算鼠标在水平方向上的移动导致图片大小以及位置的变化情况。

3.然后再在水平翻转计算结果的基础上,计算垂直翻转导致的图片大小以及位置的变化情况。

4.把两个分运动计算结果作为最终结果设置图片的样式值,其中要注意的是由于图片的大小越大,证明离观察者距离越短,所以应该层叠级最高,因此可以直接把图片尺寸取整后作为zIndex的值。

return {
init: function() {

_setContainerStyle();
_setImgsStyle();
_initCenterPoint();
_attachMouseMoveHandler();

}

}


最后返回单体,为调用者提供简单的接口init函数,该函数内部调用上文分析的多个私有函数。

外部初始化方式:

<script>
shower.init();

</script>


欢迎转载,但请标明出处:/article/5223719.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: