简单富文本编辑器实现
在线demo预览,实现原理如下:
1)获取选区内容,如果没有选区则给整段文本设置样式。
2)新增span标签包裹选区内容,为span标签增加style样式。
3)优化DOM结构。比如demo中删除了空白节点、合并父子层级样式减少层级嵌套。
第一步:通过 www.getSelection() 获取选区,sel.isCollapsed判断选区的起始点和终止点是否位于一个位置
//返回一个 Selection 对象,表示用户选择的文本范围或光标的当前位置
let sel = window.getSelection()
let range = sel.getRangeAt(0) //返回一个包含当前选区内容的区域对象。
if (sel.isCollapsed) { //没有框选设置整段文本样式
container.style[key] = val
return
}
第二步:新增span标签包裹选区内容
const f = range.extractContents() //获取选取内容,并删除
let span = document.createElement('span')
span.style.setProperty(key, val)
span.appendChild(f) //span标签包裹选取内容
【简单富文本编辑器实现】第三步:优化dom结构,替换选取节点内容
const keys = ['font-size', 'letter-spacing', 'font-weight', 'color']function getNodeStyle(n) {
const style = n.style
let ret = {}
keys.filter(k => style[k] != null && style[k] != '').forEach(k => {
ret[k] = style[k]
})
return ret
}function appendStyle(n, style) {
for (let key in style) {
n.style.setProperty(key, style[key])
}
}function isSame(s1, s2) {
return JSON.stringify(s1) == JSON.stringify(s2)
}
//找到文本,向上获取父节点的样式附加到自身,减少span嵌套层级
function flatNode(node) {
let list = []
let pStyle = getNodeStyle(node)
let last = null;
function _each(n, s) {
for (let i = 0;
i < n.childNodes.length;
i++) {
let child = n.childNodes[i]
if (child.nodeType == 3) {
let newStyle = Object.assign({}, s, pStyle)
if (last && isSame(newStyle, getNodeStyle(last))) {
last.appendChild(child.cloneNode())
last.normalize() //相邻文本节点合并
} else {
let span = document.createElement('span')
span.appendChild(child.cloneNode())
appendStyle(span, newStyle)
list.push(span)
last = span;
}
} else {
_each(child, Object.assign({}, s, getNodeStyle(child), pStyle))
}
}
}
_each(node, {})
return list;
}const nodeList = flatNode(span)
let newF = document.createDocumentFragment()
newF.replaceChildren(...nodeList)
newF.normalize()
range.insertNode(newF) //选区位置插入新节点
推荐阅读
- 树莓派文字转语音|树莓派文字转语音 python_基于树莓派的OTON眼镜(将文本转换为语音)
- C++实现简单的计算器功能
- (九)React|(九)React Ant Design Pro + .Net5 WebApi(后端环境搭建-IdentityServer4-简单配置)
- C语言实现简单员工工资管理系统
- java|JAVA使用EasyExcel数据库动态导出Excel,超简单!
- k8s原来这么简单(二)安装k8s1.23集群
- 强化学习|强化学习笔记(五)Pytorch实现简单DQN
- 自然语言处理|BERT(5)---实战[BERT+CNN文本分类]
- 设计模式|Java设计模式之简单工厂模式
- 机器学习实战|机器学习实战 | SKLearn入门与简单应用案例