基于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元素的鼠标按下事件,以及按下之后的移动事件和松开事件。在鼠标按下且移动过程中,可实时获得鼠标的X轴坐标的值,通过简单计算,可计算出目标元素的宽度&…...
使用MyBatis(2)
目录 一、定义接口、实体类、创建XML文件实现接口) 二、MyBatis的增删改查 🍅1、MyBatis传递参数查询 🎈写法一 🎈写法二 🎈两种方式的区别 🍅2、删除操作 🍅3、根据id修改用户名 &#x…...
【FPGA/D6】
2023年7月25日 VGA控制器 视频23notecodetb 条件编译error时序图保存与读取??RGBTFT显示屏 视频24PPI未分配的引脚或电平的解决方法 VGA控制器 视频23 note MCU单片机 VGA显示实时采集图像 行消隐/行同步/场同步/场消隐 CRT:阴极射线管 640…...
【WebGIS实例】(10)Cesium开场效果(场景、相机旋转,自定义图片底图)
效果 漫游效果视频: 【WebGIS实例】(10)Cesium开场效果(场景、相机 点击鼠标后将停止旋转并正常加载影像底图: 代码 可以直接看代码,注释写得应该比较清楚了: /** Date: 2023-07-28 16:21…...
【Spring】IOC的原理
一、 IOC 的概念 Spring 的 IOC ,即控制反转,所谓控制反转 —— 本来管理业务对象(bean)的操作是由我们程序员去做的,但是有了 Spring 核心容器后,这些 Bean 对象的创建和管理交给我们Spring容器去做了&am…...
AI加速游戏开发 亚马逊云科技适配3大场景,打造下一代游戏体验
随着疫情的消散,中国游戏产业正在快速前进。在伴随着游戏产业升级的同时,整个行业都在面临着新的挑战与新的诉求。亚马逊云科技游戏研发解决方案和服务,覆盖端到端3大场景,为游戏公司与游戏开发人员赋能。 场景1:AI辅助…...
C++ | 继承(基类,父类,超类),(派生类,子类)
文章参考:https://blog.csdn.net/war1111886/article/details/8609957 一 .继承中的访问权限关系 1.基类,父类,超类是指被继承的类,派生类,子类是指继承于基类的类. 2…...
Commands Of Hadoop
序言 持续整理下常用的命令cuiyaonan2000163.com Command 文件拷贝 当从多个源拷贝时,如果两个源冲突,distcp会停止拷贝并提示出错信息,. 如果在目的位置发生冲突,会根据选项设置解决。 默认情况会跳过已经存在的目标文件&am…...
SQL-每日一题【620.有趣的电影】
题目 某城市开了一家新的电影院,吸引了很多人过来看电影。该电影院特别注意用户体验,专门有个 LED显示板做电影推荐,上面公布着影评和相关电影描述。 作为该电影院的信息部主管,您需要编写一个 SQL查询,找出所有影片…...
linux 精华总结
...
Eureka 学习笔记2:客户端 DiscoveryClient
版本 awsVersion ‘1.11.277’ DiscoveryClient # cacheRefreshTask // 配置shouldFetchRegistry if (clientConfig.shouldFetchRegistry()) {// 配置client.refresh.intervalint registryFetchIntervalSeconds clientConfig.getRegistryFetchIntervalSeconds();// 配置expB…...
okhttp原理分析
工程目录图 请点击下面工程名称,跳转到代码的仓库页面,将工程 下载下来 Demo Code 里有详细的注释 01okhttp module里 包含的设计模式:建造者设计模式、责任链设计模式 CustomInject 演示自定义注解 代码:okhttp原理分析、Andro…...
freeswitch的mod_xml_curl模块
概述 freeswitch是一款简单好用的VOIP开源软交换平台。 随着fs服务的增多,每一台fs都需要在后台单独配置,耗时耗力,心力憔悴。 如果有一个集中管理配置的配置中心,统一管理所有fs的配置,并可以实现动态的修改配置就…...
高速数据采集专家-FMC140【产品手册】
FMC140是一款具有缓冲模拟输入的低功耗、12位、双通道(5.2GSPS/通道)、单通道10.4GSPS、射频采样ADC模块,该板卡为FMC标准,符合VITA57.1规范,该模块可以作为一个理想的IO单元耦合至FPGA前端,8通道的JESD204…...
【SSM】知识集锦
项目一:狂神JAVA 功能1:实现全部书籍查询 1.思路:首页index.jsp ——>Controller——>hello.jsp 2.步骤: step1:index.jsp <% page language"java" contentType"text/html; charsetUTF-8" page…...
Flowable-中间事件-信号中间抛出事件
定义 当流程执行到达信号抛出事件时,流程引擎会直接抛出信号,其他引用了与其相同的信号捕获 事件会被触发,信号发出后事件结束,流程沿后继路线继续执行。其抛出的信号可以被信号开始事 件(Signal Start Event…...
【算法基础:动态规划】5.3 计数类DP(整数拆分、分拆数)
文章目录 例题:900. 整数划分解法1——完全背包解法2——分拆数⭐⭐⭐ 例题:900. 整数划分 https://www.acwing.com/problem/content/902/ 解法1——完全背包 容量是 n,物品的大小和价值是 1 ~ n 中的所有数字。 import java.util.*;pub…...
封装(Encapsulation)
目录 概念 好处 数据隐藏 模块化设计 代码复用 简化接口 示例 意义 概念 封装(Encapsulation)是面向对象编程的一个核心概念,它指的是将数据和相关操作封装在一个对象中,隐藏了实现的细节。(就是实现数据封装和…...
php 原型模式
一,原型模式,就是先创建好一个原型对象,然后通过拷贝原型对象来生成新的对象。适用于大对象的创建,因为每次new一个大对象会有很大的开销,原型模式仅需内存拷贝即可。 原型模式中的主要角色: 1,…...
LiveGBS流媒体平台GB/T28181功能-支持轮巡播放分屏轮巡值守播放监控视频轮播大屏轮询播放
LiveGBS支持轮巡播放分屏轮巡值守播放监控视频轮播大屏轮询播放 1、背景2、分屏展示3、选择轮播通道4、配置轮播间隔(秒)5、点击开始轮播6、轮播停止及全屏7、搭建GB28181视频直播平台 1、背景 视频监控项目使用过程中,有时需要大屏值守,值守的时候多分…...
突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的----NTFS源代码分析--重要
根目录0xa0属性对应的Ntfs!_SCB中的FileObject是什么时候被建立的 第一部分: 0: kd> g Breakpoint 9 hit Ntfs!ReadIndexBuffer: f7173886 55 push ebp 0: kd> kc # 00 Ntfs!ReadIndexBuffer 01 Ntfs!FindFirstIndexEntry 02 Ntfs!NtfsUpda…...
Rust 开发环境搭建
环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行: rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu 2、Hello World fn main() { println…...
Golang——7、包与接口详解
包与接口详解 1、Golang包详解1.1、Golang中包的定义和介绍1.2、Golang包管理工具go mod1.3、Golang中自定义包1.4、Golang中使用第三包1.5、init函数 2、接口详解2.1、接口的定义2.2、空接口2.3、类型断言2.4、结构体值接收者和指针接收者实现接口的区别2.5、一个结构体实现多…...
在 Spring Boot 项目里,MYSQL中json类型字段使用
前言: 因为程序特殊需求导致,需要mysql数据库存储json类型数据,因此记录一下使用流程 1.java实体中新增字段 private List<User> users 2.增加mybatis-plus注解 TableField(typeHandler FastjsonTypeHandler.class) private Lis…...
LangFlow技术架构分析
🔧 LangFlow 的可视化技术栈 前端节点编辑器 底层框架:基于 (一个现代化的 React 节点绘图库) 功能: 拖拽式构建 LangGraph 状态机 实时连线定义节点依赖关系 可视化调试循环和分支逻辑 与 LangGraph 的深…...
elementUI点击浏览table所选行数据查看文档
项目场景: table按照要求特定的数据变成按钮可以点击 解决方案: <el-table-columnprop"mlname"label"名称"align"center"width"180"><template slot-scope"scope"><el-buttonv-if&qu…...
