if ( !viewer.offsetWidth ) {
styles = { display: style.display, visibility: style.visibility };
$$D.setStyle( viewer, { display: "block", visibility: "hidden" });
}
...
if ( styles ) { $$D.setStyle( viewer, styles ); }
为了跟随时,让鼠标固定在显示框中心位置,先根据显示框的offsetWidth/offsetHeight修正参数:
复制代码 代码如下:
this._repairFollowLeft = viewer.offsetWidth / 2;
this._repairFollowTop = viewer.offsetHeight / 2;
如果显示框的offsetParent不是body,还需要根据offsetParent修正坐标:
复制代码 代码如下:
if ( !/BODY|HTML/.test( viewer.offsetParent.nodeName ) ) {
var parent = viewer.offsetParent, rect = $$D.rect( parent );
this._repairFollowLeft += rect.left + parent.clientLeft;
this._repairFollowTop += rect.top + parent.clientTop;
}
ps:在Maxthon测试时发现body子元素的offsetParent不是body而是html。
为了在移除程序后,能恢复显示框的样式,在load程序中做了样式的备份:
复制代码 代码如下:
var viewer = this._viewer, style = viewer.style, styles;
this._stylesFollow = {
left: style.left, top: style.top, position: style.position
};
并在dispose中恢复:
$$D.setStyle( this._viewer, this._stylesFollow );
现在已经达到了基本的效果,但由于大图移动范围的限制,当鼠标移动到接近边界时,大图就卡住不会动了。
为了实现在鼠标移动时,大图会持续变化的效果,在repair中修正了移动坐标:
复制代码 代码如下:
pos.left = ( viewerWidth / 2 - pos.left ) * ( viewerWidth / zoom.width - 1 );
pos.top = ( viewerHeight / 2 - pos.top ) * ( viewerHeight / zoom.height - 1 );
原理稍有些复杂,以水平坐标为例,先看下图:
大方框代表大图对象,小方框代表显示框。
当前位置是根据鼠标坐标得到的实际显示的位置,目标位置想要实现效果的位置。
有一些物理或几何知识应该明白这个等式:x / y = m / n
可以推出:y = x * n / m = x * ( zoom.width - viewerWidth ) / zoom.height
x当前坐标可以通过pos.left来得到:x = viewerWidth / 2 - pos.left
最后得到:left = -y = ( viewerWidth / 2 - pos.left ) * ( viewerWidth / zoom.width - 1 )
垂直坐标也差不多。
【拖柄模式】
拖柄是一个层,在原图上面,用来表示显示范围在原图的位置和范围。
显示范围可以根据_rangeWidth/_rangeHeight获取。
至于位置的指定可以根据鼠标坐标或大图定位坐标来设置。
如果鼠标坐标的话还必须做其他处理,例如范围控制,而根据大图定位坐标相对就方便准确得多,程序也是用后面一个方法。
首先在init定义一个_handle拖柄对象:
复制代码 代码如下:
var handle = $$( this.options.handle );
if ( !handle ) {
var body = document.body;
handle = body.insertBefore(this._viewer.cloneNode(false), body.childNodes[0]);
handle.id = "";
handle["_createbyhandle"] = true;
}
$$D.setStyle( handle, { padding: 0, margin: 0, display: "none" } );
如果没有自定义拖柄对象,会复制显示框作为拖柄对象。
对于自动生成的拖柄对象,会添加"_createbyhandle"属性作标记,方便在dispose中移除。
在load时,设置拖柄样式:
复制代码 代码如下:
$$D.setStyle( handle, {
position: "absolute",
width: this._rangeWidth + "px",
height: this._rangeHeight + "px",
display: "block",
visibility: "hidden"
});
绝对定位是必须的,并根据_rangeWidth/_rangeHeight设置尺寸。
设置display和visibility是为了下面获取参数。
先根据原图坐标获取修正参数:
this._repairHandleLeft = rect.left + this._repairLeft - handle.clientLeft;
this._repairHandleTop = rect.top + this._repairTop - handle.clientTop;
和跟随模式类似,也要做offsetParent定位的修正:
复制代码 代码如下:
if ( handle.offsetParent.nodeName.toUpperCase() != "BODY" ) {
var parent = handle.offsetParent, rect = $$D.rect( parent );
this._repairHandleLeft -= rect.left + parent.clientLeft;
this._repairHandleTop -= rect.top + parent.clientTop;
}
然后重新隐藏:
$$D.setStyle( handle, { display: "none", visibility: "visible" });
在start时,显示拖柄对象。
在move时,根据大图定位坐标设置拖柄定位:
复制代码 代码如下: