结构重构

This commit is contained in:
satori 2025-01-16 06:05:50 +08:00
parent 04c3f57218
commit 5bb61de760
2 changed files with 31 additions and 88 deletions

View File

@ -53,65 +53,52 @@ export class Cursor {
// 获取当前光标的矩形位置
getBoundingClientRect() {
this.updateRange()
this.range.setStart(this.targetNode, this.insertIndex)
this.range.setEnd(this.targetNode, this.insertIndex)
return this.range.getBoundingClientRect()
}
// 更新光标位置
updatePosition(rect) {
if (!rect) {
this.hide()
return
}
this.cursorElement.style.left = `${rect.left}px`
this.cursorElement.style.top = `${rect.top}px`
updatePosition({ left, top }) {
this.cursorElement.style.left = `${left}px`
this.cursorElement.style.top = `${top}px`
this.cursorElement.style.display = "block"
}
// 隐藏光标
hide() {
this.cursorElement.style.display = "none"
}
// 移除光标元素
remove() {
this.cursorElement.remove()
}
move(key) {
// 获取目标节点的上下兄弟节点li元素)
const children = Array.from(this.targetNode.parentNode.parentNode.children)
const siblings = children.filter(node => {
return node !== this.targetNode && node.nodeType === Node.ELEMENT_NODE
}).map(item => {
return Array.from(item.childNodes).find(node => node.nodeType === Node.TEXT_NODE)
})
const currentIndex = siblings.indexOf(this.targetNode)
oninput({ value }) {
const text = this.targetNode.textContent
const left = text.slice(0, this.insertIndex)
const right = text.slice(this.insertIndex)
this.insertIndex += value.length
this.targetNode.textContent = left + value + right
this.updatePosition(this.getBoundingClientRect())
}
if (key === "ArrowUp" && currentIndex > 0) {
const prevSibling = siblings[currentIndex - 1]
const index = Math.max(0, Math.min(prevSibling.textContent.length, this.insertIndex))
this.setTarget(prevSibling, index) // 光标在上一个兄弟元素的起始位置
return
onkeydown({ key }) {
if (key === "ArrowUp" && this.targetNode.parentNode.previousElementSibling) {
// 先取兄弟元素的最后一个子元素, 没有则取兄弟元素, 没有则向上回溯
this.targetNode = Array.from(this.targetNode.parentNode.previousElementSibling.childNodes).find(node => node.nodeType === Node.TEXT_NODE)
this.insertIndex = Math.max(0, Math.min(this.targetNode.textContent.length, this.insertIndex))
this.updatePosition(this.getBoundingClientRect())
}
if (key === "ArrowDown" && currentIndex >= 0 && currentIndex < siblings.length - 1) {
const nextSibling = siblings[currentIndex + 1]
const index = Math.max(0, Math.min(nextSibling.textContent.length, this.insertIndex))
this.setTarget(nextSibling, index) // 光标在下一个兄弟元素的起始位置
return
if (key === "ArrowDown" && this.targetNode.parentNode.nextElementSibling) {
// 先取当前子元素, 没有则取下一个兄弟元素, 没有则向上回溯
this.targetNode = Array.from(this.targetNode.parentNode.nextElementSibling.childNodes).find(node => node.nodeType === Node.TEXT_NODE)
this.insertIndex = Math.max(0, Math.min(this.targetNode.textContent.length, this.insertIndex))
this.updatePosition(this.getBoundingClientRect())
}
if (key === "ArrowLeft" && this.insertIndex > 0) {
if (key === "ArrowLeft") {
this.insertIndex = Math.max(0, Math.min(this.targetNode.textContent.length, this.insertIndex - 1))
this.updateRange()
return
return this.updatePosition(this.getBoundingClientRect())
}
if (key === "ArrowRight" && this.insertIndex < this.targetNode.textContent.length) {
if (key === "ArrowRight") {
this.insertIndex = Math.max(0, Math.min(this.targetNode.textContent.length, this.insertIndex + 1))
this.updateRange()
return
return this.updatePosition(this.getBoundingClientRect())
}
}
}

View File

@ -33,49 +33,13 @@ document.body.appendChild(textarea)
// 处理输入事件
textarea.oninput = () => {
const inputText = textarea.value // 获取用户输入的文本
if (!inputText) return
cursors.forEach(cursor => {
if (!cursor.targetNode || cursor.insertIndex === null) return
// 更新文本节点内容
cursor.targetNode.textContent =
cursor.targetNode.textContent.slice(0, cursor.insertIndex) +
inputText +
cursor.targetNode.textContent.slice(cursor.insertIndex)
// 更新插入位置
cursor.insertIndex += inputText.length
})
// 清空输入框
cursors.forEach(cursor => cursor.oninput(textarea))
textarea.value = ""
updateCursors()
}
// 处理方向键移动插入点
textarea.onkeydown = (event) => {
cursors.filter(cursor => cursor.targetNode && cursor.insertIndex !== null).forEach(cursor => {
cursor.move(event.key)
updateCursors()
})
}
// 更新所有光标的位置
const updateCursors = () => {
cursors.forEach(cursor => {
if (!cursor.targetNode || cursor.insertIndex === null) {
cursor.hide()
return
}
// 获取插入点位置
const rect = cursor.getBoundingClientRect()
// 更新光标位置
cursor.updatePosition(rect)
})
cursors.forEach(cursor => cursor.onkeydown({ key: event.key }))
}
// 渲染 Markdown 并监听点击事件
@ -131,18 +95,10 @@ element.onclick = (event) => {
}
// 更新光标位置
updateCursors()
cursors.forEach(cursor => cursor.updatePosition(cursor.getBoundingClientRect()))
// 聚焦输入框
textarea.value = ""
textarea.focus()
}
// 按删除键移除光标
document.addEventListener('keydown', (event) => {
if (event.key === 'Delete' && cursors.length > 0) {
const cursorToRemove = cursors.pop() // 移除最后一个光标
cursorToRemove.remove() // 移除对应的光标元素
console.log("移除光标")
}
})