输入框加表情

发布时间 2024-01-11 14:59:47作者: 孙大猛子

<template>
<view class="content">
<image class="logo" src="/static/logo.png"></image>
<view class="text-area">
156
<view
placeholder="请输入内容"
:addImg="status"
:change:addImg="editorRender.insertImage"
@blur="blurEvent"
@focus="focusEvent"
class="editor"
contenteditable="true"
></view>
</view>
<button @click="onAdd">添加表情</button>
</view>
</template>

<script>
export default {
data() {
return {
title: 'Hello',
status: 0
};
},
onLoad() {},
methods: {
onAdd() {
this.status++;
},
blurEvent() {},
focusEvent() {}
}
};
</script>

<script module="editorRender" lang="renderjs">
export default {
name: "o-editor",
data() {
return {
enterFlag: 2
};
},
mounted() {
let editor = document.querySelector(".editor");
editor.addEventListener("keydown", this.keydownEvent);
editor.addEventListener("keyup", this.keyupEvent);
editor.addEventListener("click", this.clickInput);
},
methods: {
/**
* 清空
*/
clearContent(){
let editor = document.querySelector(".editor");
editor.innerHTML = "";
this.keyupEvent();
},
keydownEvent(e) {
if (e.keyCode === 13) {
if (++this.enterFlag < 2) {
e.preventDefault();
return false;
}
this.enterFlag = -1;
return false;
}
},
keyupEvent(e) {
let editor = document.querySelector(".editor");
let content = editor.innerHTML;
if (e && e.keyCode === 13) {
let range = window.getSelection().getRangeAt(0);
range.endContainer.setAttribute("name", "o---input---div---")
}
this.callMethod('inputContent', content)
},
callMethod(methodName, value) {
this.$ownerInstance.callMethod(methodName, {
content: value
})
},
async insertImage(newValue) {
let url = 'https://lrwuyu.shenduxr.com/10001/20230605/ceb77ce688ea9556f40a46d02268e5ff.jpg';
console.log(newValue);
if (!newValue) {
return;
}
let options = {
src: 'https://lrwuyu.shenduxr.com/10001/20230605/ceb77ce688ea9556f40a46d02268e5ff.jpg',
width: '20px',
height: '20px',
extClass: 'emoji',
data: {
name: '你好啊'
}
};
if(options.type === 'clear'){
this.clearContent();
return;
}
// if (!options.src) {
// options.fail && options.fail("src cannot be empty");
// return;
// }
let img = document.createElement("img");
img.src = options.src;
img.setAttribute("style", `width: ${options.width}; height: ${options.height};`);
img.setAttribute("alt", options.alt);
img.setAttribute("class", options.extClass);
console.log(img);
// 节点上增加标签
await this.serialization(options.data, img);
this.insertImg(img);
options.success && options.success(true);
options.complete && options.complete('end');
},
insertImg(el) {
const editor = document.querySelector(".editor");
var selection = window.getSelection(); // 获取光标
if ( // 如果没有焦点或者焦点不在输入框内,聚焦到输入框
selection.anchorNode !== editor &&
!editor.contains(selection.anchorNode)
) {
// 聚焦到输入框
selection.removeAllRanges();
editor.focus();
if (editor.lastChild)
selection.getRangeAt(0).setStartAfter(editor.lastChild);
selection.collapseToEnd();
}

let range = selection.getRangeAt(0);
range.deleteContents();

range.insertNode(el);
range = range.cloneRange();
range.setStartAfter(el);
range.collapse();
selection.removeAllRanges();
selection.addRange(range);
this.keyupEvent();
},
// 序列化字符串:key=value;key=value
serialization(data, el) {
return new Promise((resovle) => {
if (data instanceof Object) {
let str = "";
const keys = Object.keys(data);
if (!keys || keys.length == 0) {
return '';
}
for (const key of keys) {
el.setAttribute(key, data[key]);
}
}
resovle(true)
})
},
// 点击输入框内容是设置光标
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();
if (e.x < targetX) {
range.setStartBefore(target);
range.setEndBefore(target);
} else {
range.setStartBefore(target);
range.setEndAfter(target);
}

range.collapse();
selection.removeAllRanges();
selection.addRange(range);
}
}
};
</script>

<style>
.text-area {
background-color: red;
}
.editor {
width: 600rpx;
}
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}

.logo {
height: 200rpx;
width: 200rpx;
margin-top: 200rpx;
margin-left: auto;
margin-right: auto;
margin-bottom: 50rpx;
}

.text-area {
display: flex;
justify-content: center;
}

.title {
font-size: 36rpx;
color: #8f8f94;
}
</style>