最近接手了一个商城项目,所以自己写了一个商品详情页面浏览商品大图的组件。虽然可能背负上重复造轮子的骂名。但我还是觉得有必要写的。 这起码也是自己的一个实践过程。兼容方面考虑到兼容IE8+,所以很多的代码都是在做兼容。
ie8是不支持style来设置属性的。但ie8支持存在runtimeStyle属性对象。
/**
* 设置元素样式属性
* @param {Object} element 元素
* @param {Object} props 属性对象
*/
function setCss(element , props){
if( element.style ){
for (var prop in props ) {
element.style[prop] = props[prop];
};
}else if(element.runtimeStyle){//ie8
for (var prop in props ) {
element.runtimeStyle[prop] = props[prop];
};
}
};
事件监听ie8也是与正常的添加事件监听不同,所以需要使用attachEvent来处理事件监听。
/**
* 事件监听
* @param {Object} element 元素
* @param {Object} type 类型
* @param {Object} fn 回调函数
*/
function addEvent(element , type , fn){
if( element.addEventListener ){//w3c
element.addEventListener(type , fn);
}else if( element.attachEvent ){//ie8
element.attachEvent('on'+type , fn);
}else{//其他
element['on'+type] = fn;
}
};
因为无法立即获得这个距离,所以只能通过遍历元素到body之间所有的元素的上边距或左边距进行选取最大值。 才可以获取得到最后元素距离页面左边距和上边距的距离。
//获取距离距离top和left的距离
function getOffset(element){
var top = 0 , left = 0;
if ( element ) {
while ( element != body && element != document ){
top = Math.max(+element.offsetTop , top);
left = Math.max(+element.offsetLeft , left);
element = element.parentNode;
}
}
return {left:left , top:top};
};
获取滚动条滚动的距离,这里主要的也是兼容问题。
IE Firefox Opera 标准模式下使用 document.documentElement.scrollLeft;
获取页面的水平滚动条位置,而混杂模式下则是使用 document.body.scrollLeft。
Chrome Safari 在两种文档模式下均使用 document.body.scrollLeft 获取页面的水平滚动条位置。
In IE 6 standards compatibility mode (where document.compatMode == “CSS1Compat”), use document.body.parentNode.scrollLeft and document.body.parentNode.scrollTop to get the scroll values of the html element.
//获取屏幕滚动距离
function getScrollXY(){
return {
x : window.scrollX ||window.scrollLeft ||
document.documentElement.scrollLeft || document.body.scrollLeft,
y : window.scrollY || window.scrollTop||
document.documentElement.scrollTop || document.body.scrollTop
}
};
var B = (function(){
var body = document.getElementsByTagName('body')[0];
//对象
function Blow(obj){
this.blowbox = obj.blowbox;
this.cursor = obj.cursor;
this.blowmax = obj.blowmax;
this.maxbox = obj.maxbox;
this.blowsmall = obj.blowsmall;
this.max = obj.max;
this.pst = {};
};
//初始化
Blow.prototype.init = function(){
var blowmax = this.blowmax ,
blowbox = this.blowbox,
cursor = this.cursor,
max = this.max ,
blowsmall = this.blowsmall,
maxbox = this.maxbox,
pst = this.pst;
setCss(blowmax , {width : max*2+'px' , height:max*2+'px'});
addEvent(blowbox , 'mousemove' , function(e){
setCss(maxbox , {display: 'block'});
pst = getPosition(e,max , blowbox);
setCss(cursor , {top : pst.top+'px' , left:pst.left+'px'});
showMax(pst , blowmax);
});
addEvent(blowbox, 'mouseout' , function(e){
setCss(maxbox , {display: 'none'});
});
};
/**
* 事件监听
* @param {Object} element 元素
* @param {Object} type 类型
* @param {Object} fn 回调函数
*/
function addEvent(element , type , fn){
if( element.addEventListener ){
element.addEventListener(type , fn);
}else if( element.attachEvent ){
element.attachEvent('on'+type , fn);
}else{
element['on'+type] = fn;
}
};
/**
* 设置元素样式属性
* @param {Object} element 元素
* @param {Object} props 属性对象
*/
function setCss(element , props){
if( element.style ){
for (var prop in props ) {
element.style[prop] = props[prop];
};
}else if(element.runtimeStyle){
for (var prop in props ) {
element.runtimeStyle[prop] = props[prop];
};
}
};
//获取位置
function getPosition(e , max , blowbox){
var offset = getOffset(blowbox) ,
xy = getScrollXY();
var x = +(e.clientX-offset.left+xy.x) ,
y = +(e.clientY-offset.top+xy.y);
var left = x-max*0.25 > 0 ? x-max*0.25 : 0 ,
top = y-max*0.25 > 0 ? y-max*0.25 : 0;
left = left > max*0.5 ? max*0.5 : left ;
top = top > max*0.5 ? max*0.5 : top ;
return {left:left ,top:top};
};
//展示大图
function showMax(pst , blowmax){
var x = pst.left*2 , y = pst.top*2;
if ( blowmax.style ){
blowmax.style.marginLeft = -x +'px';
blowmax.style.marginTop = -y+'px';
}else if( blowmax.runtimeStyle ){
blowmax.runtimeStyle.marginLeft = -x +'px';
blowmax.runtimeStyle.marginTop = -y+'px';
}
};
//获取距离距离top和left的距离
function getOffset(element){
var top = 0 , left = 0;
if ( element ) {
while ( element != body && element != document ){
top = +element.offsetTop > top ? +element.offsetTop : top;
left = +element.offsetLeft > left ? +element.offsetLeft : left;
element = element.parentNode;
}
}
return {left:left , top:top};
};
//获取屏幕滚动距离
function getScrollXY(){
return {
x : window.scrollX || window.scrollLeft || document.documentElement.scrollLeft || document.body.scrollLeft,
y : window.scrollY || window.scrollTop|| document.documentElement.scrollTop || document.body.scrollTop
}
};
return {
run : function(obj){
return new Blow(obj).init();
}
}
})();
//index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>查看大图</title>
<link rel="stylesheet" type="text/css" href="blow.css"/>
</head>
<body>
<div class="blow-box">
<div class="blow-small-box">
<div class="blow-content-box" id="j_blow_box">
<div class="blow-img-box">
<img class="blow-small-img" id="j_blow_small" src="images/small.jpg"/>
</div>
<span class="blow-img-cursor" id="j_blow_cursor"></span>
</div>
<div class="blow-small-bar">
<ul class="blow-small-list">
<li class="blow-small-list-i"><img src="images/small.jpg"/></li>
<li class="blow-small-list-i"><img src="images/small.jpg"/></li>
<li class="blow-small-list-i"><img src="images/small.jpg"/></li>
<li class="blow-small-list-i"><img src="images/small.jpg"/></li>
</ul>
</div>
</div>
<div class="blow-max-box" id="j_blow_max_box">
<img src="images/max.jpg" id="j_blow_max"/>
</div>
</div>
</body>
<script src="blow.js"></script>
<script>
//手势
var cursor = document.getElementById('j_blow_cursor'),
//小图
blowsmall = document.getElementById('j_blow_small'),
//大图
blowmax = document.getElementById('j_blow_max'),
//大图box
maxbox = document.getElementById('j_blow_max_box'),
//小图box
blowbox = document.getElementById('j_blow_box');
//运行
;B.run({
blowbox :blowbox,
cursor : cursor,
blowmax : blowmax,
maxbox : maxbox,
blowsmall : blowsmall,
max : 464//大图大小
})
</script>
</html>
.blow-box{
width: 574px;
height: 464px;
position: relative;
margin-left: 100px;
margin-top: 400px;
}
.blow-small-box{
width: 100%;
height: 100%;
}
.blow-max-box{
position: absolute;
z-index: 99;
right: -464px;
top: 0;
width: 464px;
height: 464px;
overflow: hidden;
}
.blow-content-box{
width: 464px;
height: 464px;
float: left;
}
.blow-small-bar{
width: 110px;
height: 464px;
overflow: hidden;
}
.blow-small-list{
width: 82px;
height: 464px;
margin: 0;
padding: 0;
}
.blow-small-list .blow-small-list-i{
width: 78px;
height: 78px;
margin: 14px;
border: 2px solid #47baac;
list-style: none;
overflow: hidden;
cursor: pointer;
}
.blow-small-list .blow-small-list-i img{
width: 78px;
height: 78px;
}
.blow-content-box{
width: 464px;
height: 464px;
overflow: hidden;
position: relative;
}
.blow-img-box , .blow-small-img{
width: 464px;
height: 464px;
}
.blow-img-cursor{
position: absolute;
display: none;
z-index: 2;
top: 0;
left: 0;
width: 232px;
height: 232px;
cursor: move;
background: url(images/blow.png) repeat transparent;
}
.blow-content-box:hover .blow-img-cursor{
display: block;
}