突破编程_前端_JS编程实例(分割窗体组件)

1 开发目标

分隔窗体组件旨在提供灵活的窗体分隔功能,支持横向分割与纵向分隔两种类型,并具备拖拽调整窗体比例的功能,同时提供最小比例设置,以防止窗体被过度缩小:

在这里插入图片描述

2 详细需求

2.1 分隔窗体类型

(1)横向分割:

  • 用户可以在窗体顶部或底部添加一个横向分割条,将窗体分割成上下两部分。
  • 分割条的位置可以通过拖拽调整,以改变上下两部分窗体的高度比例。

(2)纵向分隔:

  • 用户可以在窗体左侧或右侧添加一个纵向分割条,将窗体分割成左右两部分。
  • 分割条的位置同样可以通过拖拽调整,以改变左右两部分窗体的宽度比例。

2.2 鼠标样式切换

(1)鼠标靠近状态:

  • 当鼠标指针移动到分割条附近的一定范围内时,分割条应自动变为拖拽样式。
  • 拖拽样式可以通过视觉上的变化来体现,例如改变分割条的颜色、形状或添加拖拽图标等。

(2)鼠标远离状态:

  • 当鼠标指针离开分割条附近的范围时,分割条应自动恢复到默认样式。
  • 默认样式应简洁明了,以便在不需要拖拽调整时保持窗体的整体美观性。

2.3 拖拽调整窗体比例

(1)拖拽过程:

  • 用户点击并拖动拖拽样式的分割条时,应能够实时改变窗体的比例。
  • 拖拽过程中,应提供平滑的过渡效果,确保窗体布局的调整连贯且自然。

(2)横向分割调整:

  • 在横向分割模式下,拖动分割条将改变上下两部分窗体的高度比例。
  • 用户可以通过向上或向下拖动分割条来调整上下窗体的相对大小。

(3)纵向分隔调整:

  • 在纵向分隔模式下,拖动分割条将改变左右两部分窗体的宽度比例。
  • 用户可以通过向左或向右拖动分割条来调整左右窗体的相对大小。

2.4 最小比例设置

(1)设置功能:

  • 组件应提供设置最小比例的功能,允许用户自定义窗体在分割调整时的最小比例限制。
  • 用户可以通过配置项或API接口来设置最小比例值。

(2)横向分割调整:

  • 当用户尝试通过拖拽将窗体调整到小于最小比例时,应阻止进一步的调整操作。
  • 此时,可以通过视觉反馈(如提示信息、分割条位置固定等)来告知用户已达到最小比例限制。

3 代码实现

首先创建一个 neat_spliterwidget.js 文件,该文件用于本组件的工具类、目录处理函数的代码构建。

(1)创建分隔窗体的基类:

首先,定义核心数据变量:

class NeatSpliterWidget {constructor(container,para) {this.container = container;this.para = para;this.wid1 = null;this.wid2 = null;this.spliterRatio = para.spliterRatio ?? 0.3;this.minSpace = 20;this.spliterSpace = 3;              // 切换鼠标样式的间距this.dragReadyFalg = false;this.dragActiveFlag = true;this.dragFalg = false;this.dragStart = 0;this.render();}

接下来,进行基础类型的渲染,包括创建子窗体:

	render() {this.container.style.display = 'flex';this.wid1Tmp = document.createElement('div');this.wid2Tmp = document.createElement('div');this.widSpliter = document.createElement('div');this.wid1 = document.createElement('div');this.wid1.style.width = '100%';this.wid1.style.height = '100%';this.wid1Tmp.appendChild(this.wid1);this.wid2 = document.createElement('div');this.wid2.style.width = '100%';this.wid2.style.height = '100%';this.wid2Tmp.appendChild(this.wid2);}

最后,定义鼠标事件,计算拖拽时的初始位置:

	initSpliterEvent() {let that = this;if (!that.dragActiveFlag) {return;}this.container.addEventListener("mousedown", function (event) {if (!that.dragActiveFlag) {return;}if('column' == that.container.style.flexDirection){that.dragStart = event.clientY - event.currentTarget.offsetTop;}else{that.dragStart = event.clientX - event.currentTarget.offsetLeft;}if (that.dragReadyFalg) {that.dragFalg = true;this.onselectstart = function () { return false; };} else {that.dragFalg = false;this.onselectstart = function () { return true; };}});this.container.addEventListener("mouseup", function (event) {if (!that.dragActiveFlag) {return;}if('column' == that.container.style.flexDirection){that.dragStart = event.clientY - event.currentTarget.offsetTop;}else{that.dragStart = event.clientX - event.currentTarget.offsetLeft;}that.dragFalg = false;this.onselectstart = function () { return true; };});}
}

(2)接下来,开始定义纵向分割窗体的组件(支持水平拖拽):

class NeaterHSpliterWidget extends NeatSpliterWidget {constructor(container,para) {super(container,para);}render() {super.render();this.wid1Tmp.style.width = (this.spliterRatio * 100).toString() + '%';this.wid1Tmp.style.height = '100%';this.wid2Tmp.style.width = '10px';this.wid2Tmp.style.height = '100%';this.wid2Tmp.style.flex = 1;this.widSpliter.style.height = '100%';this.widSpliter.style.width = '1px';this.widSpliter.style.borderLeft = '1px solid #CACDD1';this.container.appendChild(this.wid1Tmp);this.container.appendChild(this.widSpliter);this.container.appendChild(this.wid2Tmp);this.initSpliterEvent();}

上面代码定义了 NeaterHSpliterWidget 的渲染方式,主要是将子窗体以及分割条做水平布局,接下来是处理水平拖拽事件:

	initSpliterEvent() {super.initSpliterEvent();let that = this;if (!that.dragActiveFlag) {return;}this.container.addEventListener("mousemove", function (event) {let clientX = event.clientX - event.currentTarget.offsetLeft;if (that.dragFalg) {let dragOffset = clientX - that.dragStart;let spliterWidth1 = that.wid1Tmp.offsetWidth + dragOffset;if (spliterWidth1 < that.minSpace || (that.container.offsetWidth - spliterWidth1) < that.minSpace) {return;}that.spliterRatio = spliterWidth1 / that.container.offsetWidth;that.wid1Tmp.style.width = spliterWidth1 + 'px';that.dragStart = clientX;} else {if (clientX > that.wid1Tmp.offsetWidth - that.spliterSpace && clientX < that.wid1Tmp.offsetWidth + that.spliterSpace + 1) {that.container.style.cursor = "col-resize";that.dragReadyFalg = true;} else {that.container.style.cursor = "default";that.dragReadyFalg = false;}}});}
}

上面代码的核心逻辑是计算更换鼠标样式的位置以及计算拖拽时分隔比例的变化。

(3)然后,定义横向分割窗体的组件(支持垂直拖拽):

class NeaterVSpliterWidget extends NeatSpliterWidget {constructor(container,para) {super(container,para);}render() {super.render();this.container.style.flexDirection = 'column';this.wid1Tmp.style.height = (this.spliterRatio * 100).toString() + '%';this.wid1Tmp.style.width = '100%';this.wid2Tmp.style.height = '10px';this.wid2Tmp.style.width = '100%';this.wid2Tmp.style.flex = 1;this.widSpliter.style.width = '100%';this.widSpliter.style.borderBottom = '1px solid #CACDD1';this.container.appendChild(this.wid1Tmp);this.container.appendChild(this.widSpliter);this.container.appendChild(this.wid2Tmp);this.initSpliterEvent();}

上面代码定义了 NeaterVSpliterWidget 的渲染方式,主要是将子窗体以及分割条做垂直布局,接下来是处理垂直拖拽事件:

	initSpliterEvent() {super.initSpliterEvent();let that = this;if (!that.dragActiveFlag) {return;}this.container.addEventListener("mousemove", function (event) {let clientY = event.clientY - event.currentTarget.offsetTop;if (that.dragFalg) {let dragOffset = clientY - that.dragStart;let spliterHeight1 = that.wid1Tmp.offsetHeight + dragOffset;if (spliterHeight1 < that.minSpace || (that.container.offsetHeight - spliterHeight1) < that.minSpace) {return;}that.spliterRatio = spliterHeight1 / that.container.offsetHeight;that.wid1Tmp.style.height = spliterHeight1 + 'px';that.dragStart = clientY;} else {if (clientY > that.wid1Tmp.offsetHeight - that.spliterSpace && clientY < that.wid1Tmp.offsetHeight + that.spliterSpace + 1) {that.container.style.cursor = "row-resize";that.dragReadyFalg = true;} else {that.container.style.cursor = "default";that.dragReadyFalg = false;}}});}
}

上面代码的核心逻辑是计算更换鼠标样式的位置以及计算拖拽时分隔比例的变化。

至此,整个分割窗体组件构建结束。

(4)完成目录导航功能的组件的代码编写后,可以创建 neat_spliterwidget.html 文件,调用该组件:

<!DOCTYPE html>
<html><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta http-equiv="X-UA-Compatible" content="ie=edge" /><title>spliter widget</title><style>html {height: 100%;}body {margin: 0;height: 100%;}</style>
</head><body><div id="divMain" style="height: 400px;width: 600px;margin: 20px;border: 1px solid #aaa;"></div>
</body>
<script src="./neat_spliterwidget.js"></script>
<script>let para = {spliterRatio:0.3,}let hSpliterWidget = new NeaterHSpliterWidget(document.getElementById('divMain'), para);para.spliterRatio = 0.7;let vSpliterWidget = new NeaterVSpliterWidget(hSpliterWidget.wid2, para);</script></html>

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

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

相关文章

经纬恒润AUTOSAR产品成功适配芯来RISC-V车规内核

近日&#xff0c;经纬恒润AUTOSAR基础软件产品INTEWORK-EAS&#xff08;ECU AUTOSAR Software&#xff0c;以下简称EAS&#xff09;在芯来提供的HP060开发板上成功适配芯来科技的RISC-V处理器NA内核&#xff0c;双方携手打造了具备灵活、可靠、高性能、强安全性的解决方案。这极…

护眼台灯哪个牌子好?护眼台灯品牌排行前十名推荐

台灯可以说家家必备的一盏灯具&#xff0c;如果家长有正在上学的孩子的更需要一款好的台灯&#xff0c;因为不管是看书、写字、阅读都离不开台灯的帮助&#xff0c;而且一款好的台灯不仅仅能够提供明亮充足的照明环境&#xff0c;而且还能起到保护视力健康&#xff0c;预防近视…

【解决方案】荣耀系统Android8.0 system目录Read-only file system

本来以为直接把Charles证书改成系统证书格式&#xff0c;然后通过mt管理器root之后移动到系统证书目录就行了&#xff0c;结果访问baidu仍然显示网络错误&#xff0c;折腾一晚上。安装为用户证书&#xff0c;又与系统证书冲突。 手机型号&#xff1a;荣耀v10 EMUI&#xff1a…

【Apple Vision Pro 应用】一款专为Vision Pro设计的三维空间无尽跑酷游戏

跑酷类游戏基本上是手机时代的大爆款&#xff08;充分利用手机的交互优势&#xff09;&#xff0c;代表神庙逃亡、地铁跑酷等&#xff0c;在VP眼镜端&#xff0c;还能玩出什么花样来&#xff0c;我知道我身边有一个创业者在做&#xff0c;目前还没上线&#xff0c;分享一家国外…

vite + vue项目报错:Uncaught ReferenceError: globalThis is not defined

vite vue项目报错&#xff1a;Uncaught ReferenceError: globalThis is not defined。 原因是&#xff0c;谷歌浏览器版本太低&#xff0c;引用的第三方库不支持导致。 解决方法&#xff1a;在index.html中添加 <script>this.globalThis || (this.globalThis this) &…

需要本地后端的真机调试-微信

打开和修改IP改为电脑与手机同一局域网的 不知道这个要不要

Spring Boot项目启动速度优化

1、配置自动配置排除列表&#xff0c;减少启动自动配置扫描&#xff0c;配置项spring.autoconfigure.exclude 2、启动类添加索引注解Indexed&#xff0c;去除启动过程中 Components 的扫描步骤&#xff0c;直接从索引文件读取。 import org.springframework.stereotype.lndexe…

AIGC浪潮下,鹅厂新一代前端人的真实工作感受

AIGC 这一时代潮流已然不可阻挡&#xff0c;我们要做的不是慌乱&#xff0c;而是把握住这个时代的机会。本文就和大家一起来探索在 AIGC 下&#xff0c;前端工程师即将面临的挑战和机遇。聊聊从以前到现在&#xff0c;AIGC 给我们带来了怎么样的变化&#xff0c;下一代前端工程…

【详细教程制作】用户列表

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;开发者-曼亿点 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 曼亿点 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a…

电脑分辨率怎么调,电脑分辨率怎么调整

随着电脑的普及以及网络的发展&#xff0c;我们现在在工作中都离不开对电脑的使用&#xff0c;今天小编教大家设置电脑分辨率&#xff0c;现在我们先了解这个分辨率是什么?通常电脑的显示分辨率就是屏幕分辨率&#xff0c;显示屏大小固定时&#xff0c;显示分辨率越高图像越清…

一个问题串联 Java 的几个基础知识

前言 关于 “” 和 equals() 的区别这个问题&#xff0c;我之前一直搞的很乱&#xff0c;虽然面试的时候一直没有被问到&#xff0c;但是我感觉这种是属于最基础的知识&#xff0c;如果不懂好像不是很好。后来我发现通过这个问题&#xff0c;可以串联起很多的知识点&#xff0…

正则表达式浅析

正则表达式&#xff0c;又称正规表示法、常规表示法&#xff08;英语&#xff1a;Regular Expression&#xff0c;在代码中常简写为regex、regexp或RE&#xff09;&#xff0c;计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很…

Linux多进程通信(3)——详细说说共享内存原理及使用例程

1.共享内存原理及优缺点 共享内存的原理便是将相同的一片物理内存映射到进程A和进程B不同的逻辑地址空间&#xff0c;两个进程同时访问这块物理内存&#xff08;共享内存&#xff09;。 1&#xff09;优点 共享内存是进程间通信访问速度最快。 例如消息队列&#xff0c;FIFO&…

Google Chrome将某个页签静音,不是网站

Google Chrome将某个页签静音&#xff0c;不是网站 打开chrome://flags/在里面搜索&#xff0c;audio&#xff0c;找到Tab audio muting UI contorl的选项&#xff0c;右侧设置为Enable。重新启动浏览器。 发现有声音的浏览器页签有一个喇叭图标&#xff0c;点击一下就行了。

Linux中间件(nginx搭建、LNMP服务搭建)

目录 一、安装nginx 第一步、下载nginx的压缩包到Linux中 ​第二步、安装依赖 第三步&#xff1a;安装 nginx 第四步&#xff1a;启动nginx 第五步&#xff1a;测试nginx 二、 nginx的配置文件 nginx.conf文件内容解读 案例&#xff1a;发布多个网站 二、lamp/lnmp …

一文入门Ubuntu22

目录 1.安装Ubuntu22 2.常用目录 3.常用指令 1.sudo 超级用户权限运行命令 2.ls 罗列当前文件信息 3.文件目录相关&#xff1a; 1.cd改变工作路径&#xff1a; 2.pwd 3.创建目录和文件&#xff1a; 4.which 5.ps 6.kill 7.ping 4.用户相关 5.ssh与scp 6.服务相关…

数字孪生|山海鲸数据管家简介及安装步骤

哈喽&#xff0c;大家好啊&#xff0c;我是雷工&#xff01; 最近在学习数字孪生相关的软件山海鲸&#xff0c;了解到采集Modbus协议需要先安装山海鲸数据管家&#xff0c;本节先学习数据管家及安装步骤&#xff0c;以下为学习笔记&#xff1a; 1、简介 数据管家是帮用户进行…

vue+nodejs+小区物业报修系统2e1fq

在对平台的各个功能模块建成整合后&#xff0c;使系统能够正常的运行&#xff0c;让用户能够通过使用本系统进行物业管理。 &#xff08;1&#xff09;前台业主端预期结果&#xff1a;业主能够查看物业相关公告信息&#xff0c;能够查看自己的缴费信息以及能够报修和投诉。 &am…

Android Studio调试中的坑

1、新建Android工程后编译发现报错 2、发现无33和34的SDK更新 3、查看google相关文档 Android Gradle 插件 8.3 版本说明 | Android Studio | Android Developers 如果需要支持相关更高SDK需要的Android Studio版本和Android Gradle 插件是有版本要求的&#xff0c;相关要…

Vision-Language Models for Vision Tasks: A Survey

论文地址&#xff1a;https://arxiv.org/pdf/2304.00685.pdf 项目地址&#xff1a;https://github.com/jingyi0000/VLM_survey 一、综述动机 视觉语言模型&#xff0c;如CLIP&#xff0c;以其独特的训练方式显著简化了视觉识别任务的流程。它减少了对大量精细标注数据的依赖&a…