依然是项目需求,图片展示在固定窗口(div)内,窗口内要求可以放大缩小、可以拖拽。

以下代码在Chrome浏览器下测试通过,谢谢伟大的甲方。

demo在线展示:https://knimet.github.io/js-zoom-drag-in-a-window/pic.html

demo地址:https://github.com/knimet/js-zoom-drag-in-a-window


页面代码很简单,div内放置一个img。我这里设置的img初始大小已经大于div了,如果有需要可以设置和div大小相同,即没有放缩:

<div class="pic" style="height:600px;width:600px;overflow:hidden;margin:0 auto">
    <img style="display:block;" id="pic" width=1000px height=1000px;>
</div>

接下来是js的部分

【拖拽】

拖拽的需求很明确,图片比外部的div大,而且div设置了overflow:hidden,自然无法完全显示,需要通过拖拽浏览图片的其他部分。基本流程为:鼠标点下,拖拽开始-鼠标移动,图片随之拖拽-鼠标抬起,拖拽结束。

拖拽的原理用一句话概括为:根据鼠标的位置设置图片的位置。在本次需求中,通过设置外边距/负外边距调整图片位置。

(1) 获取元素

var div1 = document.getElementById("pic");

(2) 对元素设置鼠标按下事件

div1.onmousedown = function(ev){
}

(3)初始化偏移量。图片偏移初始为0,因此两个方向的偏移均设置为0.

var offX = 0,offY = 0;

(4) 事件内的处理逻辑如下:记录鼠标点击位置distanceX,distanceY。根据鼠标移动后的位置newX,newY,计算移动的距离,即移动后的位置和移动前位置的差:x1=newX-distanceX,y1=newY-distanceY。计算后得到的x1,y1即为本次鼠标移动的距离。图片被鼠标拖拽,意味着图片随着鼠标的移动而移动,因此图片移动的距离也为x1,y1。

div1.onmousedown = function(ev){
    ev.preventDefault(); //阻止浏览器动作,有些浏览器试图拖拽图片的时候,是会把图片单独到一个页面来查看的。
  var oevent = ev || event; //兼容性处理
  var distanceX = oevent.clientX; //记录鼠标点击x位置
  var distanceY = oevent.clientY; //记录鼠标点击y位置
    document.onmousemove = function(ev){ //当鼠标点击后,才对document设置mousemove事件
        var oevent = ev || event;
        x1 = oevent.clientX - distanceX;//oevent.clientX是鼠标移动到的x位置,oevent.clientX-distanceX是移动的距离
        y1 = oevent.clientY - distanceY;
        distanceX = oevent.clientX; //更新distanceX的位置信息。这一步非常重要非常重要非常重要,因为mousemove事件在鼠标移动时触发,而不是鼠标停止移动后触发
        distanceY = oevent.clientY;
        div1.style.marginLeft = (x1 + offX) + "px"; //若x1为正,则鼠标向右移动,设置图片的margin-left为正,向右偏移;为负同理向左偏移。
        div1.style.marginTop = (y1+ offY) +"px"; //offX和offY为前一次的偏移,本次移动是在前一次的基础上发生的,要加上偏移值才是鼠标本次移动后图片的位置。
        offX = x1+offX; //记录此时图片的偏移位置
        offY = y1+offY;
    };
  document.onmouseup = function(){ //鼠标抬起后,就取消document的mousemove事件
            document.onmousemove = null;
  };
      
}

【放缩】

放缩的详细需求是,鼠标在div框内滚动滚轴,向前滚动为放大,向后滚动为缩小,div框内滚轴的滚动不带动页面上下滚动。

处理逻辑:对页面设置鼠标滚轴事件,若事件发生在图片上,则改变图片的宽和高,形成放缩效果。

兼容性处理:

if(document.addEventListener){
    document.addEventListener('DOMMouseScroll',scrollFunc,false);
}//W3C
    window.onmousewheel=document.onmousewheel=scrollFunc;//IE/Opera/Chrome

监听事件:

function scrollFunc(e) {
    if(e.target!=document.getElementById("pic")){ //如果事件没发生在pic上,不执行该函数。
        return;
    }
    var oImg = document.getElementById("pic");
    var direct = 0;
    e = e || window.event;
    if (e.wheelDelta) { //IE/Opera/Chrome
        if (e.wheelDelta > 0) { //大于0,向前滚,放大
            oImg.width = oImg.width * 1.1;
            oImg.height = oImg.height * 1.1;
        } else { //否则是缩小
            oImg.width = oImg.width / 1.1;
            oImg.height = oImg.height / 1.1;
        }
    } else if (e.detail) { //Firefox
        if (e.detail > 0) {
            oImg.width = oImg.width * 1.1;
            oImg.height = oImg.height * 1.1;
        } else {
            oImg.width = oImg.width / 1.1;
            oImg.height = oImg.height / 1.1;
        }
    }
    if(e.preventDefault) { //阻止浏览器自身事件
        e.preventDefault();
        e.stopPropagation();
    }else{
        e.returnValue = false;
        e.cancelBubble = true;
    }
}

【放缩鼠标所在位置】

这个先空着。

其实结合前面两个就可以实现了,根据鼠标位置,再根据鼠标滚轴的方向,放大或缩小图片的width和height,再设置图片的margin保证图片放大/缩小后鼠标所在的位置依旧处于可视范围内原位置。



参考资料:


http://www.jb51.net/article/43049.htm