Js 可视化框选Dom元素,Xpath路径变更Dom元素

 应用于可视化埋点需求,需要一个JS能够通过框选 获取页面的DOM元素

且记录Xpath路径,用于后续对Dom进行后续的操作

简单做了Demo,后续继续优化

<!doctype html>
<html>
<head>
    <title>Js 可视化圈选Dom元素,Xpath路径变更Dom</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        .drawDiv {
            position: absolute;
            background: #ccc;
        }


        .selBlue {
            border: 1px dashed blue !important;
        }


        .sel {
            margin: 30px auto;
            width: 960px;
            overflow: hidden
        }

        li {
            list-style: none;
            float: left;
            width: 60px;
            height: 20px;
        }

        .selColor {
            float: left
        }


        .xz {
            width: 340px;
            float: left;
        }

        #canvas {
            width: 960px;
            height: 500px;
            border: 1px solid #ccc;
            margin: 0 auto
        }
    </style>
    <script>


        function del(){
            var xpath=document.getElementById("xPath").value;
            var doc=getElem(xpath);
            if(doc!=""){
                var classVal = doc.getAttribute("class");
                classVal=classVal.replace("selBlue");
                doc.setAttribute("class",classVal);
            }
        };


        function $Id(id) {
            return document.getElementById(id);
        }

        function getXPath(elm) {
            let allNodes = document.getElementsByTagName('*')
            for (var segs = []; elm && elm.nodeType == 1; elm = elm.parentNode) {
                if (elm.hasAttribute('id')) {
                    let uniqueIdCount = 0
                    for (var n = 0; n < allNodes.length; n++) {
                        if (allNodes[n].hasAttribute('id') && allNodes[n].id == elm.id) uniqueIdCount++;
                        if (uniqueIdCount > 1) break;
                    }
                    if (uniqueIdCount == 1) {
                        segs.unshift('//*[@id="' + elm.getAttribute('id') + '"]');
                        return segs.join('/');
                    } else {
                        return false
                    }
                } else {
                    for (var i = 1, sib = elm.previousSibling; sib; sib = sib.previousSibling) {
                        if (sib.localName == elm.localName) i++;
                    }
                    if (i == 1) {
                        if (elm.nextElementSibling) {
                            if (elm.nextElementSibling.localName != elm.localName) {
                                segs.unshift(elm.localName.toLowerCase())
                            } else {
                                segs.unshift(elm.localName.toLowerCase() + '[' + i + ']');
                            }
                        } else {
                            segs.unshift(elm.localName.toLowerCase())
                        }
                    } else {
                        segs.unshift(elm.localName.toLowerCase() + '[' + i + ']');
                    }
                }
            }
            return segs.length ? '/' + segs.join('/') : null
        };

        function getElem(path) {
            try {
                var evaluator = new XPathEvaluator();
                var result = evaluator.evaluate(path, document.documentElement, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
                return result.singleNodeValue || '';
            } catch (e) {
                console.log(e)
                return ''
            }
        };



        window.onload = function () {
            var oCanvas = $Id('canvas');

            // var oRadius = $Id('radius');
            var aInputs = document.getElementsByTagName('input');
            var xz = 'none';
            var arr = [];
            for (var i = 0; i < aInputs.length; i++) {
                if (aInputs[i].type == 'checkbox') {
                    arr.push(aInputs[i]);
                }
            }
            for (var i = 0; i < arr.length; i++) {
                arr[i].onclick = function () {
                    if (!this.checked) {
                        this.checked = false;
                    } else {
                        for (var j = 0; j < arr.length; j++) {
                            arr[j].checked = false;
                        }
                        this.checked = true;
                        xz = this.value;
                    }
                }
            }

            document.onclick = function (ev) {
                for (var i = 0; i < arr.length; i++) {
                    if (arr[i].checked) {
                        arr[i].checked = true;
                        xz = arr[i].value;
                        if (xz != "none") {
                            return;
                        }
                    }
                }
                var x = ev.clientX;
                var y = ev.clientY;
                var delDocArr = document.elementsFromPoint(x, y);
                for (var delDoc of delDocArr) {
                    var classVal = delDoc.getAttribute("class");
                    //如果圈选的内容已经存在了,则跳过
                    if (classVal!=null && classVal.indexOf("selBlue")>=0) {
                        console.log(delDoc);
                        // alert("选择了删除,删除圈选内容:" + delDoc.id);
                        console.log("选择了删除,删除圈选内容:" + delDoc.id);
                        // delDoc.remove();
                        var selDivName = document.getElementById("selDivName");
                        selDivName.value = delDoc.id;
                        var xPath = getXPath(delDoc);
                        document.getElementById("xPath").value = xPath;
                    }
                }

            }

            oCanvas.onmousedown = function (ev) {
                if (oCanvas.setCapture) {
                    oCanvas.setCapture();
                }
                for (var i = 0; i < arr.length; i++) {
                    if (arr[i].checked) {
                        arr[i].checked = true;
                        xz = arr[i].value;
                        if (xz != "select") {
                            return;
                        }
                    }
                }
                var oEv = ev || window.event;
                var disX = oEv.clientX;
                var disY = oEv.clientY;
                var oR = document.createElement('div');
                // oR.id = "div";
                oR.className = "drawDiv"
                oR.style.top = disY + 'px';
                oR.style.left = disX + 'px';
                // oR.style.backgroundColor = color;
                oR.style.border = '1px dashed red';
                oR.style.backgroundColor = 'transparent';
                document.body.appendChild(oR);

                document.onmousemove = function (ev) {
                    if (oCanvas.setCapture) {
                        oCanvas.setCapture();
                    }
                    var oEv = ev || window.event;
                    var x = oEv.clientX;
                    var y = oEv.clientY;
                    if (x < oCanvas.offsetLeft) {
                        x = oCanvas.offsetLeft;
                    } else if (x > oCanvas.offsetLeft + oCanvas.offsetWidth) {
                        x = oCanvas.offsetLeft + oCanvas.offsetWidth
                    }
                    if (y < oCanvas.offsetTop) {
                        y = oCanvas.offsetTop;
                    } else if (y > oCanvas.offsetTop + oCanvas.offsetHeight) {
                        y = oCanvas.offsetTop + oCanvas.offsetHeight
                    }
                    oR.style.width = Math.abs(x - disX) + 'px';
                    oR.style.height = Math.abs(y - disY) + 'px';
                    oR.style.top = Math.min(disY, y) + 'px';
                    oR.style.left = Math.min(disX, x) + 'px';
                }

                document.onmouseup = function (ev) {
                    if (oCanvas.setCapture) {
                        oCanvas.setCapture();
                    }
                    var x = event.clientX;
                    var y = event.clientY;
                    var divx1 = oCanvas.offsetLeft;
                    var divy1 = oCanvas.offsetTop;
                    var divx2 = oCanvas.offsetLeft + oCanvas.offsetWidth;
                    var divy2 = oCanvas.offsetTop + oCanvas.offsetHeight;

                    if (x < divx1 || x > divx2 || y < divy1 || y > divy2) {
                        console.log("在外面");
                        // return;
                    } else {
                        console.log("在里面");
                        if (xz == 'select') {
                            document.onmousemove = null;
                            document.onmouseout = null;

                            var leftX = parseInt(oR.style.left.replace("px", ""));
                            var leftY = parseInt(oR.style.top.replace("px", ""));

                            var rightX = leftX + parseInt(oR.style.width.replace("px", ""));
                            var rightY = leftY + parseInt(oR.style.height.replace("px", ""));

                            console.log("左上角坐标点xy:" + leftX + "," + leftY);
                            console.log("右下角坐标点xy:" + rightX + "," + rightY);

                            // var cc=0;
                            var domArr = [];
                            outer:
                                for (var i = leftX; i <= rightX; i += 5) {
                                    for (var k = leftY; k <= rightY; k += 5) {
                                        var ddArr = document.elementsFromPoint(i, k);
                                        for (var add of ddArr) {
                                            // cc++;
                                            // console.log(cc)
                                            var dlx = parseInt(add.offsetLeft);
                                            var dly = parseInt(add.offsetTop);
                                            var dWidth = parseInt(add.offsetWidth);
                                            var dHight = parseInt(add.offsetHeight);
                                            var drx = dlx + dWidth;
                                            var dry = dly + dHight;
                                            if ( leftX<=dlx  &&  leftY <= dly && drx <= rightX && dry <= rightY) {
                                                if (domArr.indexOf(add) == -1 && add.className != "selBlue") {
                                                    // console.log("dl:"+dlx+","+dly+"--dr:"+drx+","+dry);
                                                    // console.log("ol:"+leftX+","+leftY+"--or:"+rightX+","+rightY);
                                                    var classVal = add.getAttribute("class");
                                                    //如果圈选的内容已经存在了,则跳过
                                                    if (classVal != null) {
                                                        if (classVal.indexOf("selBlue") >= 0) {
                                                            break outer;
                                                        }
                                                        classVal = classVal.concat(" selBlue");
                                                    } else {
                                                        classVal = "selBlue";
                                                    }
                                                    domArr.push(add);
                                                    console.log(add);
                                                    console.log("圈中的DIV:" + add.id);
                                                    alert("圈中的DIV:" + add.id);
                                                    add.setAttribute("class", classVal);

                                                    var selDivName = document.getElementById("selDivName");
                                                    selDivName.value = add.id;
                                                    var xPath = getXPath(add);
                                                    document.getElementById("xPath").value = xPath;
                                                    break outer;
                                                }
                                            }
                                        }
                                    }
                                    ;
                                };
                            // console.log(document.elementsFromPoint(ev.clientX, ev.clientY));
                            // console.log(domArr)
                            oR.remove();

                        }

                    }

                    if (oCanvas.releaseCapture) {
                        oCanvas.releaseCapture();
                    }
                }
                return false;
            }
        }
    </script>
</head>
<body>
<div class="sel">
    <span class="selColor">选择操作类型:</span>
    <p class="xz">
        <input type="checkbox" checked="checked" value="none" id="none"/>无操作
        <input type="checkbox" id="select" value="select"/>框选
        <!--        <input type="checkbox" id="del" value="select"/>删除-->
    </p>

</div>
<div id="canvas" style="float: left;margin-left: 10%">
    <div style="width: 30%;height: 40%;border: 1px solid red;float: left" id="div1"></div>

    <div style="width: 20%;height: 20%;margin-top: 25%;margin-left: 20% ;border: 1px solid black" id="div2">
        <div style="width: 20%;height: 20%;margin-top: 20px;margin-left: 20% ;border: 1px solid black" id="div3">
        </div>
    </div>
    <div style="width: 20%;height: 20%;margin-left: 60% ;border: 1px solid black" id="div4">
    </div>
</div>

<div style="width: 30%;height: 40%;border: 1px solid red;float: left;margin-left: 10px" id="divrg">
    选中的DIV <input type="text" value="" id="selDivName" style="width: 200px"/>
    <br>
    xPath路径 <input type="text" value="" id="xPath" style="width: 200px"/>
    <br>
    <button type="button" id="save">保存</button>
    <button type="button" id="del" onclick="del()">删除</button>
</div>

</body>
</html>

效果图

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值