【工作记录】基于CSS+JS可拖拽改变大小、可吸附到边界的DIV

news2024/12/28 3:04:47

记录一段实现可拖拽、可自动吸附到边界的代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <style>
        body {
            overflow: hidden;
        }
        #pane {
            position: absolute;
            width: 45%;
            height: 45%;
            top: 20%;
            left: 20%;
            margin: 0;
            padding: 0;
            z-index: 99;
            border: 2px solid purple;
            background: #fefefe;
        }

        #title {
            font-family: monospace;
            background: purple;
            color: white;
            font-size: 16px;
            height: 22px;
            text-align: center;
        }

        #ghostpane {
            background: #999;
            opacity: 0.2;
            width: 45%;
            height: 45%;
            top: 20%;
            left: 20%;
            position: absolute;
            margin: 0;
            padding: 0;
            z-index: 98;
            -webkit-transition: all 0.25s ease-in-out;
            -moz-transition: all 0.25s ease-in-out;
            -ms-transition: all 0.25s ease-in-out;
            -o-transition: all 0.25s ease-in-out;
            transition: all 0.25s ease-in-out;
        }
    </style>
    <title>测试div可拖拽</title>
    <meta http-equiv="Content-Type" content="text/html;charset=utf-8"/>
</head>
<body>
<div>
    这里是测试文本
</div>
<div id="pane">
    <div id="title">属性配置</div>
</div>
<div id="ghostpane"></div>
<script>
    // Minimum resizable area
    var minWidth = 400;
    var minHeight = 200;

    // Thresholds
    var FULLSCREEN_MARGINS = -10;
    var MARGINS = 4;

    // End of what's configurable.
    var clicked = null;
    var onRightEdge, onBottomEdge, onLeftEdge, onTopEdge;

    var rightScreenEdge, bottomScreenEdge;

    var preSnapped;

    var b, x, y;

    var redraw = false;

    var pane = document.getElementById('pane');
    var ghostpane = document.getElementById('ghostpane');

    function setBounds(element, x, y, w, h) {
        element.style.left = x + 'px';
        element.style.top = y + 'px';
        element.style.width = w + 'px';
        element.style.height = h + 'px';
    }

    function hintHide() {
        setBounds(ghostpane, b.left, b.top, b.width, b.height);
        ghostpane.style.opacity = 0;
    }


    // Mouse events
    pane.addEventListener('mousedown', onMouseDown);
    document.addEventListener('mousemove', onMove);
    document.addEventListener('mouseup', onUp);

    // Touch events
    pane.addEventListener('touchstart', onTouchDown);
    document.addEventListener('touchmove', onTouchMove);
    document.addEventListener('touchend', onTouchEnd);


    function onTouchDown(e) {
        onDown(e.touches[0]);
        e.preventDefault();
    }

    function onTouchMove(e) {
        onMove(e.touches[0]);
    }

    function onTouchEnd(e) {
        if (e.touches.length === 0) onUp(e.changedTouches[0]);
    }

    function onMouseDown(e) {
        onDown(e);
        e.preventDefault();
    }

    function onDown(e) {
        calc(e);

        var isResizing = onRightEdge || onBottomEdge || onTopEdge || onLeftEdge;

        clicked = {
            x: x,
            y: y,
            cx: e.clientX,
            cy: e.clientY,
            w: b.width,
            h: b.height,
            isResizing: isResizing,
            isMoving: !isResizing && canMove(),
            onTopEdge: onTopEdge,
            onLeftEdge: onLeftEdge,
            onRightEdge: onRightEdge,
            onBottomEdge: onBottomEdge
        };
    }

    function canMove() {
        return x > 0 && x < b.width && y > 0 && y < b.height && y < 30;
    }

    function calc(e) {
        b = pane.getBoundingClientRect();
        x = e.clientX - b.left;
        y = e.clientY - b.top;

        onTopEdge = y < MARGINS;
        onLeftEdge = x < MARGINS;
        onRightEdge = x >= b.width - MARGINS;
        onBottomEdge = y >= b.height - MARGINS;

        rightScreenEdge = window.innerWidth - MARGINS;
        bottomScreenEdge = window.innerHeight - MARGINS;
    }

    let e;

    function onMove(ee) {
        calc(ee);

        e = ee;

        redraw = true;

    }

    function animate() {

        requestAnimationFrame(animate);

        if (!redraw) return;

        redraw = false;

        if (clicked && clicked.isResizing) {

            if (clicked.onRightEdge) pane.style.width = Math.max(x, minWidth) + 'px';
            if (clicked.onBottomEdge) pane.style.height = Math.max(y, minHeight) + 'px';

            if (clicked.onLeftEdge) {
                var currentWidth = Math.max(clicked.cx - e.clientX + clicked.w, minWidth);
                if (currentWidth > minWidth) {
                    pane.style.width = currentWidth + 'px';
                    pane.style.left = e.clientX + 'px';
                }
            }

            if (clicked.onTopEdge) {
                var currentHeight = Math.max(clicked.cy - e.clientY + clicked.h, minHeight);
                if (currentHeight > minHeight) {
                    pane.style.height = currentHeight + 'px';
                    pane.style.top = e.clientY + 'px';
                }
            }

            hintHide();

            return;
        }

        if (clicked && clicked.isMoving) {

            if (b.top < FULLSCREEN_MARGINS || b.left < FULLSCREEN_MARGINS || b.right > window.innerWidth - FULLSCREEN_MARGINS || b.bottom > window.innerHeight - FULLSCREEN_MARGINS) {
                // hintFull();
                setBounds(ghostpane, 0, 0, window.innerWidth, window.innerHeight);
                ghostpane.style.opacity = 0.2;
            } else if (b.top < MARGINS) {
                // hintTop();
                setBounds(ghostpane, 0, 0, window.innerWidth, window.innerHeight / 2);
                ghostpane.style.opacity = 0.2;
            } else if (b.left < MARGINS) {
                // hintLeft();
                setBounds(ghostpane, 0, 0, window.innerWidth / 2, window.innerHeight);
                ghostpane.style.opacity = 0.2;
            } else if (b.right > rightScreenEdge) {
                // hintRight();
                setBounds(ghostpane, window.innerWidth / 2, 0, window.innerWidth / 2, window.innerHeight);
                ghostpane.style.opacity = 0.2;
            } else if (b.bottom > bottomScreenEdge) {
                // hintBottom();
                setBounds(ghostpane, 0, window.innerHeight / 2, window.innerWidth, window.innerWidth / 2);
                ghostpane.style.opacity = 0.2;
            } else {
                hintHide();
            }

            if (preSnapped) {
                setBounds(pane,
                    e.clientX - preSnapped.width / 2,
                    e.clientY - Math.min(clicked.y, preSnapped.height),
                    preSnapped.width,
                    preSnapped.height
                );
                return;
            }

            // moving
            pane.style.top = (e.clientY - clicked.y) + 'px';
            pane.style.left = (e.clientX - clicked.x) + 'px';

            return;
        }

        // This code executes when mouse moves without clicking

        // style cursor
        if (onRightEdge && onBottomEdge || onLeftEdge && onTopEdge) {
            pane.style.cursor = 'nwse-resize';
        } else if (onRightEdge && onTopEdge || onBottomEdge && onLeftEdge) {
            pane.style.cursor = 'nesw-resize';
        } else if (onRightEdge || onLeftEdge) {
            pane.style.cursor = 'ew-resize';
        } else if (onBottomEdge || onTopEdge) {
            pane.style.cursor = 'ns-resize';
        } else if (canMove()) {
            pane.style.cursor = 'move';
        } else {
            pane.style.cursor = 'default';
        }
    }

    animate();

    function onUp(e) {
        calc(e);

        if (clicked && clicked.isMoving) {
            // Snap
            var snapped = {
                width: b.width,
                height: b.height
            };

            if (b.top < FULLSCREEN_MARGINS || b.left < FULLSCREEN_MARGINS || b.right > window.innerWidth - FULLSCREEN_MARGINS || b.bottom > window.innerHeight - FULLSCREEN_MARGINS) {
                // hintFull();
                setBounds(pane, 0, 0, window.innerWidth, window.innerHeight);
                preSnapped = snapped;
            } else if (b.top < MARGINS) {
                // hintTop();
                setBounds(pane, 0, 0, window.innerWidth, window.innerHeight / 2);
                preSnapped = snapped;
            } else if (b.left < MARGINS) {
                // hintLeft();
                setBounds(pane, 0, 0, window.innerWidth / 2, window.innerHeight);
                preSnapped = snapped;
            } else if (b.right > rightScreenEdge) {
                // hintRight();
                setBounds(pane, window.innerWidth / 2, 0, window.innerWidth / 2, window.innerHeight);
                preSnapped = snapped;
            } else if (b.bottom > bottomScreenEdge) {
                // hintBottom();
                setBounds(pane, 0, window.innerHeight / 2, window.innerWidth, window.innerWidth / 2);
                preSnapped = snapped;
            } else {
                preSnapped = null;
            }

            hintHide();

        }

        clicked = null;

    }
</script>
</body>
</html>

效果展示:
起始状态
吸附效果:
吸附效果

结语

不得不说css和js用的好的话是可以实现很多好玩的功能的,只是我自己对这俩用的还没那么精通。
看到这个好玩的代码就赶紧记录下来,希望能帮助到需要的人吧。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/701977.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

青岛大学_王卓老师【数据结构与算法】Week03_07_线性表的链式表示和实现7_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c;另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础–…

【Java项目】拉取公司GitLab项目的教程

文章目录 创建Git账号登录Git 创建Git账号 进入公司后&#xff0c;会拿到公司给你注册的邮箱以及密码&#xff0c;你得到用户名和密码之后&#xff0c;需要先创建一个拉取这个仓库对应的git账号。 我们先登录GitLab 当你登录GitLab之后&#xff0c;会显示你还没有ssh key&…

基于matlab使用基本形态运算符和 blob分析的组合从视频流中提取信息(附源码)

一、前言 此示例演示如何使用基本形态运算符和 blob 分析的组合从视频流中提取信息。在本例中&#xff0c;该示例计算每个视频帧中大肠杆菌的数量。请注意&#xff0c;细胞的亮度各不相同&#xff0c;这使得分割任务更具挑战性。 形态运算符是一种图像处理中常用的操作&#…

Linux系统部署BBR服务器加速软件

1. BBR加速软件介绍 BBR简介&#xff1a;   BBR是谷歌的黑科技&#xff0c;也可以理解为用来加速网络的软件&#xff0c;如果服务器在海外&#xff0c;会发现丢包率很高&#xff0c;线路还会时断时续。所以&#xff0c;不用点黑科技&#xff0c;肯定是没办法使用。而BBR加速能…

团体程序设计天梯赛-练习集L2篇⑨

&#x1f680;欢迎来到本文&#x1f680; &#x1f349;个人简介&#xff1a;Hello大家好呀&#xff0c;我是陈童学&#xff0c;一个与你一样正在慢慢前行的普通人。 &#x1f3c0;个人主页&#xff1a;陈童学哦CSDN &#x1f4a1;所属专栏&#xff1a;PTA &#x1f381;希望各…

Redis 安装配置 常用命令

---------------------- 关系数据库与非关系型数据库 ---------------------------------------- ●关系型数据库&#xff1a; 关系型数据库是一个结构化的数据库&#xff0c;创建在关系模型&#xff08;二维表格模型&#xff09;基础上&#xff0c;一般面向于记录。 SQL 语句&…

Tomcat的安装部署

tomcat安装部署 tomcat安装部署 一、概述&#xff1a;1.tomcat介绍&#xff1a;2.tomcat核心组件&#xff1a;3.tomcat处理内部请求&#xff08;数据流向图&#xff09;4.tomcat服务部署&#xff1a; 二、虚拟主机配置&#xff1a;1.创建 chan 和 baek 项目目录和文件&#xf…

【C语言初阶(5)】循环练习题

文章目录 1. 计算 n 的阶乘2. 计算 1!2!3!……10!3. 使用二分查找法查找某数二分查找算法介绍代码实现 4. 演示字符移动5. 模拟用户登录场景 1. 计算 n 的阶乘 阶乘 某个数从 1 开始一直乘到这个数本身为止&#xff1b; 例如&#xff1a;3 的阶乘就是 1 * 2 * 3 6&#xff1b…

利用SpringBoot整合mybatis

代码地址&#xff1a;https://gitee.com/jkangle/springboot-exercise.git 1.构建SpringBoot项目 注意版本不能太高版本太高会出现问题整体的项目结构如图 2.导入Mybatis依赖 <!-- https://mvnrepository.com/artifact/org.mybatis/mybatis --><dependency>&l…

vim 对js文件和txt的操作不同

vim 对js文件和txt的操作不同 https://www.runoob.com/w3cnote/ascii.html 同样一段话&#xff0c;vim 123.txt 和 vim 123.js &#xff0c;将下面这些内容复制&#xff0c;然后粘贴&#xff0c; 显示的效果不一样 .js文件 会把 0D 0A 变换为 0A 09 import { request } from…

图像去模糊:RSBlur 数据集以及模糊图像合成方法

本内容主要介绍图像去模糊数据集 RSBlur&#xff0c;以及逼真模糊图像合成方法。 论文&#xff1a;Realistic Blur Synthesis for Learning Image Deblurring 代码&#xff08;官方&#xff09;&#xff1a;https://github.com/rimchang/RSBlur 1.1 背景 运动模糊是由曝光…

89C52RC普中单片机-4

20230629 Thusday lcd1602代码 lcd1602.c #include <REGX52.H>//引脚配置&#xff1a; sbit LCD_RSP2^6; sbit LCD_RWP2^5; sbit LCD_ENP2^7; #define LCD_DataPort P0//函数定义&#xff1a; /*** brief LCD1602延时函数&#xff0c;12MHz调用可延时1ms* param 无*…

UNet Pytorch实现

用于图像分割的不同种类的Unet模型的实现 UNet - U-Net&#xff1a; 用于生物医学图像分割的卷积网络 https://arxiv.org/abs/1505.04597RCNN-UNet - 基于U-Net的递归残差卷积神经网络&#xff08;R2U-Net&#xff09;用于医学图像分割 https://arxiv.org/abs/1802.06955Atten…

ROS学习总结(一)

渐渐开始接触项目了&#xff0c;准备把以前学习的ros做一些总结&#xff0c;以致孰能生巧。 ros分布框架学习 vscode使用ros节点和包 vscode使用 下载&#xff1a;https://code.visualstudio.com/ 安装&#xff1a;sudo dpkg -i code(tap补全) code 能快捷启动。 插件安装&am…

django.db.utils.OperationalError: no such table: onlyoffice_customuser

我写了个类 Curstomuser 重新运行命令&#xff1a; >python manage.py makemigrations就报错了&#xff1a; 我以为是自己设计的类有问题&#xff0c;结果发现是因为我在其它 py 文件中进行了数据库查询。 而 Django 架构让我忽略了代码运行的前后关系。。。 先注释掉其它…

【STM32】keil MDK-Arm 5.38 功能详解

一、基本概念二、软件安装三、软件介绍3.1 Intro3.2 keil菜单栏3.21 file选项3.22 Edit 选项3.23 View选项3.24 Project选项3.25 Flash选项3.26 Debug选项3.27 Peripherals选项3.28 Tools选项3.29 SVCS选项3.2.10 Window选项3.2.11 Help选项 3.3 keil工具栏 四、设置与项目设置…

七牛云下载文件(显示在浏览器上)

最近在做关于如何将七牛云的文件下载下来&#xff0c;且在浏览器页面展示下载文件。 首先&#xff0c;我们需要注册七牛云账号 七牛云官网。 选择个人账户即可&#xff0c;若是需要企业账户&#xff0c;则可以选择企业账户。 注册成功绑定邮箱后&#xff0c;我们可以创建存储…

NIO三大组件和ByteBuffer

目录 一、NIO三大组件 1、Channel 2、Buffer 3、Selector 二、ByteBuffer 1、基本使用 2、内部结构 3、常用方法 allocate方法 读取方法 字符串与ByteBuffer互转 Scattering Reads 4、念包、半包问题 三、文件编程 1、FileChannel 2、两个Channel传输数据 3、…

解决 pyecharts 地图不显示的问题

总结 在 pyecharts 中如果修改了 online host&#xff0c;会导致绘制的地图显示不全&#xff0c;需要将 host 改回默认的 https://assets.pyecharts.org/assets/ 细节 最近需要使用 pyecharts 绘制中国地图&#xff0c;按官网的示例代码https://github.com/pyecharts/pyecha…

LLM - ChatGLM-6B (General Language Model) 的工程配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://blog.csdn.net/caroline_wendy/article/details/131104546 Paper&#xff1a;GLM: General Language Model Pretraining with Autoregressive Blank Infilling ChatGLM是通用的预训练语…