js图片拖拽、缩放、添加图层功能(原创)

最近项目中完成的需求,仿百度地图中的功能:

要求:1.底层图可以拖拽、缩放。

      2.拖拽一个图标,在底层图上对应位置添加一个标注点,该标注点位置要随底层图移动。

   3.添加的标注点,可以拖动,删除。

主要知识点和难点就是各个浏览器的点击、拖拽、缩放事件兼容性,对js运动属性、运动偏移位置的了解,以及js面向对象的应用。

这里跟大家分享一下完成后的代码。

html代码主要知识点就是运动元素和底层元素的相对绝对定位,css代码不再贴出:

<div id="warp" style="position: relative;width: 100%;height: 100%;background: #d7d7d7;">
		<img title="拖动" class="dragImg" id="dragImg" src="images/video_16px_566474.png">
		<div class="dragAble bgDiv" id="block1" style="zoom:1;">
			<img id="wheelImg" src="images/photo2FDIB963M30AI20009NOS.jpg" style="zoom:1;" title="底层图片">
			<p>这段文字跟着div一起运动</p>
		</div>
</div>

 js代码,初始化:

 1 var clearSlct = "getSelection" in window ? function() {
 2                 window.getSelection().removeAllRanges();
 3             } : function() {
 4                 document.selection.empty();
 5             };
 6             $(window).on("mouseup keyup", function() {
 7                 clearSlct();
 8             });
 9             document.getElementById('warp').oncontextmenu = function(e){
10                 e.preventDefault();
11                };
12             var dragDemo=new dragImg('block1','dragImg','wheelImg');
View Code

js代码,构造器+原型链进行面向对象开发:

function dragImg(bgDivId, imgId, bgImgId) {
    this.disX = 0;
    this.disY = 0; //初始点击点

    this.xx = 0;
    this.yy = 0; //点击点相对于button的左上角的距离left,top

    this.marginX = 0;
    this.marginY = 0; //运动后底层图偏移量

    this.isdrag = false;
    this.clicky = 0;
    this.clickx = 0; //初始点击点
    this.oDragObj = null; //操作对象

    this.init(bgDivId, imgId);
    this.initBgDiv(bgDivId);
    this.initMouseWheel(bgImgId);
}

dragImg.prototype = {
    init: function(bgDivId, imgId) { //图标拖拽
        dragImg.imgId = imgId;
        dragImg.bgDivId = bgDivId;
        var drag_Img = document.getElementById(imgId),
            bg_div = document.getElementById(bgDivId);
        drag_Img.addEventListener('mousedown', dragDownEvent, false);
        drag_Img.addEventListener('mouseup', dragUpEvent, false);

        function dragDownEvent(e) {
            $('.dragBtnSpan').remove();
            var oevent = e || e.event;
            if(oevent.button == 0) {
                var layerX = oevent.offsetX || oevent.layerX,
                    layerY = oevent.offsetY || oevent.layerY;

                dragImg.disX = oevent.clientX - drag_Img.offsetLeft;
                dragImg.disY = oevent.clientY - drag_Img.offsetTop;

                dragImg.xx = oevent.clientX - drag_Img.offsetLeft;
                dragImg.yy = oevent.clientY - drag_Img.offsetTop;
                document.onmousemove = dragMoveEvent;
            }
        }

        function dragMoveEvent(e) {
            var oevent = e || e.event;
            var x = oevent.clientX,
                y = oevent.clientY;
            var offsetx = x - dragImg.disX,
                offsety = y - dragImg.disY;
            //                console.log(offsetx,offsety);
            if(offsetx < 0) {
                offsetx = 0;
            } else if(offsetx > document.documentElement.clientWidth - drag_Img.offsetWidth) {
                offsetx = document.documentElement.clientWidth - drag_Img.offsetWidth;
            }
            if(offsety < 0) {
                offsety = 0;
            } else if(offsety > document.documentElement.clientHeight - drag_Img.offsetHeight) {
                offsety = document.documentElement.clientHeight - drag_Img.offsetHeight;
            }
            $("#" + dragImg.imgId).css('left', offsetx);
            $("#" + dragImg.imgId).css('top', offsety);
        }

        function dragUpEvent(e) {
            //拖拽结束,判断是否在允许放置的范围内(当前位置是否与底层图相交)
            var oevent = e || e.event;
            if(oevent.button == 0) {
                $('.dragBtn').remove();
                var x = oevent.clientX,
                    y = oevent.clientY;
                var zoom = bg_div.style.zoom; //缩放比例
                var btn_X = drag_Img.offsetLeft,
                    btn_Y = drag_Img.offsetTop,
                    btn_width = drag_Img.offsetWidth * zoom,
                    btn_height = drag_Img.offsetHeight * zoom,
                    //缩放后长度,位置都会发生变化,需要*缩放倍率
                    map_X = bg_div.offsetLeft * zoom,
                    map_Y = bg_div.offsetTop * zoom,
                    map_left = bg_div.style.left,
                    map_top = bg_div.style.top,
                    map_width = bg_div.offsetWidth * zoom,
                    map_height = bg_div.offsetHeight * zoom;
                var m = (btn_X + dragImg.xx > map_X + map_width) || (btn_X + dragImg.xx + btn_width < map_X);
                var n = (btn_height + btn_Y + dragImg.yy < map_Y) || (btn_Y + dragImg.yy > map_Y + map_height);
                if(m || n) {
                    console.log('相离');
                } else {
                    //缩放后位置会偏移
                    var yesIE = IEVersion();
                    if(yesIE != -1) {
                        //ie浏览器获取的就是实际偏移量,需要清除缩放倍率
                        if(yesIE > 8 || yesIE == 'Edge') {
                            dragImg.marginX = bg_div.offsetLeft;
                            dragImg.marginY = bg_div.offsetTop;
                        }
                    } else {
                        dragImg.marginX = map_X,
                        dragImg.marginY = map_Y;
                    }
                    var percentX = (x - dragImg.marginX - dragImg.xx) / zoom;
                    var percentY = (y - dragImg.marginY - dragImg.yy) / zoom;
                    //                console.log('percentXxxxx',percentX);
                    //                console.log('percentYyyyy',percentY);
                    LONG=percentX;//选定坐标点,赋值全局变量
                    LAT=percentY;
                    var createImg = document.createElement('img');
                    createImg.src = 'resources/images/point_easyicon.png';
                    createImg.style.left = percentX + 'px';
                    createImg.style.top = percentY + 'px';
                    var btnId = 'btn_' + parseInt(percentX) + "_" + parseInt(percentY);
                    createImg.setAttribute('id', btnId);
                    createImg.setAttribute('class', 'dragBtn');
                    bg_div.appendChild(createImg);
                    $("#" + btnId).on('mousedown', function(event) {
                        if(event.button == 2) {
                            $('.dragBtnSpan').remove();
                            var dragBtnSpan = document.createElement('ul');
                            var htm = '<li><a href="javascript:(0);" onclick="alert(123);">移动</a></li><li><a href="javascript:(0);" onclick="alert(456);">删除</a></li>';
                            dragBtnSpan.innerHTML = htm;
                            dragBtnSpan.setAttribute('id', btnId + 'ul');
                            dragBtnSpan.setAttribute('class', 'dragBtnSpan');
                            bg_div.appendChild(dragBtnSpan);
                            $('#' + btnId + 'ul').css('left', percentX + 10).css('top', percentY + 10).show();
                        }
                    });
                    $("#dragImg").css('left', 10);
                    $("#dragImg").css('top', 10);
                }
                document.onmousemove = null;
            }
        }
    },
    initBgDiv: function(bgDivId) { //底层图拖拽
        dragImg.bgDivId = bgDivId;
        var bg_div = document.getElementById(bgDivId);
        bg_div.addEventListener('mousedown', initDrag, false);
        document.onmouseup = new Function("dragImg.isdrag=false");

        function initDrag(e) {
            if(e.button == 0) {
                var nn6 = document.getElementById && !document.all;
                var oDragHandle = nn6 ? e.target : event.srcElement;
                var topElement = "HTML";
                while(oDragHandle.tagName != topElement && oDragHandle.className.indexOf("dragAble") == -1) {
                    oDragHandle = nn6 ? oDragHandle.parentNode : oDragHandle.parentElement;
                }
                if(oDragHandle.className.indexOf("dragAble") != -1) {
                    dragImg.isdrag = true;
                    dragImg.oDragObj = oDragHandle;
                    nTY = parseInt(dragImg.oDragObj.style.top + 0); //当前初始位置
                    dragImg.clicky = nn6 ? e.clientY : event.clientY; //点击位置
                    nTX = parseInt(dragImg.oDragObj.style.left + 0);
                    dragImg.clickx = nn6 ? e.clientX : event.clientX;
                    // oDragObj.style.zIndex++;
                    document.onmousemove = moveMouse;
                    return false;
                }
            }
        }

        function moveMouse(e) {
            if(dragImg.isdrag) { //初始位置+运动长度-点击时位置
                var oevent = e || window.event;
                var clientX = oevent.clientX,
                    clientY = oevent.clientY;
                var moveX = nTX + clientX - dragImg.clickx,
                    moveY = nTY + clientY - dragImg.clicky;
                dragImg.oDragObj.style.top = moveY + "px";
                dragImg.oDragObj.style.left = moveX + "px";
                return false;
            }
        }

    },
    initMouseWheel: function(bgImgId) { //底层图鼠标滚轮缩放
        var bg_img = document.getElementById(bgImgId);
        //        if (document.addEventListener) {
        bg_img.addEventListener('mousewheel', onWheelZoom, false); //IE9, Chrome, Safari, Oper
        //            bg_img.addEventListener('wheel', onWheelZoom, false); //Firefox
        //            bg_img.addEventListener('DOMMouseScroll', onWheelZoom, false); //Old Firefox
        //        } else {
        //            bg_img.attachEvent('onmousewheel', onWheelZoom); //IE 6/7/8
        //        }
        function onWheelZoom(e) {
            $('.dragBtnSpan').remove();
            var obj = e.srcElement ? e.srcElement : e.target;
            var parentNode = obj.parentNode || obj;
            zoom = parseFloat(parentNode.style.zoom); //操作行内样式zoom,行内必须有zoom属性,不支持firefox
            var wheelDelta = event.wheelDelta || event.deltaY;

            tZoom = zoom + (wheelDelta > 0 ? 0.1 : -0.1);
            if(tZoom < 0.5) {
                return true;
            }
            parentNode.style.zoom = tZoom;
            return false;
        }
    },
    getPosition: function(node) {
        var left = node.offsetLeft; //获取元素相对于其父元素的left值var left
        var top = node.offsetTop;
        current = node.offsetParent; // 取得元素的offsetParent
          // 一直循环直到根元素
          
        while(current != null) {  
            left += current.offsetLeft;  
            top += current.offsetTop;  
            current = current.offsetParent;  
        }
        return {
            "left": left,
            "top": top
        };
    }
}
View Code

由于ie8和火狐需要更多的兼容性考虑,时间关系就没有支持ie8和火狐。

function IEVersion() {
    var version = -1;
    var userAgent = navigator.userAgent;
    var isIE = userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1;
    var isEdge = userAgent.indexOf('Edge') > -1 && !isIE;
    var isIE11 = userAgent.indexOf('Trident') > -1 && userAgent.indexOf('rv:11.0') > -1;
    if(isIE) {
        if(userAgent.indexOf("MSIE 5.5") > 0) {
            version = 5.5;
        } else if(userAgent.indexOf("MSIE 6.0") > 0) {
            version = 6;
        } else if(userAgent.indexOf("MSIE 7.0") > 0) {
            version = 7;
        } else if(userAgent.indexOf("MSIE 8.0") > 0 || (userAgent.indexOf("MSIE 9.0") > 0 && !window.innerWidth)) {
            version = 8;
        } else if(userAgent.indexOf("MSIE 9.0") > 0) {
            version = 9;
        } else {
            version = 10;
        }
    } else if(isEdge) {
        version = 'Edge';
    } else if(isIE11) {
        version = 11;
    } else {
        version = -1;
    }
    return version;
}
View Code

 

代码写的都很简单,关键位置都有注释,各位不要见笑。

posted on 2018-09-13 15:10  过路的妖怪  阅读(3654)  评论(1编辑  收藏  举报