[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 分钟前
“最新国产代码大杀器”——MiniMax-M2!
前端·javascript
Python私教13 分钟前
Rust 编程语言基础知识全面介绍
开发语言·后端·rust
小马哥编程30 分钟前
【软考架构】案例分析-web应用设计:SSH 和 SSM(Spring + Spring MVC + MyBatis ) 之间的区别,以及使用场景
前端·架构·ssh
用户1031133116634 分钟前
Vuex学习记录
前端
前端开发爱好者36 分钟前
Electron 淘汰!新的跨端框架来了!性能飙升!
前端·javascript
狮子座的男孩41 分钟前
js基础:08、构造函数(共享方法)、原型(prototype)、原型对象、(修改原型)toString方法、垃圾回收
前端·javascript·经验分享·prototype·垃圾回收·构造函数·原型对象
前端开发爱好者1 小时前
Vue 团队成员又搞了个 "新玩具"!
前端·javascript·vue.js
用户0136087566881 小时前
前端实现文件上传功能
前端
七月稻草人1 小时前
Rust 与数据库连接池的集成:安全与性能的深度耦合
数据库·安全·rust
咖啡の猫2 小时前
Vue-github 用户搜索案例
前端·vue.js·github