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

news2024/9/21 10:38:27

场景需求

  • 编辑器段落对应显示材料
  • 编辑器滚动时,材料同步滚动
  • 编辑器段落无数据时,材料不显示

实现方法

  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.coloradmin.cn/o/2055842.html

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

相关文章

鸿蒙开发5.0【基于自定义注解和代码生成实现路由框架】

场景描述 在应用开发中无论是出于工程组织效率还是开发体验的考虑&#xff0c;开发者都需要对项目进行模块间解耦&#xff0c;此时需要构建一套用于模块间组件跳转、数据通信的路由框架。 业界常见的实现方式是在编译期生成路由表。 1. 实现原理及流程 在编译期通过扫描并解…

吴恩达机器学习-C2W3-应用机器学习的建议

在本实验中&#xff0c;您将探索评估和改进机器学习模型的技术。 1-调包 首先&#xff0c;让我们运行下面的单元格来导入在此任务中需要的所有包。 numpymatplotlibscikitlearntensorflow import numpy as np %matplotlib widget import matplotlib.pyplot as plt from skle…

模拟实现queue适配器【队列】【C++】

P. S.&#xff1a;以下代码均在VS2022环境下测试&#xff0c;不代表所有编译器均可通过。 P. S.&#xff1a;测试代码均未展示头文件stdio.h的声明&#xff0c;使用时请自行添加。 博主主页&#xff1a;LiUEEEEE                        …

私域经济的挖掘:多元渠道下的流量引爆方法

近年来&#xff0c;私域经济越来越受到品牌企业的青睐。基于个性化需求的私域市场&#xff0c;既有精准定位的成本优势&#xff0c;又有巨大的潜力空间。然而&#xff0c;想要把私域做成&#xff0c;其实也是充满了挑战&#xff0c;其中&#xff0c;怎样有效吸引流量&#xff0…

01、Redis入门:数据类型、基本操作、SpringDataRedis

Redis快速入门 Redis的常见命令和客户端使用 1.初识Redis Redis是一种键值型的NoSql数据库&#xff0c;这里有两个关键字&#xff1a; 键值型 NoSql 其中键值型&#xff0c;是指Redis中存储的数据都是以key、value对的形式存储&#xff0c;而value的形式多种多样&#xf…

错误信息“缺少msvcr120.dll”或“找不到msvcr120.dll”应该如何修复?几种方法快速修复

由于这个msvcr120.dll文件与应用程序的运行密切相关&#xff0c;任何与之相关的问题都可能导致应用程序无法正常运行。错误信息如“缺少msvcr120.dll”或“找不到msvcr120.dll”&#xff0c;通常出现在软件安装不正确或系统更新后。接下俩就教大家几种方法快速修复msvcr120.dll…

7 周岁自闭症儿童可以去普校上学吗?

对于许多自闭症儿童的家长来说&#xff0c;孩子能否去普通学校上学是一个至关重要的问题。而星贝育园给出了充满希望的答案。 星贝育园向家长郑重承诺&#xff0c;4 周岁之前开始干预可以 100%摘帽&#xff0c;即消除自闭症症状。在这里&#xff0c;为自闭症儿童提供个性化教学…

Spring源码解析(34)之Spring事务回滚流程

一、前言 在上一个篇章我们主要介绍了Spring事务的运行流程&#xff0c;也带着一步步debug看了整个事务的运行流程&#xff0c;但是还是欠缺了Spring事务的回滚的流程。 在上篇也主要介绍了Spring事务的传播特性&#xff0c;这里还是要看一下Spring事务的传播特性&#xff0c;因…

思博伦测试每秒最大新建、并发、吞吐

详细方法查看本文资源链接 一、最大新建测试说明 1、新建测试的主要目标是测试被测设备&#xff08;DUT&#xff09;的处理器能力。在单位时间内能够建立的连接数越多&#xff0c;说明被测设备的处理器的能力越强。 2、由于在测试过程中&#xff0c;我们只关心成功的建立TCP…

流动会场:定义新一代灵活空间的全新选择—轻空间

在当今快节奏的世界里&#xff0c;活动和会议的需求正变得越来越多样化和复杂化。无论是公司年会、大型宴会、还是各类演出和会议&#xff0c;场地的选择不仅需要满足功能需求&#xff0c;更要灵活、易于部署。正是在这样的背景下&#xff0c;“流动会场”这一创新概念应运而生…

反向沙箱是什么?如何使用反向沙箱保障上网安全

反向沙箱是什么&#xff1f; 反向沙箱是深信达的一种沙箱技术&#xff0c;又称SPN&#xff08;Sandbox Proxy Network&#xff09;沙箱。主要用于解决企业在安全上网过程中的风险问题。它通过在企业内部部署一个隔离的沙盒环境&#xff0c;实现安全的互联网访问&#xff0c;从而…

注意力机制(课程笔记)

一&#xff1a; 针对的问题 解决在循环卷积网络RNN模型中存在的信息瓶颈问题。 信息瓶颈&#xff1a; 举的是机器翻译的例子。在RNN中&#xff0c;Decoder的第一个输出取决于Encoder中的上一个输出&#xff0c;然后Decoder的其余输出都取决于上一个Decoder输出&#xff08;也就…

使用Nexus3为containerd和docker配置镜像代理

1.Nexus3介绍&#xff1a; Nexus3&#xff08;Nexus Repository Manager3&#xff09;是一个用于存储、组织和管理软件组件&#xff08;如 JAR文件、npm包、Docker镜像等&#xff09;的仓库管理系统。它由Sonatype开发并维护。Nexus Repository Manger支持许多流行的包管理工具…

免费仿微信聊天工具盒子IM

盒子IM是一个仿微信实现的网页版聊天软件&#xff0c;不依赖任何第三方收费组件。后端采用springbootnetty实现&#xff0c;web端使用vue&#xff0c;移动端使用uniapp&#xff0c;支持私聊、群聊、离线消息、发送图片、文件、语音、emoji表情、视频聊天等功能。包含pc端和移动…

Redis 技术详解

一、Redis 基础 &#xff08;一&#xff09;为什么使用 Redis 速度快&#xff0c;因为数据存在内存中&#xff0c;类似于 HashMap&#xff0c;查找和操作的时间复杂度都是 O(1)。支持丰富数据类型&#xff0c;支持 string、list、set、Zset、hash 等。支持事务&#xff0c;操…

Go —— 反射

反射 反射是什么&#xff1f; 反射是运行时检查自身结构的机制反射是困惑的源泉。 反射特性与 interface 紧密相关。 接口 1. 类型 Go是静态类型语言&#xff0c;比如int、float32、[]byte&#xff0c;等等。每个变量都有一个静态类型&#xff0c;而且在编译时就确定了。…

自主智能体的未来:LangChain Agents如何实现复杂任务自动化

一、AI Agents 基础&#xff1a;ReAct 范式 在AI领域&#xff0c;智能体&#xff08;Agents&#xff09;指的是能够自主感知环境并采取行动以实现特定目标的系统。ReAct&#xff08;Reasoning and Acting&#xff09;范式是理解智能体的基础&#xff0c;它强调智能体在执行任务…

【YashanDB知识库】共享集群YAC换IP

【标题】共享集群YAC换IP 【需求分类】安装部署&#xff0c;配置变更 【关键字】安装部署&#xff0c;更换IP&#xff0c;运维&#xff0c;配置变更&#xff0c;高可用&#xff0c;YAC 【需求描述】客户需要将已经部署的YAC集群更换IP&#xff0c;从测试网段切换生产网段 【…

2024年AI艺术生成器精选榜单,抢先体验!

选择合适的AI艺术生成器对于设计项目的成功至关重要。无论是从设计线框到复杂的交互原型&#xff0c;合适的工具都能帮助顺利实现目标。本文将分享2024年最受欢迎的AI艺术生成器&#xff0c;让我们一起来看看&#xff01; 即时设计 在2024年好用的AI艺术生成器中&#xff0c;…

基于STM32开发的智能家居照明系统

目录 引言环境准备工作 硬件准备软件安装与配置系统设计 系统架构硬件连接代码实现 系统初始化光线检测与自动调节手动控制与状态指示Wi-Fi通信与远程控制应用场景 家庭智能照明办公室自动化照明常见问题及解决方案 常见问题解决方案结论 1. 引言 智能家居照明系统通过集成光…