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

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

相关推荐
松树戈44 分钟前
plus-ui&RuoYi-Vue-Plus 基于pgSql本地运行实践
前端·vue.js·spring boot·ui
new6669991 小时前
css画图形
前端·css
Yvonne爱编码2 小时前
CSS- 1.1 css选择器
前端·css·状态模式·html5·hbuilder
山河故人1632 小时前
uniapp使用npm下载
前端·npm·uni-app
-曾牛2 小时前
基于微信小程序的在线聊天功能实现:WebSocket通信实战
前端·后端·websocket·网络协议·微信小程序·小程序·notepad++
一口一个橘子3 小时前
[ctfshow web入门] web72
前端·web安全·网络安全
Web极客码3 小时前
如何使用WordPress SEO检查器进行实时内容分析
前端·seo·wordpress
Stella25213 小时前
【Vue】CSS3实现关键帧动画
前端·vue.js·css3
junjun.chen06063 小时前
【在qiankun模式下el-dropdown点击,浏览器报Failed to execute ‘getComputedStyle‘ on ‘Window‘: parameter 1 is not o
前端·javascript·前端框架
Yvonne爱编码3 小时前
HTML-3.3 表格布局(学校官网简易布局实例)
前端·html·github·html5·hbuilder