【CSON原创】 图片滑动展开效果发布
功能说明:
鼠标移动到不同图片上,该图片滑动展开,其它图片折叠。
支持IE 6 7 8 firefox chrome
效果预览:
实现原理:
当鼠标移动到某张图片,该图片以及该图片前的图片以相同速度向左运动,该图片之后的图片也以相同速度向右运动,形成展开选中图片的效果。
代码分析:
var flow_slide_imgs = function(options) {
this._init();
}
flow_slide_imgs.prototype = {
_init: function(options) {
var defaults = {
containerId: 'container',
ImgsWidth: 0.6
};
var opts = util.extend(defaults, options);
this.container = util.$(opts.containerId);
this.imgs = this.container.getElementsByTagName('img');
this.imgWidth = parseInt(util.getComputedStyle(this.container).width) * opts.ImgsWidth;
this.containerWidth = parseInt(util.getComputedStyle(this.container).width);
this.containerHeight = parseInt(util.getComputedStyle(this.container).height);
this.aveWidth = this.containerWidth / this.imgs.length;
this.newAveWidth = (this.containerWidth - parseInt(this.imgWidth)) / (this.imgs.length - 1);
this.selectedIndex;
this.movePath = 80;
this.canLeft = true;
this.canRight = true;
this._setContainerStyle();
this._setImgsStyle();
this._bindClickEvent();
},
_init方法中,复制传入的参数对象,并使用extend方法把传入参数与默认参数结合,再以对象属性形式保存。最后调用其他私有函数进行初始化。
_setContainerStyle: function() {
this.container.style.cssText = 'overflow:hidden; position:relative;';
},
设置容器的样式,由于容器内图片使用绝对定位并改变位置来实现图片的展开和折叠,所以容器设置为相对定位,并且隐藏超出容器的图片。
_setImgsStyle: function() {
for (var i = 0; i < this.imgs.length; i++) {
this.imgs[i].style.cssText = 'position:absolute;'
+ 'left:' + i * this.aveWidth + 'px;'
+ 'top:0px;'
+ 'width:' + this.imgWidth + ';'
+ 'height:' + this.containerHeight + 'px;'
+ 'z-index:' + i + ';'
+ 'display:block';
}
},
获取容器内图片,并批量设置图片样式,aveWidth为图片初始的平均宽度,该数值在_init方法中通过容器宽度除以图片数量得出。以每张图片的索引为值设置图片的层叠级别,这样可以保证由最左边开始,一张图片叠在其右边的图片的上面。由于图片为行内元素,所以再设置其display为block。
_getSelectedIndex: function(target) {
for (var i = 0, len = this.imgs.length; i < len; i++) {
if (target == this.imgs[i]) {
if (this.selectedIndex && this.selectedIndex < i) {
this.canLeft = true;
this.canRight = false;
}
if (this.selectedIndex && this.selectedIndex > i) {
this.canLeft = false;
this.canRight = true;
}
break;
}
}
return i;
},
获取所选择图片,并且把该图片的索引和之前已打开的图片的索引进行比较,如果所选图片在已打开的图片左边,则图片组只何以向左移动,否则图片只可以向右移动,这样是为了解决鼠标移动过快造成的左边图片和右边图片作相反方向移动的问题。总之,这里保证的所有图片向同一个方向移动。
_resetImgsSizeAndPos: function(obj, selectedIndex) {
if (typeof obj.selectedIndex == 'undefined') {
if (parseInt(util.getComputedStyle(obj.imgs[1]).left) > obj.newAveWidth) {
for (var i = 1; i < obj.imgs.length; i++) {
if (i <= selectedIndex)
obj.imgs[i].style.left = Math.max(parseInt(obj.imgs[i].style.left) - obj.movePath * i, i * obj.newAveWidth) + 'px';
else
obj.imgs[i].style.left = Math.min(parseInt(obj.imgs[i].style.left) + obj.movePath * (obj.imgs.length - i), obj.containerWidth - (obj.imgs.length - i) * obj.newAveWidth) + 'px';
}
obj.timeId = window.setTimeout(arguments.callee, 100, obj, selectedIndex);
}
if (parseInt(util.getComputedStyle(obj.imgs[1]).left) == obj.newAveWidth || parseInt(util.getComputedStyle(obj.imgs[1]).left) == obj.imgWidth) {
obj.selectedIndex = selectedIndex;
}
}
else if (obj.selectedIndex > selectedIndex) {
if (parseInt(util.getComputedStyle(obj.imgs[selectedIndex + 1]).left) < (selectedIndex + 1) * obj.newAveWidth + (obj.imgWidth - obj.newAveWidth) && obj.canRight) {
for (var j = selectedIndex + 1; j <= obj.selectedIndex; j++) {
obj.imgs[j].style.left = Math.min(parseInt(obj.imgs[j].style.left) + obj.movePath, obj.newAveWidth * (j - 1) + obj.imgWidth) + 'px';
}
obj.timeId = window.setTimeout(arguments.callee, 100, obj, selectedIndex);
}
else {
obj.canLeft = true;
obj.selectedIndex = selectedIndex;
}
}
else if (obj.selectedIndex < selectedIndex) {
if (parseInt(util.getComputedStyle(obj.imgs[selectedIndex]).left) > (selectedIndex) * obj.newAveWidth && obj.canLeft) {
for (var j = selectedIndex; j > obj.selectedIndex; j--) {
obj.imgs[j].style.left = Math.max(parseInt(obj.imgs[j].style.left) - obj.movePath, j * obj.newAveWidth) + 'px';
}
obj.timeId = window.setTimeout(arguments.callee, 100, obj, selectedIndex);
}
else {
obj.canRight = true;
obj.selectedIndex = selectedIndex;
}
}
},
根据 所有图片均未打开(第一次选择图片),已打开图片在所选择图片的前面,已打开图片在所选择图片的后面 这三种情况,图片组作不同方向的运动,通过setTimeout每隔100ms移动一个单位位移。
_bindClickEvent: function() {
util.addEventHandler(this.container, 'mouseover', (function(obj) {
return function(eve) {
eve = eve || window.event;
var target = eve.srcElement || eve.target,
selectedIndex = obj._getSelectedIndex(target);
obj._resetImgsSizeAndPos(obj, selectedIndex);
}
})(this));
}
为容器的mouseover事件绑定事件处理程序,利用事件冒泡在容器的处理程序里产生选中图片时的效果。
这里由于需要为事件处理传递参数,所以利用闭包,使传入的obj对象可访问。鼠标移动到图片上方时,调用上面分析过的resetImgsSizeAndPos方法,根据实际情况让图片作出不同的运动。
new flow_slide_imgs();
最后是调用方法,这里没有传入参数,则控件里面使用默认值。
完整demo代码:
html:
<div id="container">
<img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_cat1.jpg" />
<img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_cat2.jpg" />
<img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_cat3.jpg" />
<img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_cat4.jpg" />
<img src="http://images.cnblogs.com/cnblogs_com/Cson/290336/r_cat5.jpg" />
</div>
css:
#container{width:600px; height:300px; background-color:Black;}
#container img{display:none;}
base.js:
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;
},
extend: function(destination, source) {
for (var name in source) {
destination[name] = source[name];
}
return destination;
}
};
(function() {
var st = window.setTimeout;
window.setTimeout = function(fn, mDelay) {
var t = new Date().getTime();
if (typeof fn == 'function') {
var args = Array.prototype.slice.call(arguments, 2);
var f = function() {
args.push(new Date().getTime() - t - mDelay);
fn.apply(null, args)
};
return st(f, mDelay);
}
return st(fn, mDelay);
}
})();
flow_slide_imgs.js:
/*
created by cson
supports ie 6 7 8 firefox and chrome
*/
/*constructor of 'flow images controller' */
var flow_slide_imgs = function(options) {
this._init();
}
flow_slide_imgs.prototype = {
/* init container and images and set object's properties */
_init: function(options) {
var defaults = {
containerId: 'container',
ImgsWidth: 0.6
};
var opts = util.extend(defaults, options);
this.container = util.$(opts.containerId);
this.imgs = this.container.getElementsByTagName('img');
this.imgWidth = parseInt(util.getComputedStyle(this.container).width) * opts.ImgsWidth;
this.containerWidth = parseInt(util.getComputedStyle(this.container).width);
this.containerHeight = parseInt(util.getComputedStyle(this.container).height);
this.aveWidth = this.containerWidth / this.imgs.length;
this.newAveWidth = (this.containerWidth - parseInt(this.imgWidth)) / (this.imgs.length - 1);
this.selectedIndex;
this.movePath = 80;
this.canLeft = true;
this.canRight = true;
this._setContainerStyle();
this._setImgsStyle();
this._bindClickEvent();
},
/* set container's style */
_setContainerStyle: function() {
this.container.style.cssText = 'overflow:hidden; position:relative;';
},
/* set styles of images in container */
_setImgsStyle: function() {
for (var i = 0; i < this.imgs.length; i++) {
this.imgs[i].style.cssText = 'position:absolute;'
+ 'left:' + i * this.aveWidth + 'px;'
+ 'top:0px;'
+ 'width:' + this.imgWidth + ';'
+ 'height:' + this.containerHeight + 'px;'
+ 'z-index:' + i + ';'
+ 'display:block';
}
},
/* get current selected image's index */
_getSelectedIndex: function(target) {
for (var i = 0, len = this.imgs.length; i < len; i++) {
if (target == this.imgs[i]) {
if (this.selectedIndex && this.selectedIndex < i) {
this.canLeft = true;
this.canRight = false;
}
if (this.selectedIndex && this.selectedIndex > i) {
this.canLeft = false;
this.canRight = true;
}
break;
}
}
return i;
},
/* reset images' size and position for three situation */
_resetImgsSizeAndPos: function(obj, selectedIndex) {
if (typeof obj.selectedIndex == 'undefined') {
if (parseInt(util.getComputedStyle(obj.imgs[1]).left) > obj.newAveWidth) {
for (var i = 1; i < obj.imgs.length; i++) {
if (i <= selectedIndex)
obj.imgs[i].style.left = Math.max(parseInt(obj.imgs[i].style.left) - obj.movePath * i, i * obj.newAveWidth) + 'px';
else
obj.imgs[i].style.left = Math.min(parseInt(obj.imgs[i].style.left) + obj.movePath * (obj.imgs.length - i), obj.containerWidth - (obj.imgs.length - i) * obj.newAveWidth) + 'px';
}
obj.timeId = window.setTimeout(arguments.callee, 100, obj, selectedIndex);
}
if (parseInt(util.getComputedStyle(obj.imgs[1]).left) == obj.newAveWidth || parseInt(util.getComputedStyle(obj.imgs[1]).left) == obj.imgWidth) {
obj.selectedIndex = selectedIndex;
}
}
else if (obj.selectedIndex > selectedIndex) {
if (parseInt(util.getComputedStyle(obj.imgs[selectedIndex + 1]).left) < (selectedIndex + 1) * obj.newAveWidth + (obj.imgWidth - obj.newAveWidth) && obj.canRight) {
for (var j = selectedIndex + 1; j <= obj.selectedIndex; j++) {
obj.imgs[j].style.left = Math.min(parseInt(obj.imgs[j].style.left) + obj.movePath, obj.newAveWidth * (j - 1) + obj.imgWidth) + 'px';
}
obj.timeId = window.setTimeout(arguments.callee, 100, obj, selectedIndex);
}
else {
obj.canLeft = true;
obj.selectedIndex = selectedIndex;
}
}
else if (obj.selectedIndex < selectedIndex) {
if (parseInt(util.getComputedStyle(obj.imgs[selectedIndex]).left) > (selectedIndex) * obj.newAveWidth && obj.canLeft) {
for (var j = selectedIndex; j > obj.selectedIndex; j--) {
obj.imgs[j].style.left = Math.max(parseInt(obj.imgs[j].style.left) - obj.movePath, j * obj.newAveWidth) + 'px';
}
obj.timeId = window.setTimeout(arguments.callee, 100, obj, selectedIndex);
}
else {
obj.canRight = true;
obj.selectedIndex = selectedIndex;
}
}
},
/*bind handler for mouseover event of images */
_bindClickEvent: function() {
util.addEventHandler(this.container, 'mouseover', (function(obj) {
return function(eve) {
eve = eve || window.event;
var target = eve.srcElement || eve.target,
selectedIndex = obj._getSelectedIndex(target);
obj._resetImgsSizeAndPos(obj, selectedIndex);
}
})(this));
}
}
欢迎转载,请标明出处:http://www.cnblogs.com/Cson/archive/2011/04/03/2004717.html