【vue】编辑器段落对应材料同步滚动交互

news/2024/9/18 12:38:05/ 标签: vue.js, 编辑器, 交互

场景需求

实现方法

  1. 编辑器与材料组件左右布局
  2. 获取编辑器高度,材料高度与编辑器高度一致
  3. 禁用材料组件的滚动事件
  4. 获取编辑器段落距离顶部的位置,对应材料的顶部高度与段落一致
  5. 监听编辑器滚动高度,对应材料组件同步滚动
  6. 当段落为空时,材料不显示
  7. 当段落比材料短的时候,对应材料进行下移,避免材料重叠

html代码

// 编辑器中段落代码
<div class="ws-container"><div class="ws-result" data-set="第一段" data-set-code="dyd" :style="[normal]"><div :style="[indentbase]">这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段这是第一段</div></div><div class="ws-result" data-set="第二段" data-set-code="ded" :style="[normal]"><div :style="[indentbase]" >这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段这是第二段</div></div><div class="ws-result" data-set="第三段" data-set-code="dsd" :style="[normal]"><div :style="[indentbase]">这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段这是第三段</div></div>
</div>// 对应段落材料代码
<div class="doc-source" @touchmove.prevent @mousewheel.prevent><div ref="sourceMode"><div class="source-mode" :ref="index" v-for="(item, index) in list" :key="index"><div class="source-mode-item" v-for="(item1, index1) in item" :key="index1" :title="item1.name"><div class="flag"></div><div class="file">来源:{{ item1.name}}</div></div></div></div>
</div>

JS代码

export const SOURCEMODE = [{ name: '第一段', code: 'dyd' },{ name: '第二段', code: 'ded' },{ name: '第三段', code: 'dsd' },
];
// 编辑器更新时
contentChange() {const dom = this.editor.document.querySelectorAll('.ws-result');SOURCEMODE.forEach(item => {let flag = false;for (let i = 0; i < dom.length; i++) {// 有情节且对应dom有高度则表示有内容if (item.name === dom[i].getAttribute('data-set') && dom[i].scrollHeight > 0) flag = true;}this.$emit('updateSourceFile', item.code, flag);});
}
// 编辑器删除段落时,更新材料状态
updateSourceFile(type, flag) {if (!flag && this.sourceModeFile[type]) delete this.sourceModeFile[type];const sourceKeys = Object.keys(this.sourceModeFile);const dom = this.$refs.editor.editor.document.querySelectorAll('.ws-result');for (let i = 0; i < dom.length; i++) {const dataSet = dom[i].getAttribute('data-set');const index = SOURCEMODE.findIndex(sourceItem => sourceItem.name === dataSet);if (index > -1) {dom[i].style.color = 'rgb(24, 144, 255)';if (this.$refs[dom[i].getAttribute('data-set-code')]) {let currentOffsetTop = dom[i].offsetTop + 26;// 当段落比证据短的时候,整体证据进行下移// 思路:1. 判断当前dom对应的证据是否有上一个 sourceKeysIndex - 1 > -1// 2.拿到上一个距离顶部的高度,拿到当前距离顶部的高度,currentOffsetTop - prevOffsetTop// 3.相减后的数字小于上一个的高度prevHeight,说明会重叠,用prevHeight - gap得到重叠高度// 4.将重叠高度加上dom距离顶部的高度给当前证据// 5.特殊情况,相减后大于上一个高度时,并且差距小于20,则加上26进行情节区分const sourceKeysIndex = sourceKeys.findIndex(source => source === dom[i].getAttribute('data-set-code'));if (sourceKeysIndex - 1 > -1) {const prevOffsetTop = this.$refs[sourceKeys[sourceKeysIndex - 1]][0].offsetTop;const prevHeight = this.$refs[sourceKeys[sourceKeysIndex - 1]][0].clientHeight;const gap = currentOffsetTop - prevOffsetTop;if (gap < prevHeight) {currentOffsetTop = currentOffsetTop + (prevHeight - gap) + 26;} else {if (gap - prevHeight < 20) {currentOffsetTop = currentOffsetTop + 26;}}}this.$refs[dom[i].getAttribute('data-set-code')][0].style.top = `${currentOffsetTop}px`;}}}const containerDom = this.$refs.editor.editor.document.querySelector('.ws-container');if (containerDom) this.$refs.sourceMode.style.height = `${containerDom.scrollHeight}px`;// 解决当编辑器不触发滚动时,手动让证据滚动到编辑器滚动位置const scrollTop = this.$refs.sourceMode.parentElement.scrollTop;if (containerDom && scrollTop !== containerDom.scrollTop) {this.editorScroll(containerDom.scrollTop);}// 编辑器滚动时,材料同步滚动this.$refs.editor.openEditorScroll();
},
// 编辑器滚动高度,同步右侧材料滚动
editorScroll(scrollTop) {this.$refs.sourceMode.parentElement.scrollTo(0, scrollTop);
},

材料列表数据

"list": {"dyd": [{ "name": "第一段材料1" },{ "name": "第一段材料2" },{ "name": "第一段材料3" }],"ded": [{ "name": "第二段材料1" },{ "name": "第二段材料2" },{ "name": "第二段材料3" }],"dsd": [{ "name": "第三段材料1" },{ "name": "第三段材料2" },{ "name": "第三段材料3" },{ "name": "第三段材料4" }]
}

效果图
在这里插入图片描述
总结:

  1. 最开始为了减少监听带来的影响,只针对当前操作的段落进行处理,但是后面发现,当操作上一段,下一段有材料时,材料的定位不准确,于是改成了只要段落变化,全部的材料位置计算一次
  2. 在当段落高度少于右侧来源高度时,思考了很久,最开始想的是用相邻段落的高度设置给材料,但是因为不是每个段落都有材料,不一定会准确,加上段落组件层级太深,组件之前取值不好维护,因此放弃了这种方式,选择用相邻材料的高度差值处理。

http://www.ppmy.cn/news/1515441.html

相关文章

【Docker】Docker学习01 | 什么是docker?

本文首发于 ❄️慕雪的寒舍 因为本人没有学习过docker&#xff0c;虽然部署过很多镜像&#xff0c;但是对于docker底层的实现一概不知。趁学习一个新项目的契机&#xff0c;将docker的相关概念了解清楚。 安装docker的教程请查看 Linux主机安装docker。 如果你想和我一起学习do…

【计算机网络】网络版本计算器

此前我们关于TCP协议一直写的都是直接recv或者read&#xff0c;有了字节流的概念后&#xff0c;我们知道这样直接读可能会出错&#xff0c;所以我们如何进行分割完整报文&#xff1f;这就需要报头来解决了&#xff01; 但当前我们先不谈这个话题&#xff0c;先从头开始。 将会…

[Algorithm][综合训练][mari和shiny][重排字符串]详细讲解

目录 1.mari和shiny1.题目链接2.算法原理详解 && 代码实现 2.重排字符串1.题目链接2.算法原理详解 && 代码实现 1.mari和shiny 1.题目链接 mari和shiny 2.算法原理详解 && 代码实现 自己的版本&#xff1a;三层循环暴力枚举 --> 超时 --> 40% …

Android如何高效的加载大型位图

图片有各种形状和大小。在很多情况下,它们的大小超过了典型应用界面的要求。例如,系统“图库”应用会显示使用 Android 设备的相机拍摄的照片,这些照片的分辨率通常远高于设备的屏幕密度。 鉴于使用的内存有限,理想情况下您只希望在内存中加载较低分辨率的版本。分辨率较低…

【记录】基于Windows系统安装rust环境的过程

到官网下载安装包【入门 - Rust 程序设计语言 (rust-lang.org)】 ![[Pasted image 20240703142911.png]] 选择1&#xff0c;快速安装 选择编译配置&#xff0c;1为标准 安装完成 验证是否安装完毕 rustc --versioncargo --version验证成功&#xff01;

从0到1使用webpack搭建react脚手架

背景 好多前端童鞋工作多年依然不会使用webpack搭建react脚手架&#xff0c;本文就介绍下如何从零开始搭建一个属于你自己的前端脚手架&#xff0c;提高自己的工程化实力&#xff0c;同时也提高团队的开发效率。 一、基础配置 目标&#xff1a;可以启动最简单的react项目 初…

el-table 表格自定义添加表格数据后自动滚动到最底部

动态表格&#xff0c;可以新增行列数&#xff0c;为了用户体验&#xff0c;新增后超出表格流体高度后&#xff0c;自动滚动到最下方 需要element-plus如下api 代码如下&#xff1a; const addCapacity () > {inputList.value.push({name: "",desc: "&quo…

Macos M1 IDEA本地调试 HBase 2.2.2

# 1. 前提 执行 mvn clean package assembly:single -DskipTests没问题&#xff0c;并在hbase-assembly/target目录下生成hbase-2.2.2-bin.tar.gz 文件夹 证明Maven 下载依赖没问题 1.1 报错 1 这里应该是报错找不到 com.google.protobuf:protoc:exe:osx-aarch_64:3.5.1 …

Django 框架中 select_related 和 prefetch_related的区别

在Django框架中&#xff0c;select_related 和 prefetch_related 是两个优化数据库查询性能的非常重要的方法&#xff0c;特别是在处理外键关联查询时。尽管它们的目的相似&#xff0c;但在处理方式和适用场景上有所不同。 select_related select_related 主要是用于解决“一…

Java SpringBoot+Vue实战教程:如何搭建高中素质评价档案系统?

✍✍计算机编程指导师 ⭐⭐个人介绍&#xff1a;自己非常喜欢研究技术问题&#xff01;专业做Java、Python、微信小程序、安卓、大数据、爬虫、Golang、大屏等实战项目。 ⛽⛽实战项目&#xff1a;有源码或者技术上的问题欢迎在评论区一起讨论交流&#xff01; ⚡⚡ Java实战 |…

基于51单片机的电动式百叶窗proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1ptXdnVxytPadcE7kOT9MwA 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectro…

iOS Native与JS通信:JSBridge

文章目录 一、简介二、JS 调用 Native1.使用 URL Schemea.UIWebViewb.WKWebView 2.使用 JavaScriptCore (iOS 7)3.使用 WKWebView 和 WKScriptMessageHandler (iOS 8) 三、Native 调用 JS1.使用 UIWebView2.使用 WKWebView3.使用 JavaScriptCore (iOS 7) 一、简介 对于移动应用…

mysql在k8s环境里安装及搭建主从架构

1、环境准备 k8s集群&#xff0c;版本1.27.0 2、搭建nfs服务器 本次用的k8smaster节点作为nfs服务器&#xff0c;因为需要在两个工作节点上连接nfs&#xff0c;所以工作节点上也要安装nfs yum install -y nfs-utils 我们直接在nfs服务器(k8s-master)当中创建这三个目录并写入…

Linux--数据链路层(macarp)

目录 1.认识以太网 2.以太网帧格式 3.模拟一次局域网通信&#xff08;交换机&#xff09; 4.认识 MAC 地址 对比理解 MAC 地址和 IP 地址 5.认识MTU MTU 对 IP 协议的影响 MTU 对 UDP 协议的影响 MTU 对于 TCP 协议的影响 6.ARP协议 ARP 协议的作用及原理 ARP 数据报的…

前端面试宝典【设计模式】【4】

在前端开发的世界里,每一次面试都是一次机遇,也是一次挑战。 你是否曾因技术深度不够而错失良机? 或是面对最新的技术趋势感到迷茫? 我们的【前端面试宝典】正是为此而来。 由拥有多年一线实战经验的资深工程师亲自授课,结合最新的行业动态与实战案例,旨在全面提升你的技…

BurpSuite2024.7.3专业版

前言 Burp Suite是一个无需安装软件&#xff0c;下载完成后&#xff0c;直接从命令行启用即可。开箱即可使用支持LInux/Windows/Mac 01更新介绍 2024.7.13版本界面大改动此版本引入了重大的性能升级、对拦截功能的重大增强&#xff0c;以及在审计项目表中新增了扫描插入点列。…

电路笔记(PCB):数字滤波电路的拉普拉斯变换与零极点分析

拉普拉斯变换基础 拉普拉斯变换 拉普拉斯变换是一种积分变换&#xff0c;用于将一个时间域的函数&#xff08;通常是信号或系统的响应&#xff09;转换为一个复频域的函数。这种变换可以简化许多微分方程和线性系统分析的过程。其定义为&#xff1a; L { f ( t ) } F ( s )…

PyCharm汉化:简单一步到胃!PyCharm怎么设置中文简体

最近在弄python的项目 一起加油哦 步骤&#xff1a; PyCharm的汉化可以通过两种主要方法完成&#xff1a; 方法一&#xff1a;通过PyCharm内置的插件市场安装中文语言包 1. 打开PyCharm&#xff0c;点击File -> Settings&#xff08;在Mac上是PyCharm -> Preferences…

[数据集][目标检测]绳子检测数据集VOC+YOLO格式322张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;322 标注数量(xml文件个数)&#xff1a;322 标注数量(txt文件个数)&#xff1a;322 标注类别…

计算机网络基础 - 应用层(1)

计算机网络基础 应用层网络应用的体系结构C/S 体系结构P2P 体系结构C/S 和 P2P 体系结构的混合体 进程通信概述套接字&#xff08;Socket&#xff09;TCP socketUDP socket 应用层协议应用层需要传输层提供的服务Web 与 HTTP概念非持续连接和持续连接HTTP报文格式请求报文响应报…