通过HTML标签的contenteditorable属性实现一个带表情图片输入的输入框
- 实现效果如下
- 这里主要是通过
contenteditorable
属性操作dom,在点击表情的时候往对应位置添加img
标签
- 主要实现代码如下(vue2)
<template>
<div class="o-input">
<div class="head">
<i class="emoji-btn iconfont icon-xiaolian" title="表情">
<div class="emoji-box">
<img
v-for="(item, index) in emojiList"
:key="index"
:src="item.src"
:title="item.name"
@click.stop="handleEmoji(item)"
/>
</div>
</i>
<i class="iconfont icon-tupian" title="图片"></i>
<i class="iconfont icon-wenjianjia" title="文件"></i>
</div>
<div
@click="clickInput"
@input="inputHandle"
@keyup="keydownEvent"
class="input-box"
ref="inputBox"
contenteditable="true"
></div>
<div class="send-btn">
<button>发送</button>
</div>
</div>
</template>
<script>
import {
emojiList } from "./emoji";
import {
parseToText } from './util';
export default {
name: "o-input",
data() {
return {
emojiList: emojiList,
};
},
methods: {
keydownEvent(e){
if(e.keyCode === 13) {
let range = window.getSelection().getRangeAt(0);
range.endContainer.setAttribute("name", "o-input-div---")
}
},
handleEmoji(emoji) {
var selection = window.getSelection();
if (
selection.anchorNode !== this.$refs.inputBox &&
!this.$refs.inputBox.contains(selection.anchorNode)
) {
selection.removeAllRanges();
this.$refs.inputBox.focus();
if (this.$refs.inputBox.lastChild)
selection.getRangeAt(0).setStartAfter(this.$refs.inputBox.lastChild);
selection.collapseToEnd();
}
let img = document.createElement("img");
img.src = emoji.src;
img.className = "in-img";
img.setAttribute("name", emoji.regName);
let range = selection.getRangeAt(0);
range.deleteContents();
range.insertNode(img);
range = range.cloneRange();
range.setStartAfter(img);
range.collapse();
selection.removeAllRanges();
selection.addRange(range);
this.inputHandle();
},
clickInput(e) {
if (!(e.target instanceof HTMLImageElement)) {
return;
}
let target = e.target;
let targetX = target.x + Math.floor(target.width / 2);
let selection = window.getSelection();
let range = selection.getRangeAt(0);
range = range.cloneRange();
range.setStartBefore(target);
if (e.x < targetX) {
range.setEndBefore(target);
} else {
range.setEndAfter(target);
}
range.collapse();
selection.removeAllRanges();
selection.addRange(range);
},
inputHandle(){
let html = this.$refs.inputBox.innerHTML;
let text = parseToText(html);
console.log(text);
}
},
};
</script>