当前位置: 首页 > news >正文

基于Vue3实现鼠标按下某个元素进行移动,实时改变左侧或右侧元素的宽度,以及点击收起或展开的功能

其原理主要是利用JavaScript中的鼠标事件来控制CSS样式。大致就是监听某个DOM元素的鼠标按下事件,以及按下之后的移动事件和松开事件。在鼠标按下且移动过程中,可实时获得鼠标的X轴坐标的值,通过简单计算,可计算出目标元素的宽度,然后再用CSS赋值就实现该效果了。

一、示例代码

<template><div class="index"><div class="index-left" ref="indexLeftRef"><div class="index-left-box"></div><div class="left-resize-bar">⋮</div></div><div class="index-middle" ref="indexRightRef"><div class="index-middle-box"><div class="left-view-more" @click="handleViewMoreLeftClick"><div class="left-view-more-false" v-if="!isExpandLeft" /><div class="left-view-more-true" v-else /></div><div class="index-middle-box_main"></div><div class="right-view-more" @click="handleViewMoreRightClick"><div class="right-view-more-false" v-if="!isExpandRight" /><div class="right-view-more-true" v-else /></div></div></div><div class="index-right" ref="indexRightRef"><div class="right-resize-bar">⋮</div><div class="index-right-box"></div></div></div>
</template><script setup>
import { onMounted, ref, getCurrentInstance } from 'vue'// 代理对象
const { proxy } = getCurrentInstance()// 左侧是否收起或展开
const isExpandLeft = ref(false)/*** 左侧点击收起或展开事件句柄方法*/
const handleViewMoreLeftClick = async () => {const indexLeftRef = await proxy.$refs.indexLeftRefisExpandLeft.value = !isExpandLeft.valueif (isExpandLeft.value) {indexLeftRef.style.width = '0'indexLeftRef.style.borderRight = '0px solid #dcdfe6'} else {indexLeftRef.style.width = '400px'indexLeftRef.style.borderRight = '1px solid #dcdfe6'}
}// 右侧是否收起或展开
const isExpandRight = ref(false)/*** 右侧点击收起或展开事件句柄方法*/
const handleViewMoreRightClick = async () => {const indexRightRef = await proxy.$refs.indexRightRefisExpandRight.value = !isExpandRight.valueif (isExpandRight.value) {indexRightRef.style.width = '0'indexRightRef.style.borderRight = '0px solid #dcdfe6'} else {indexRightRef.style.width = '400px'indexRightRef.style.borderRight = '1px solid #dcdfe6'}
}/*** 左侧拖动事件句柄方法*/
const handleDragLeftResizeBar = () => {var leftResizeBar = document.getElementsByClassName("left-resize-bar")[0]var wholeArea = document.getElementsByClassName("index")[0]var leftArea = document.getElementsByClassName("index-left")[0]var middleArea = document.getElementsByClassName("index-middle")[0]var rightArea = document.getElementsByClassName("index-right")[0]console.log('leftResizeBar =>', leftResizeBar)console.log('wholeArea =>', wholeArea)console.log('leftArea =>', leftArea)console.log('middleArea =>', middleArea)console.log('rightArea =>', rightArea)// 鼠标按下事件leftResizeBar.onmousedown = function (eventDown) {// 颜色提醒leftResizeBar.style.backgroundColor = "#5e7ce0"leftResizeBar.style.color = "#ffffff"// 鼠标移动事件document.onmousemove = function (eventMove) {let width = eventMove.clientXconsole.log('width =>', width)if (width >= 600) {width = 600 // 设置最大拉伸宽度为600} else if (width <= 0) {// 当拉伸宽度为小于或等于0,最小拉伸宽度为0,同时是否收起图标向右width = 0isExpandLeft.value = true} else {// 当拉伸宽度为大于0且小于600,是否收起图标向左isExpandLeft.value = false}leftArea.style.width = width + 'px'}// 鼠标松开事件document.onmouseup = function (evt) {// 颜色恢复leftResizeBar.style.backgroundColor = "#ffffff"leftResizeBar.style.color = "#40485c"document.onmousemove = nulldocument.onmouseup = nullleftResizeBar.releaseCapture && leftResizeBar.releaseCapture() // ReleaseCapture()函数用于释放该元素捕获的鼠标}leftResizeBar.setCapture && leftResizeBar.setCapture() // setCapture()函数用于设置该元素捕获的鼠标为空// 说明:一般情况下,SetCapture()和ReleaseCapture()函数是成对使用的。在使用SetCapture()函数捕获鼠标之后,需要在适当的时候调用ReleaseCapture()函数释放鼠标,否则可能会导致鼠标失去响应或者其他异常情况return false}
}/*** 右侧拖动事件句柄方法*/
const handleDragRightResizeBar = () => {var rightResizeBar = document.getElementsByClassName("right-resize-bar")[0]var wholeArea = document.getElementsByClassName("index")[0]var leftArea = document.getElementsByClassName("index-left")[0]var middleArea = document.getElementsByClassName("index-middle")[0]var rightArea = document.getElementsByClassName("index-right")[0]console.log('rightResizeBar =>', rightResizeBar)console.log('wholeArea =>', wholeArea)console.log('leftArea =>', leftArea)console.log('middleArea =>', middleArea)console.log('rightArea =>', rightArea)// 鼠标按下事件rightResizeBar.onmousedown = function (eventDown) {// 颜色提醒rightResizeBar.style.backgroundColor = "#5e7ce0"rightResizeBar.style.color = "#ffffff"// 鼠标移动事件document.onmousemove = function (eventMove) {let width = wholeArea.clientWidth - eventMove.clientXif (width >= 600) {width = 600 // 设置最大拉伸宽度为600} else if (width <= 0) {// 当拉伸宽度为小于或等于0,最小拉伸宽度为0,同时是否收起图标向左width = 0isExpandRight.value = true} else {// 当拉伸宽度为大于0且小于600,是否收起图标向右isExpandRight.value = false}rightArea.style.width = width + 'px'}// 鼠标松开事件document.onmouseup = function (evt) {// 颜色恢复rightResizeBar.style.backgroundColor = "#ffffff"rightResizeBar.style.color = "#40485c"document.onmousemove = nulldocument.onmouseup = nullrightResizeBar.releaseCapture && rightResizeBar.releaseCapture() // ReleaseCapture()函数用于释放该元素捕获的鼠标}rightResizeBar.setCapture && rightResizeBar.setCapture() // setCapture()函数用于设置该元素捕获的鼠标为空// 说明:一般情况下,SetCapture()和ReleaseCapture()函数是成对使用的。在使用SetCapture()函数捕获鼠标之后,需要在适当的时候调用ReleaseCapture()函数释放鼠标,否则可能会导致鼠标失去响应或者其他异常情况return false}
}onMounted(() => {handleDragLeftResizeBar()handleDragRightResizeBar()
})
</script><style lang="less" scoped>.index {display: flex;flex-direction: row;width: 100%;height: 100%;overflow: hidden;/* ---- ^ 左边 ---- */:deep(.index-left) {position: relative;z-index: 0;display: flex;flex-direction: row;width: 400px;border-right: 1px solid #dcdfe6;.index-left-box {flex: 1;display: flex;flex-direction: column;padding: 7px 0 7px 7px;overflow: hidden;background-color: #f3f6f8;.index-left-box_header {width: 100%;min-width: 400px - 14px;height: auto;.header__navbar {display: flex;width: 100%;align-items: center;font-size: 13px;text-align: center;margin-bottom: 7px;.header__navbar_panorama {flex: 1;margin-right: 5px;padding: 5px 0;border: 1px solid #dcdfe6;transition: all ease 0.3s;cursor: pointer;}.header__navbar_product {flex: 1;margin-left: 5px;padding: 5px 0;border: 1px solid #dcdfe6;transition: all ease 0.3s;cursor: pointer;}.header__navbar_panorama:hover,.header__navbar_product:hover{border: 1px solid #5e7ce0;}.header__navbar_actived {background-color: #5e7ce0;border: 1px solid #5e7ce0;color: #fff;}}.header__form {border-top: 1px solid #dcdfe6;padding-top: 7px;}}.index-left_content {flex: 1;overflow: hidden;border: 1px solid #dcdfe6;}}.left-resize-bar {display: flex;align-items: center;width: 7px;height: 100%;background-color: rgb(255, 255, 255);cursor: col-resize;user-select: none;transition: all ease 0.3s;font-size: 20px;color: #40485c;&:hover {color: #fff !important;background-color: #5e7ce0 !important;}}}/* ---- / 左边 ---- *//* ---- ^ 中间 ---- */:deep(.index-middle) {position: relative;z-index: 1;flex: 1;height: 100%;position: relative;transition: all ease 0.3s;background-color: #ffffff;.index-middle-box {display: flex;position: relative;width: 100%;height: 100%;overflow: hidden;// ^ 是否收起左侧边栏的图标.left-view-more {width: 12px;height: 30px;background-color: #ccc;border-bottom-right-radius: 4px;border-top-right-radius: 4px;position: absolute;display: block;margin: auto;left: 0;top: 0;bottom: 0;cursor: pointer;z-index: 1;transition: all ease 0.3s;&:hover {background-color: #5e7ce0;}.left-view-more-true {width: 100%;height: 10px;position: absolute;display: block;margin: auto;left: 0;right: 0;top: 0;bottom: 0;&::before {display: block;height: 2px;width: 10px;content: "";position: absolute;left: 0;top: 0;background-color: #fff;transform: rotate(70deg);}&::after {display: block;height: 2px;width: 10px;content: "";position: absolute;left: 0;bottom: 0;background-color: #fff;transform: rotate(-70deg);}}.left-view-more-false {width: 100%;height: 10px;position: absolute;display: block;margin: auto;left: 0;right: 0;top: 0;bottom: 0;&::before {display: block;height: 2px;width: 10px;content: "";position: absolute;left: 0;top: 0;background-color: #fff;transform: rotate(-70deg);}&::after {display: block;height: 2px;width: 10px;content: "";position: absolute;left: 0;bottom: 0;background-color: #fff;transform: rotate(70deg);}}}// / 是否收起左侧边栏的图标// ^ 是否收起右侧边栏的图标.right-view-more {width: 12px;height: 30px;background-color: #ccc;border-bottom-left-radius: 4px;border-top-left-radius: 4px;position: absolute;display: block;margin: auto;right: 0;top: 0;bottom: 0;cursor: pointer;z-index: 1;transition: all ease 0.3s;&:hover {background-color: #5e7ce0;}.right-view-more-true {width: 100%;height: 10px;position: absolute;display: block;margin: auto;left: 0;right: 0;top: 0;bottom: 0;&::before {display: block;height: 2px;width: 10px;content: "";position: absolute;left: 0;top: 0;background-color: #fff;transform: rotate(-70deg);}&::after {display: block;height: 2px;width: 10px;content: "";position: absolute;left: 0;bottom: 0;background-color: #fff;transform: rotate(70deg);}}.right-view-more-false {width: 100%;height: 10px;position: absolute;display: block;margin: auto;left: 0;right: 0;top: 0;bottom: 0;&::before {display: block;height: 2px;width: 10px;content: "";position: absolute;right: 0;top: 0;background-color: #fff;transform: rotate(70deg);}&::after {display: block;height: 2px;width: 10px;content: "";position: absolute;right: 0;bottom: 0;background-color: #fff;transform: rotate(-70deg);}}}// / 是否收起右侧边栏的图标}}/* ---- / 中间 ---- *//* ---- ^ 右边 ---- */:deep(.index-right) {position: relative;z-index: 0;display: flex;flex-direction: row;width: 400px;border-left: 1px solid #dcdfe6;.right-resize-bar {display: flex;align-items: center;width: 7px;height: 100%;background-color: rgb(255, 255, 255);cursor: col-resize;user-select: none;transition: all ease 0.3s;font-size: 20px;color: #40485c;&:hover {color: #fff !important;background-color: #5e7ce0 !important;}}.index-right-box {flex: 1;display: flex;flex-direction: column;padding: 7px 7px 7px 0;overflow: hidden;background-color: #f3f6f8;}}/* ---- / 右边 ---- */}
</style>

二、效果如下 ~

 

相关文章:

基于Vue3实现鼠标按下某个元素进行移动,实时改变左侧或右侧元素的宽度,以及点击收起或展开的功能

其原理主要是利用JavaScript中的鼠标事件来控制CSS样式。大致就是监听某个DOM元素的鼠标按下事件&#xff0c;以及按下之后的移动事件和松开事件。在鼠标按下且移动过程中&#xff0c;可实时获得鼠标的X轴坐标的值&#xff0c;通过简单计算&#xff0c;可计算出目标元素的宽度&…...

使用MyBatis(2)

目录 一、定义接口、实体类、创建XML文件实现接口&#xff09; 二、MyBatis的增删改查 &#x1f345;1、MyBatis传递参数查询 &#x1f388;写法一 &#x1f388;写法二 &#x1f388;两种方式的区别 &#x1f345;2、删除操作 &#x1f345;3、根据id修改用户名 &#x…...

【FPGA/D6】

2023年7月25日 VGA控制器 视频23notecodetb 条件编译error时序图保存与读取&#xff1f;&#xff1f;RGBTFT显示屏 视频24PPI未分配的引脚或电平的解决方法 VGA控制器 视频23 note MCU单片机 VGA显示实时采集图像 行消隐/行同步/场同步/场消隐 CRT&#xff1a;阴极射线管 640…...

【WebGIS实例】(10)Cesium开场效果(场景、相机旋转,自定义图片底图)

效果 漫游效果视频&#xff1a; 【WebGIS实例】&#xff08;10&#xff09;Cesium开场效果&#xff08;场景、相机 点击鼠标后将停止旋转并正常加载影像底图&#xff1a; 代码 可以直接看代码&#xff0c;注释写得应该比较清楚了&#xff1a; /** Date: 2023-07-28 16:21…...

【Spring】IOC的原理

一、 IOC 的概念 Spring 的 IOC &#xff0c;即控制反转&#xff0c;所谓控制反转 —— 本来管理业务对象&#xff08;bean&#xff09;的操作是由我们程序员去做的&#xff0c;但是有了 Spring 核心容器后&#xff0c;这些 Bean 对象的创建和管理交给我们Spring容器去做了&am…...

AI加速游戏开发 亚马逊云科技适配3大场景,打造下一代游戏体验

随着疫情的消散&#xff0c;中国游戏产业正在快速前进。在伴随着游戏产业升级的同时&#xff0c;整个行业都在面临着新的挑战与新的诉求。亚马逊云科技游戏研发解决方案和服务&#xff0c;覆盖端到端3大场景&#xff0c;为游戏公司与游戏开发人员赋能。 场景1&#xff1a;AI辅助…...

C++ | 继承(基类,父类,超类),(派生类,子类)

文章参考&#xff1a;https://blog.csdn.net/war1111886/article/details/8609957 一 .继承中的访问权限关系 &#xff11;&#xff0e;基类&#xff0c;父类&#xff0c;超类是指被继承的类&#xff0c;派生类&#xff0c;子类是指继承于基类的类&#xff0e; &#xff12;…...

Commands Of Hadoop

序言 持续整理下常用的命令cuiyaonan2000163.com Command 文件拷贝 当从多个源拷贝时&#xff0c;如果两个源冲突&#xff0c;distcp会停止拷贝并提示出错信息&#xff0c;. 如果在目的位置发生冲突&#xff0c;会根据选项设置解决。 默认情况会跳过已经存在的目标文件&am…...

SQL-每日一题【620.有趣的电影】

题目 某城市开了一家新的电影院&#xff0c;吸引了很多人过来看电影。该电影院特别注意用户体验&#xff0c;专门有个 LED显示板做电影推荐&#xff0c;上面公布着影评和相关电影描述。 作为该电影院的信息部主管&#xff0c;您需要编写一个 SQL查询&#xff0c;找出所有影片…...

linux 精华总结

...

Eureka 学习笔记2:客户端 DiscoveryClient

版本 awsVersion ‘1.11.277’ DiscoveryClient # cacheRefreshTask // 配置shouldFetchRegistry if (clientConfig.shouldFetchRegistry()) {// 配置client.refresh.intervalint registryFetchIntervalSeconds clientConfig.getRegistryFetchIntervalSeconds();// 配置expB…...

okhttp原理分析

工程目录图 请点击下面工程名称&#xff0c;跳转到代码的仓库页面&#xff0c;将工程 下载下来 Demo Code 里有详细的注释 01okhttp module里 包含的设计模式&#xff1a;建造者设计模式、责任链设计模式 CustomInject 演示自定义注解 代码&#xff1a;okhttp原理分析、Andro…...

freeswitch的mod_xml_curl模块

概述 freeswitch是一款简单好用的VOIP开源软交换平台。 随着fs服务的增多&#xff0c;每一台fs都需要在后台单独配置&#xff0c;耗时耗力&#xff0c;心力憔悴。 如果有一个集中管理配置的配置中心&#xff0c;统一管理所有fs的配置&#xff0c;并可以实现动态的修改配置就…...

高速数据采集专家-FMC140【产品手册】

FMC140是一款具有缓冲模拟输入的低功耗、12位、双通道&#xff08;5.2GSPS/通道&#xff09;、单通道10.4GSPS、射频采样ADC模块&#xff0c;该板卡为FMC标准&#xff0c;符合VITA57.1规范&#xff0c;该模块可以作为一个理想的IO单元耦合至FPGA前端&#xff0c;8通道的JESD204…...

【SSM】知识集锦

项目一&#xff1a;狂神JAVA 功能1&#xff1a;实现全部书籍查询 1.思路&#xff1a;首页index.jsp ——>Controller——>hello.jsp 2.步骤&#xff1a; step1:index.jsp <% page language"java" contentType"text/html; charsetUTF-8" page…...

Flowable-中间事件-信号中间抛出事件

定义 当流程执行到达信号抛出事件时&#xff0c;流程引擎会直接抛出信号&#xff0c;其他引用了与其相同的信号捕获 事件会被触发&#xff0c;信号发出后事件结束&#xff0c;流程沿后继路线继续执行。其抛出的信号可以被信号开始事 件&#xff08;Signal Start Event&#xf…...

【算法基础:动态规划】5.3 计数类DP(整数拆分、分拆数)

文章目录 例题&#xff1a;900. 整数划分解法1——完全背包解法2——分拆数⭐⭐⭐ 例题&#xff1a;900. 整数划分 https://www.acwing.com/problem/content/902/ 解法1——完全背包 容量是 n&#xff0c;物品的大小和价值是 1 ~ n 中的所有数字。 import java.util.*;pub…...

封装(Encapsulation)

目录 概念 好处 数据隐藏 模块化设计 代码复用 简化接口 示例 意义 概念 封装&#xff08;Encapsulation&#xff09;是面向对象编程的一个核心概念&#xff0c;它指的是将数据和相关操作封装在一个对象中&#xff0c;隐藏了实现的细节。&#xff08;就是实现数据封装和…...

php 原型模式

一&#xff0c;原型模式&#xff0c;就是先创建好一个原型对象&#xff0c;然后通过拷贝原型对象来生成新的对象。适用于大对象的创建&#xff0c;因为每次new一个大对象会有很大的开销&#xff0c;原型模式仅需内存拷贝即可。 原型模式中的主要角色&#xff1a; 1&#xff0c;…...

LiveGBS流媒体平台GB/T28181功能-支持轮巡播放分屏轮巡值守播放监控视频轮播大屏轮询播放

LiveGBS支持轮巡播放分屏轮巡值守播放监控视频轮播大屏轮询播放 1、背景2、分屏展示3、选择轮播通道4、配置轮播间隔(秒)5、点击开始轮播6、轮播停止及全屏7、搭建GB28181视频直播平台 1、背景 视频监控项目使用过程中&#xff0c;有时需要大屏值守&#xff0c;值守的时候多分…...

【Python】 -- 趣味代码 - 小恐龙游戏

文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

docker 部署发现spring.profiles.active 问题

报错&#xff1a; org.springframework.boot.context.config.InvalidConfigDataPropertyException: Property spring.profiles.active imported from location class path resource [application-test.yml] is invalid in a profile specific resource [origin: class path re…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

解读《网络安全法》最新修订,把握网络安全新趋势

《网络安全法》自2017年施行以来&#xff0c;在维护网络空间安全方面发挥了重要作用。但随着网络环境的日益复杂&#xff0c;网络攻击、数据泄露等事件频发&#xff0c;现行法律已难以完全适应新的风险挑战。 2025年3月28日&#xff0c;国家网信办会同相关部门起草了《网络安全…...

C++ 类基础:封装、继承、多态与多线程模板实现

前言 C 是一门强大的面向对象编程语言&#xff0c;而类&#xff08;Class&#xff09;作为其核心特性之一&#xff0c;是理解和使用 C 的关键。本文将深入探讨 C 类的基本特性&#xff0c;包括封装、继承和多态&#xff0c;同时讨论类中的权限控制&#xff0c;并展示如何使用类…...

EC2安装WebRTC sdk-c环境、构建、编译

1、登录新的ec2实例&#xff0c;证书可以跟之前的实例用一个&#xff1a; ssh -v -i ~/Documents/cert/qa.pem ec2-user70.xxx.165.xxx 2、按照sdk-c demo中readme的描述开始安装环境&#xff1a; https://github.com/awslabs/amazon-kinesis-video-streams-webrtc-sdk-c 2…...