结构重构

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

View File

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