[2023.09.22]:探索Rust编写基于web_sys的WebAssembly编辑器:挑战输入光标定位的实践

昨天,我对过去两周的工作进行了总结并上传了源代码。而今天,我又踏入了一个对我来说既熟悉又陌生的领域:编辑器。

我对编辑器的熟悉来自于多年来使用他人开发的编辑器的经验,但对于自己开发编辑器这件事情,我感到陌生。

重新设计一个编辑器基于以下两个目的:

  1. 我想在笔记数据中插入一些元数据,以供后期对笔记数据的分析和整理使用。这需要我能够完全控制这个编辑器的数据输出格式;
  2. 我也很想体验基于Rust开发出来的WebAssembly,它性能到底会有多高;

想自己开发一个编辑器,我的感受,就一个字"难",但我很享受这个挑战。这也让我反思了一下,这些年来,我到底写了多少有价值的代码呢?

步骤

今天主要解决输入光标的位置获取以及再次定位。期间遇到的困难就不分享了,这里只把步骤列出来。

1. 设置contenteditable设置

contenteditable是一个属性,它可以应用于任何HTML元素,并且允许用户编辑元素的内容。当将contenteditable属性设置为true时,可以像Input或者TextArea一样,让用户编辑其中的内容。重点是,它的innerHtml是可编辑的,因此这让我们有了实现丰富编辑功能的潜在可能性。

html 复制代码
<div class="content" contenteditable="true" {oninput} ref={content1_ref}>
</div>

2. 获取当前window对象

在web_sys中,window对象是,是除了事件对象之外,我们获取一切对象的入口。比如,我们后面要获取当前的光标位置,就要从window对象开始。

rust 复制代码
let window = web_sys::window().expect("get window object err");

3. 获取当前的Selection

Selection对象代表当前用户选择的范围,它其中就包含我们需要的光标位置。Selection这个概念中也包含两个名词需要说明一下,这对后面控制光标的位置有帮助。一个是anchor,一个是focus。anchor(锚点)是用户选择开始的位置,focus(焦点)是用户选择结束。

rust 复制代码
let selection = window.get_selection().expect("get selection result err").expect("get selection option err");

4. 记录当前光标位置

光标的位置,从上面取到的selection对象得到。当然,下面的代码比较简单,实际的应用可能会更复杂一些。后面我再更新。因为我们是在输入事件中捕获光标的位置,所以就直接使用range.start_offset()的返回值。变量pos记录了当前光标的位置。

rust 复制代码
let range: Range = selection.get_range_at(0).expect("get range err");
let pos = range.start_offset().unwrap();

5. 设置当前的光标位置

当我们对输入的数据进行格式化之后,光标会自动跳到行首,这个时候需要再次设置光标的位置。这里,我们分别调用了range.set_start()range.set_end

rust 复制代码
selection.remove_all_ranges().unwrap();
selection.add_range(&range);
let div = get_div_element(&e).expect("get div");
range.set_start(&div.first_child().expect("get first child"), pos);
range.set_end(&div.first_child().expect("get first child"), pos);

6. 从新设置焦点

上面,我们只是设置了Selection,还需要最后一行代码来将输入光标显示出来。

rust 复制代码
div.focus();

总结

这个过程我们涉及到的对象有window, Selection, Range, HtmlDivElement。获取输入光标的路径是window -> Selection -> Range。

好了今天就到这里,大家周末愉快。欢迎大家留言交流。

相关推荐
白兰地空瓶2 小时前
🚀你以为你在写 React?其实你在“搭一套前端操作系统”
前端·react.js
爱上妖精的尾巴2 小时前
6-4 WPS JS宏 不重复随机取值应用
开发语言·前端·javascript
似水流年QC3 小时前
深入探索 WebHID:Web 标准下的硬件交互实现
前端·交互·webhid
陪我去看海3 小时前
测试 mcp
前端
speedoooo4 小时前
在现有App里嵌入一个AI协作者
前端·ui·小程序·前端框架·web app
全栈胖叔叔-瓜州4 小时前
关于llamasharp 大模型多轮对话,模型对话无法终止,或者输出角色标识User:,或者System等角色标识问题。
前端·人工智能
三七吃山漆4 小时前
攻防世界——wife_wife
前端·javascript·web安全·网络安全·ctf
用户47949283569154 小时前
面试官问"try-catch影响性能吗",我用数据打脸
前端·javascript·面试
GISer_Jing4 小时前
前端营销技术实战:数据+AI实战指南
前端·javascript·人工智能
GIS之路5 小时前
使用命令行工具 ogr2ogr 将 CSV 转换为 Shp 数据(二)
前端