[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。

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

相关推荐
LinXunFeng4 分钟前
Flutter - Melos Pub workspaces 实践
前端·flutter·架构
艾小码7 分钟前
前端人必看!3个技巧让你彻底搞懂JS条件判断与循环
前端·javascript
Kiri霧5 小时前
Linux下的Rust 与 C 的互操作性解析
c语言·开发语言·rust
灵感__idea8 小时前
Hello 算法:让前端人真正理解算法
前端·javascript·算法
向葭奔赴♡8 小时前
CSS是什么?—— 网页的“化妆师”
前端·css
黑犬mo8 小时前
在Edge、Chrome浏览器上安装uBlock Origin插件
前端·edge
excel8 小时前
🧩 Vue 3 watch 源码详解(含完整注释)
前端·javascript·vue.js
大前端helloworld8 小时前
前端梳理体系从常问问题去完善-网络篇
前端·面试
excel9 小时前
🌿 一文看懂 Vue 3 的 watch 源码:从原理到流程
前端
繁依Fanyi9 小时前
让工具说话:我在 Inspira Board 里用 AI 把“能用、好用、可复用”落成了日常
前端