突破编程_前端_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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Ant Design Vue中的table与pagination的联合使用

效果&#xff1a; 代码&#xff1a; <a-table:dataSource"dataSource":columns"columns":pagination"pagination"change"handleTableChange":scroll"{ x: 100%, y: 600 }"> </a-table> export default defin…

零基础入门实战深度学习Pytorch课程下载

本课程旨在帮助零基础学员掌握PyTorch深度学习框架。通过实战项目&#xff0c;学员将学习神经网络基础、模型训练和调优技巧。逐步掌握深度学习核心概念&#xff0c;为未来在人工智能领域打下坚实基础。 课程大小:2.6G 课程下载&#xff1a;https://download.csdn.net/downlo…

网络安全 | 什么是云安全?

关注WX&#xff1a;CodingTechWork 云安全-介绍 云安全是为了解决企业安全所面临的外部和内部威胁&#xff0c;它是一组程序和技术的集合。企业在实施其数字化转型策略&#xff0c;并将各种云端工具和服务纳入企业基础架构中时&#xff0c;需要云安全保障业务顺利进行。 云计…

CentOS7.9排查网络带宽高占用的情况

//显示全部网卡 ifconfig //安装iftop yum install iftop -y //设定监测的网卡 iftop -i eth0 按 P 显示 host 信息及端口信息。 按 D 切换是否显示远端目标主机的端口信息。

15 - grace序列处理 - 十三点滑动平均法

grace序列处理 -十三点滑动平均法 滑动平均是一种常用的平滑数据的方法,可以用于去除噪声或者提取趋势。十三点滑动平均是指使用窗口大小为13的滑动平均,应用于GRACE序列处理中可以去除周年项的影响。 十三点滑动平均的计算公式为: y [ n ] = ( x [ n − 6 ]

C++ | Leetcode C++题解之第6题Z字形变换

题目&#xff1a; 题解&#xff1a; class Solution { public:string convert(string s, int numRows) {int n s.length(), r numRows;if (r 1 || r > n) {return s;}string ans;int t r * 2 - 2;for (int i 0; i < r; i) { // 枚举矩阵的行for (int j 0; j i &l…

ARM64架构栈帧以及帧指针FP

文章目录 前言一、arm64架构寄存器简介1.1 异常等级1.2 通用寄存器1.3 ARM64架构ABI 二、ARM64架构函数调用标准2.1 AArch64过程调用标准简介2.2 通用寄存器中的参数 三、demo分析3.1 main函数3.2 funb3.3 funa 四、栈帧总结五、demo演示参考资料 前言 这篇文章描述了 x86_64架…

Linux之实现Apache服务器监控、数据库定时备份及通过使用Shell脚本发送邮件

目录 一、Apache服务器监控 为什么要用到服务监控&#xff1f; 实现Apache服务器监控 二、数据库备份 为什么要用到数据库备份&#xff1f; 实现数据库备份 三、Shell脚本发送邮件 为什么要用使用Shell脚本发送邮件&#xff1f; 实现Shell脚本发送邮件 一、Apache服务器…

Mysql故障解析

目录 一、Mysql单实例故障排查 1.故障一 2.故障二 3.故障三 4.故障四 5.故障五 6.故障六 7.故障七 8.故障八 二、Mysql主从故障排查 1.故障一 2.故障二 3.故障三 三、Mysql优化 1.硬件方面 &#xff08;1&#xff09;关于CPU &#xff08;2&#xff09;关于内…

【技巧】如何解除Excel“打开密码”?

给Excel表格设置“打开密码”&#xff0c;可以保护表格不被他人随意打开&#xff0c;那如果后续不需要保护了&#xff0c;不想每次打开Excel都需要输密码&#xff0c;要怎么去除“打开密码”呢&#xff1f; 今天分享3个方法&#xff0c;最后一个方法记得收藏起来&#xff0c;以…

GWO-CNN-BiLSTM多输入时序预测|灰狼群算法优化的卷积-双向长短期神经网络|Matlab

目录 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 亮点与优势&#xff1a; 二、实际运行效果&#xff1a; 三、算法介绍&#xff1a; 四、完整程序下载&#xff1a; 一、程序及算法内容介绍&#xff1a; 基本内容&#xff1a; 本代码基于Matlab平台编译&…

ssm013小型企业办公自动化系统的设计和开发+vue

小型企业办公自动化系统的设计与实现 摘 要 互联网发展至今&#xff0c;无论是其理论还是技术都已经成熟&#xff0c;而且它广泛参与在社会中的方方面面。它让信息都可以通过网络传播&#xff0c;搭配信息管理工具可以很好地为人们提供服务。针对小型企业办公信息管理混乱&am…

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

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

GS1-全球分类标准

GS1 GS1是一个中立的全球合作平台&#xff0c;汇集行业领袖、政府、监管机构、学术界和协会&#xff0c;共同开发基于标准的解决方案&#xff0c;以应对数据交换的挑战。我们的规模和影响力——遍布 116 个国家/地区的当地会员组织、超过 200 万家用户公司和每天 100 亿笔交易—…

量化交易入门(三十八)CCI指标Python实现和回测

今天我们先单纯用CCI指标来完成策略的编写&#xff0c;后续我们会改进这个策略&#xff0c;将CCI指标和前面讲到的MACD和RSI相结合来优化&#xff0c;看看我们优化后的效果会不会更好。 一、量化策略 CCI指标在量化交易中的策略&#xff1a; 在以下情况下生成买入信号&#…

easy connect 连接不上网络,本地环境出现异常

环境&#xff1a; Win7 专业版 easy connect 问题描述&#xff1a; easy connect 连接不上网络&#xff0c;本地环境出现异常 解决方案&#xff1a; 1.打开IE的lnternet选项–高级 看看是否勾选了SSL 3.0 TLS1.0&#xff0c;取消&#xff08;未解决&#xff09; 2.请先关…

【工具-MATLAB】

MATLAB ■ MATLAB-简介■ MATLAB-应用领域■ MATLAB■ MATLAB■ MATLAB■ MATLAB ■ MATLAB-简介 MATLAB是matrix&laboratory两个词的组合&#xff0c;意为矩阵工厂&#xff08;矩阵实验室&#xff09; 美国MathWorks公司出品的商业数学软件, MATLAB和Mathematica、Maple并…

基于ssm汽车养护管理系统论文

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本汽车养护管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大的数据信息…

深度学习算法模型部署

绝大数情况&#xff0c;我们使用网上公开数据集&#xff0c;跑通一个深度学习算法模型&#xff0c;获得了较高的准确率&#xff0c;这样仅停留在仿真阶段&#xff0c;并未考虑算法实际的部署。以下将以故障诊断为例&#xff0c;将深度学习算法模型部署到Android系统&#xff0c…

SwiftUI Swift 显示隐藏系统顶部状态栏

Show me the code // // TestHideSystemTopBar.swift // pandabill // // Created by 朱洪苇 on 2024/4/1. //import SwiftUIstruct TestHideSystemTopBar: View {State private var isStatusBarHidden falsevar body: some View {Button {withAnimation {self.isStatusBa…