我的问题在某种程度上类似于这篇帖子中的讨论,但我想实现的功能相比之下要更丰富。我正在尝试构思一个能够模拟contenteditable特性的div元素,但它将提供更好的体验。用户可以在这个div中添加各种格式、样式的文本,包括不同的字体等,并且甚至还能支持图片、视频等内容的插入。目前这只是一个想法(所以请不要太过于纠结其实用性)。
简而言之,我有一个看起来像这样的div元素。
<div tabindex="0" id="canvas">
<i id="canvas-cursor"> </i>
</div>
JavaScript代码部分是这样的:```markdown
// 获取相关DOM元素
let canvas = document.getElementById("canvas");
let cursor = document.getElementById("canvas-cursor");
// 为画布添加键盘事件监听器
canvas.addEventListener("keydown", editText);
// 定义一个移除元素所有属性的函数
const removeAttributes = (element) => {
for (let i = 0; i < element.attributes.length; i++) {
element.removeAttribute(element.attributes[i].name);
}
};
// 编辑文本事件处理函数
function editText(event) {
event.preventDefault();
const keyName = event.key;
// 处理Ctrl键按下
if (keyName === "Control") {
console.log(`Control key ${keyName}`);
return;
}
// 若同时按下了Ctrl键
if (event.ctrlKey) {
console.log(`Combination of ctrlKey ${keyName}`);
} else {
// 创建一个新的span元素
let newElement = document.createElement("span");
newElement.setAttribute("class", "canvas-child");
switch (keyName) {
case " ":
newElement.innerHTML = "&nbsp";
break;
case "ArrowLeft":
return;
case "ArrowRight":
return;
case "Backspace":
var deleted = canvas.removeChild(cursor.previousElementSibling);
removeAttributes(deleted);
return;
case "ArrowUp":
return;
case "ArrowDown":
return;
case "Enter":
newElement.innerText += "\n";
break;
case "Shift":
case "Alt":
console.log("Alt button is pressed.");
case "Tab":
case "Meta":
case "CapsLock":
return;
default:
newElement.innerText += keyName;
break;
}
// 为新元素添加鼠标进入与离开事件监听器
newElement.addEventListener("mouseenter", (event) => {
// newElement.style.background = "green";
});
newElement.addEventListener("mouseleave", (event) => {
newElement.style.background = "none";
});
// 为新元素添加双击事件监听器
newElement.addEventListener("dblclick", (event) => {
console.log("On click event: " + event
+ "\nsource: " + newElement);
canvas.insertBefore(cursor, newElement);
});
// 将新元素插入到光标前
canvas.insertBefore(newElement, cursor);
}
}
css
|#canvas-cursor {
background-color: red;
animation: blinker 1s linear infinite;
}
为了简洁起见,文本导航和字体样式/格式化功能已被移除,但这些功能运行正常;用户可以选择代码样式、下划线、粗体、字体样式、高亮等样式。
接下来我想处理的是复制和粘贴两个事件。我知道如果我给<div>
元素添加contenteditable="true"
属性,可以很容易地启用这一功能。但是,这样一来,任何键盘输入都会填充到div中,这意味着用户输入的所有内容都会被重复记录,这不是我想要的结果,因为我已经实现了处理用户输入的功能。我只想捕获粘贴事件并按照自己的需求来处理它。有没有办法做到这一点呢?
提前感谢您的帮助。