矩形框选滚动

主要用来实现下图的效果,通过鼠标左键按住框选元素,将框选的元素返回
很少用js写前端了,最近项目需要,用的Js来实现功能,有不足的地方还请帮忙指出
在这里插入图片描述

/**
 * 矩形框选页面上元素并回填
 * 通过改变屏幕的pageStatus来实现屏幕上的鼠标事件的操作
 * 在页面加载的时候给鼠标绑定事件,当pageStatus为指定的状态时,则可以执行事件对应的操作
 * $("#rightspan")[0] 指的也是页面对象,主要用来获取页面已经滚动的距离
 */
function onSelectPluginClone() {
    //这里的y1 y2 指的都是在所有页面上的位置,不是屏幕上的位置
    let x1, y1, x2, y2;
    //表示的是所有页面上的元素
    let $content = $("#content");

    // 1、鼠标点击确定起始坐标并准备绘制选框
    $content.on("mousedown", function (e) {
        // 1、判断页面状态  如果是指定的状态表示进入框选状态,否之不管
        if (window.pageStatus !== "selectable") {
            return;
        }
        // 2、记录选区起始坐标
        x1 = e.clientX;
        //选框开始的位置应该为当前屏幕的距离+已经滚动的距离
        y1 = e.clientY + $("#rightspan")[0].scrollTop;
        // 3、创建选区 创建该div为选区元素,主要用来显示一个框告知用户框选的范围,目前是隐藏状态在移动时恢复显示
        $content.append(`<div id="area" style="display: none;position: absolute;z-index: 9999999;border: 2px solid blue;"></div>`);
        // 4、阻止文字拖拽和选择
        e.preventDefault();
    });
    // 2、鼠标移动调整选框位置和宽高
    $content.on("mousemove", function (e) {
        // 1、判断页面状态 x1为空或x2为空表示选区还未创建,起始位置还未确定,暂时不执行
        if (window.pageStatus !== "selectable" || !x1 || !y1) {
            return;
        }
        //当光标到距离屏幕底部50px的距离则屏幕往下滚动
        if (e.clientY >= window.screen.height - 50) {
            $("#rightspan")[0].scrollTop += (e.clientY - window.screen.height + 75)
        }
        // 2、调整选框位置和宽高
        //解释:e.clientY + $("#rightspan")[0].scrollTop - y1
        //选框高度为  当前鼠标的位置+已经滚动的距离-选框的起始位置
        let width = Math.abs(e.clientX - x1), 
            height = Math.abs(e.clientY + $("#rightspan")[0].scrollTop - y1);
        //这里用min取小值主要为了可能框选的位置是从往左上框选
        let top = Math.min(e.clientY + $("#rightspan")[0].scrollTop, y1), 
            left = Math.min(e.clientX, x1);
        let $area = $("#area");
        //如果父元素已经改变过位置,则需要减去父元素的位置
        let parentTop = parseFloat($("#rightspan").css("top"));
        let parentLeft = parseFloat($("#rightspan").css("left"));
        top -= parentTop;
        left -= parentLeft
        $area.css("width", width + "px");
        $area.css("height", height + "px");
        $area.css("left", left + "px");
        $area.css("top", top + "px");
        $area.show();
    });
    // 3、鼠标松开确定结束结点,并处理选区中的组件
    $content.on("mouseup", function (e) {
        // 1、判断页面状态
        if (window.pageStatus !== "selectable" || !x1 || !y1) {
            return;
        }

        // 2、记录结束坐标,保证x1 < x2, y1 < y2  如果选框在起始点左上位置,
        //    则当前选框结束位置变为开始位置,开始位置作为结束位置
        if (e.clientX > x1) {
            x2 = e.clientX;
        } else {
            x2 = x1;
            x1 = e.clientX;
        }
        //如果当前鼠标的位置+滚动的距离  大于开始的位置,则表示是往右下框选,正常获取选框
        if (e.clientY + $("#rightspan")[0].scrollTop > y1) {
            y2 = e.clientY + $("#rightspan")[0].scrollTop;
        } else {
            y2 = y1;
            y1 = e.clientY + $("#rightspan")[0].scrollTop;
        }
        handleMouseUp();
    });

    /**
     * 处理鼠标松开事件
     */
    function handleMouseUp() {
        // 1、获取区间内所有组件,当组件太多的时候可能会出现效率问题
        let plugins = Array.from($content.find(".ui-plugin"));
        let rightSpan = $("#rightspan")[0];
        // 2、筛选出有效组件
        let selectedPlugins = null
        selectedPlugins = plugins.filter(plugin => {
            // 需要减去滚动距离
            let left = offset(plugin, "left") - rightSpan.scrollLeft,
                top = offset(plugin, "top");
            let width = plugin.offsetWidth,
                height = plugin.offsetHeight;
            //组件到左边的距离在起始x1内,到顶端的距离在起始y1内
            //且组件到左边的距离+组件本身的宽度在框选结束x2内
            //且组件到顶部的距离+组件本身的高度在框选结束y2内
            //表示该组件位于框选的位置内,将组件加入
            return left >= x1 && top >= y1 && (left + width) <= x2 && (top + height) <= y2;
        });
        // 3、重置坐标,并删除选区
        x1 = 0;
        y1 = 0;
        x2 = 0;
        y2 = 0;
        $("#area").remove();
        // 4、处理组件
        handleSelectedPlugins(selectedPlugins);
        // 5、更改页面状态
        $(".content").removeClass("selectable");
        $("#page-container").removeClass("top");
        window.pageStatus = "edit";
    }

    /**
     * 处理选中的组件
     * @param plugins
     */
    function handleSelectedPlugins(plugins) {
        if (plugins.length < 1) {
            return
        }
        //对选中的组件集合plugins进行操作
    }

    /**
     * 获取元素距离左边界和上边界的实际值
     * @param ele
     * @param leftOrTop
     */
    function offset(ele, leftOrTop) {
        // offsetLeft Or offsetTop
        let offsetDir = "offset" + leftOrTop[0].toUpperCase() + leftOrTop.substring(1);
        //获取元素的 左 | 上的距离
        let realValue = ele[offsetDir];
        //遍历元素的父元素,获得元素的父元素到外层的距离
        let parent = ele.offsetParent;
        while (parent !== null) {
            realValue += parent[offsetDir];
            parent = parent.offsetParent;
        }
        return realValue;
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 PyQt5 中的 QGraphicsView 和 QGraphicsScene 实现这个功能。以下是一个简单的示例代码: ```python import sys from PyQt5.QtWidgets import QApplication, QGraphicsView, QGraphicsScene from PyQt5.QtGui import QPixmap, QPen, QColor from PyQt5.QtCore import Qt class ImageViewer(QGraphicsView): def __init__(self): super().__init__() # 创建场景 self.scene = QGraphicsScene() self.setScene(self.scene) # 加载图片 self.image = QPixmap('image.jpg') self.scene.addPixmap(self.image) # 设置滚动条策略 self.setVerticalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setHorizontalScrollBarPolicy(Qt.ScrollBarAsNeeded) self.setDragMode(QGraphicsView.ScrollHandDrag) # 设置缩放策略 self.setRenderHint(QPixmap.Antialiasing) self.setRenderHint(QPixmap.SmoothTransformation) self.setRenderHint(QPixmap.HighQualityAntialiasing) self.setInteractive(True) self.setTransformationAnchor(QGraphicsView.AnchorUnderMouse) self.setResizeAnchor(QGraphicsView.AnchorUnderMouse) # 画笔和矩形框 self.pen = QPen(QColor(255, 0, 0, 128)) self.rect = None self.start_pos = None def wheelEvent(self, event): # 按住 Ctrl 键滚动鼠标滚轮进行缩放 if event.modifiers() == Qt.ControlModifier: delta = event.angleDelta().y() factor = 1.1 if delta > 0 else 0.9 self.scale(factor, factor) else: super().wheelEvent(event) def mousePressEvent(self, event): # 按下鼠标左键开始框矩形 if event.button() == Qt.LeftButton: self.start_pos = event.pos() def mouseMoveEvent(self, event): # 移动鼠标更新框矩形 if self.start_pos is not None: if self.rect is not None: self.scene.removeItem(self.rect) self.rect = self.scene.addRect(self.start_pos.x(), self.start_pos.y(), event.pos().x() - self.start_pos.x(), event.pos().y() - self.start_pos.y(), self.pen) def mouseReleaseEvent(self, event): # 松开鼠标左键结束框矩形并输出坐标 if event.button() == Qt.LeftButton: if self.rect is not None: self.scene.removeItem(self.rect) self.rect = self.scene.addRect(self.start_pos.x(), self.start_pos.y(), event.pos().x() - self.start_pos.x(), event.pos().y() - self.start_pos.y(), self.pen) print(self.rect.boundingRect().x(), self.rect.boundingRect().y(), self.rect.boundingRect().width(), self.rect.boundingRect().height()) self.start_pos = None if __name__ == '__main__': app = QApplication(sys.argv) viewer = ImageViewer() viewer.show() sys.exit(app.exec_()) ``` 在这个示例中,我们创建了一个 ImageViewer 类,并在其中添加了 QGraphicsView 和 QGraphicsScene。我们加载了一张图片并将其添加到场景中。然后我们设置了滚动条和缩放策略,并重载了鼠标事件来实现矩形框和输出坐标的功能。最后我们创建了一个 QApplication 并展示了 ImageViewer。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值