• 爬虫可视化点选配置工具之获取鼠标点选元素


    前言

    前面两章已经介绍怎么开发一个chrome插件和怎么使用vue搭建一个弹出框的chrome插件,这一章来实现页面元素选择的功能,效果如下图,鼠标放到元素上,元素会高亮:

    主要实现思路,创建一个和页面一样宽高的蒙层,监听蒙层的鼠标移动事件,再使用elementFromPoint函数来获得当前鼠标所在位置的页面元素,具体实现如下:
    shelter.js这是主函数

    
    import $ from 'jquery';
    import validateSelect from './validateSelected';
    import isContentElement from "./isContentElement";
    
    //选择遮罩
    export default class {
        constructor() {
            this.shelter = $("<div class='layuiex'></div>"); //选择过程中的div
            this.shelter.attr("id", "__pAp_SpiderShelter");
    
            this.block = $("<div class='layuiex'></div>");
    
            this.lastSelectEl = null; //当前鼠标移动到元素
            this.shelterInterval = null;
    
            $(document.body).append(this.shelter);
            $(document.body).append(this.block);
        }
    
        beginSelect(onDomClick, onContextMenu, callback) {
            let that = this;
            this.shelter.css("position", "absolute");
            this.shelter.css("display", "block");
            this.shelter.addClass("pAp_spider_Selecter_Block");
            this.shelter.bind("click", onDomClick);
            this.shelter.show();
            this.shelter.css("width", "100%");
            this.shelter.css("height", $(document).height() + "px");
            this.shelter.css("left", "0");
            this.shelter.css("top", "0");
            this.shelter.mousemove(this.onShelterMouseMove(callback));
            //初始化遮罩
            function initCover() {
                that.shelterInterval = setInterval(function() {
                    //如果遮罩层的高度小于页面高度,则将遮罩的高度设置成页面高度
                    if ($(document).height() > that.shelter.height()) {
                        that.hideCover();
                        that.showCover();
                    }
                }, 500);
            }
    
            //鼠标移动到遮罩层上的时候,重置遮罩层
            this.shelter.mouseover(function() {
                if (that.shelterInterval) {
                    clearInterval(that.shelterInterval);
                    that.shelterInterval = null;
                }
            }).mouseout(initCover);
    
            this.block.css("position", "absolute");
            this.block.css("display", "block");
            this.block.show();
            this.showShelter(); //显示遮罩阴影
            this.block.css("z-index", "19891009")
            this.shelter.css("z-index", "19891010");
    
            //绑定右键事件
            document.oncontextmenu = onContextMenu;
    
            //鼠标滚动事件,目的是防止页面滚动
            $(this.shelter).on("mousewheel", function(evt) {
                event.stopPropagation();
                event.preventDefault();
                var height = evt.originalEvent.wheelDelta;
                if (!that.lastSelectEl) return;
                var el = that.lastSelectEl.get(0);
                while (el) {
                    if (el.scrollHeight > el.offsetHeight || el.tagName == "BODY") {
                        var lastTop = el.scrollTop;
                        el.scrollTop = el.scrollTop - height;
                        if (lastTop !== el.scrollTop) {
                            break;
                        }
                    }
                    el = el.parentElement;
                }
            });
            initCover();
        };
    
        endSelect(callback) {
            if (this.shelterInterval) {
                clearInterval(this.shelterInterval);
                this.shelterInterval = null;
            }
            this.shelter.unbind();
            this.shelter.remove();
            this.block.remove();
            $(document).unbind();
            document.oncontextmenu = function() {};
            callback && callback();
        };
    
        showShelter() {
            this.block.css("box-shadow", "0 0 20px #d4930d");
        };
    
        hideShelter() {
            this.block.css("box-shadow", "none");
        };
    
        //鼠标移动时的操作
        onShelterMouseMove(callback) {
            let that = this;
            var position = {
                x: 0,
                y: 0
            };
    
            return function(e) {
                event.stopPropagation();
                if (Math.abs(position.x - e.pageX) > 10 || Math.abs(position.y - e.pageY) > 10) {
                    //隐藏蒙层
                    that.hideCover();
                    //返回当前鼠标所在位置的最顶层元素,也就是鼠标所在的页面元素
                    var el = $(document.elementFromPoint(e.clientX, e.clientY));
                    //显示蒙层
                    that.showCover();
    
                    //如果是弹出框或者是遮罩则返回
                    if (!isContentElement(el)) return;
    
                    //如果元素中有我们生成的属性,则取父元素
                    if (!validateSelect(el)) {
                        el = el.parent();
                    }
                    if (!that.lastSelectEl || that.lastSelectEl.get(0) != el.get(0)) {
                        that.lastSelectEl = el;
                    }
                    position = {
                        x: e.pageX,
                        y: e.pageY
                    };
                    that.setPosition(el, that.block);
                    callback && callback(that.lastSelectEl);
                }
            }
        }
    
        setShelterPosition(el) {
            this.setPosition(el, this.shelter);
        }
    
        /**
         * 把选择框设置当当前选择元素的位置
         * @param {Jquery Dom Element} el 选择的元素
         * @param {Jquery Dom Element} shelter 遮罩层
         */
        setPosition(el, shelter) {
            if ((el.width() == 0 || el.height() == 0) && el.get(0).tagName == 'A' && el.children().length) {
                that.setPosition(el.children().eq(0), shelter);
                return;
            }
    
            var paddingObject = {
                left: parseInt(el.css("padding-left")),
                top: parseInt(el.css("padding-top")),
                right: parseInt(el.css("padding-right")),
                bottom: parseInt(el.css("padding-bottom"))
            };
    
            var _width = 0,
                _height = 0;
            if (!isNaN(paddingObject.left)) {
                _width += paddingObject.left;
            }
            if (!isNaN(paddingObject.right)) {
                _width += paddingObject.right;
            }
            if (!isNaN(paddingObject.top)) {
                _height += paddingObject.top;
            }
            if (!isNaN(paddingObject.bottom)) {
                _height += paddingObject.bottom;
            }
    
            var top = parseInt(el.offset().top);
            var height = el.height() + _height;
            var availHeight = $(document).height() - top;
            height = height > availHeight ? availHeight : height;
    
            var obj = {
                "left": parseInt(el.offset().left) + "px",
                "top": top + "px",
                "width": el.width() + _width,
                "height": height
            };
    
            shelter.css(obj);
        };
    
        hideCover() {
            this.block.css("z-index", "-2")
            this.shelter.css("z-index", "-1");
            this.shelter.css("display", "none");
            this.block.css("display", "none");
        };
    
        showCover() {
            this.shelter.css("display", "block");
            this.block.css("display", "block");
            this.block.css("z-index", "19891009")
            this.shelter.css("z-index", "19891010");
    
            var height = $(document).height();
            this.shelter.css("width", "100%");
            this.shelter.css("height", height + "px");
            this.shelter.css("left", "0");
            this.shelter.css("top", "0");
        };
    
        setBlockCss(key, value) {
            this.block.css(key, value);
        }
    
        setShelterCss(key, value) {
            this.shelter.css(key, value);
        }
    }
    

    validateSelected.js确保所选择的元素是页面本身的元素

    
    import $ from 'jquery';
    
    /**
     * 判断是否有我们生成的元素,即被我们标记为选中的元素
     * @param {*} element 
     */
    export default function(element) {
        var el = $(element);
    
        if (el.attr("__pAp_select")) {
            return false;
        }
    
        if (el.hasClass("__pAp_selectrow")) {
            return false;
        }
        return true;
    };
    

    isContentElement.js这个函数的作用也是确保所选择的的元素是页面自有的元素

    
    import $ from 'jquery';
    
    /*
        判断是否内容元素,也就是判断是不是我们的弹出框或者是遮罩
    */
    export default function(element) {
        var expectClasses = [".layuiex", ".layuiex-layer", ".layuiex-layer-shade", ".layuiex-layer-moves", ".pAp_spider_Selecter_Block"];
        for (var _i = 0; _i < expectClasses.length; _i++) {
            var els = $(expectClasses[_i]);
            for (var a = 0; a < els.length; a++) {
                //$.contains( container, contained )
                //检测一个元素包含在另一个元素之内
                //container    Element类型 指定可能包含其他元素的祖辈容器元素。
                //contained    Element类型 指定可能被其他元素包含的后代元素。
                if ($.contains(els.eq(a).get(0), element) || els.eq(a).get(0) == element) {
                    return false;
                }
            }
        }
        return true;
    };
    

    这样页面选择函数就写完了,下面就是引用了,在main.js中添加函数

    
    import Vue from 'vue';
    import $ from "jquery";
    import './layer/layer.css';
    import layer from './layer/layer';
    import shelter from './js/selector/shelter';
    
    Vue.config.productionTip = false;
    let shelterUi = new shelter();
    
    ......
    
    new Vue({
        el: "#__paApa_container",
        components: {},
        data() {
            return {
                selectedEl: null
            };
        },
        mounted() {
            let that = this;
            shelterUi.beginSelect(that.onDomClick, null,
                function(selectedEl) {
                    that.selectedEl = selectedEl;
                });
        },
        methods: {
            onDomClick() {
                console.log('点击');
            }
        }
    });
    

    以上就完成了页面选择功能

    原文地址:https://segmentfault.com/a/1190000016750965

  • 相关阅读:
    HTML超链接应用场景
    String 字符串和StringBuffer的知识点总结
    猜数游戏代码
    MemoryLayout
    偏swift框架
    git的使用
    寄存器
    swift基础
    枚举
    安装Ubuntu 20.04 以后
  • 原文地址:https://www.cnblogs.com/lalalagq/p/9903808.html
Copyright © 2020-2023  润新知