electron+vue实现div contenteditable截图功能
最近在学习基于electron + electron-vue开发聊天客户端项目时,需要用到编辑器插入表情功能。一般通过input或textarea也能实现,通过插入[笑脸]、(:12 这些标签,展示的时候解析标签就行。
如下图效果:
在网上找到的jq插件实现在textarea光标处插入表情符标签
<!doctype html> <html> <head> <meta charset="utf-8"> <title></title> <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="container"> <div class="row"> <div class="col col-sm-12"> <button class="btn btn-success" data-emoj="[笑脸]">[笑脸]</button> <button class="btn btn-success" data-emoj="[奋斗]">[奋斗]</button> <button class="btn btn-success" data-emoj="[:17]">[:17]</button> </div> <div class="col col-sm-12"> <textarea class="form-control" id="content" rows="10"></textarea> </div> </div> </div> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script> <script> (function ($) { $.fn.extend({ insertemojatcaret: function (myvalue) { var $t = $(this)[0]; if (document.selection) { this.focus(); sel = document.selection.createrange(); sel.text = myvalue; this.focus(); } else if ($t.selectionstart || $t.selectionstart == '0') { var startpos = $t.selectionstart; var endpos = $t.selectionend; var scrolltop = $t.scrolltop; $t.value = $t.value.substring(0, startpos) + myvalue + $t.value.substring(endpos, $t.value.length); this.focus(); $t.selectionstart = startpos + myvalue.length; $t.selectionend = startpos + myvalue.length; $t.scrolltop = scrolltop; } else { this.value += myvalue; this.focus(); } } }); })(jquery); $("button").on("click", function() { $("#content").insertemojatcaret($(this).attr("data-emoj")); }); </script> </body> </html>
可是这种方法并不是我想要的类似微信编辑框插入表情效果。
如是就想到了div模拟 设置 contenteditable="true"
实现富文本编辑器效果,这种方法是可以实现,不过在vue中不能绑定v-model,最后参考一些技术贴实现了这个功能,一顿操作下来采坑不少,于是就做一些分享记录吧。
vue中通过给div添加contenteditable=true
属性实现富文本功能
实现方式:
单独声明一个vue组件,chatinput.vue,通过监听数据变化并返回父组件。
1、父组件添加v-model
<template> ... <chatinput ref="chatinput" v-model="editortext" @focusfn="handleeditorfocus" @blurfn="handleeditorblur" /> </template>
import chatinput from './chatinput' export default { data () { return { editortext: '', ... } }, components: { chatinput, }, ... }
2、v-model中传入的值在子组件prop中获取
export default { props: { value: { type: string, default: '' } }, data () { return { editortext: this.value, ... } }, watch: { value() { ... } }, }
3、通过监听获取到的prop值,并将该值赋值给子组件中的v-html参数,双向绑定就ok了。
chatinput.vue组件
<!-- vue实现contenteditable功能 --> <template> <div ref="editor" class="editor" contenteditable="true" v-html="editortext" @input="handleinput" @focus="handlefocus" @blur="handleblur"> </div> </template> <script> export default { props: { value: { type: string, default: '' } }, data () { return { editortext: this.value, ischange: true, } }, watch: { value() { if(this.ischange) { this.editortext = this.value } } }, methods: { handleinput() { this.$emit('input', this.$el.innerhtml) }, // 清空编辑器 handleclear() { this.$refs.editor.innerhtml = '' this.$refs.editor.focus() }, // 获取焦点 handlefocus() { this.ischange = false this.$emit('focusfn') }, // 失去焦点 handleblur() { this.ischange = true this.$emit('blurfn') }, /** * 光标处插入内容 * @param html 需要插入的内容 */ inserthtmlatcaret(html) { let sel, range; if(!this.$refs.editor.childnodes.length) { this.$refs.editor.focus() } if (window.getselection) { // ie9 and non-ie sel = window.getselection(); if (sel.getrangeat && sel.rangecount) { range = sel.getrangeat(0); range.deletecontents(); let el = document.createelement("div"); el.appendchild(html) var frag = document.createdocumentfragment(), node, lastnode; while ((node = el.firstchild)) { lastnode = frag.appendchild(node); } range.insertnode(frag); if (lastnode) { range = range.clonerange(); range.setstartafter(lastnode); range.collapse(true); sel.removeallranges(); sel.addrange(range); } } } else if (document.selection && document.selection.type != "control") { // ie < 9 document.selection.createrange().pastehtml(html); } this.handleinput() } } } </script> <style> </style>
组件功能已经亲测,直接一次性拿走使用。
以下是一些参考:
1、vue官方描叙, 自定义组件的v-model:
一个组件上的 v-model 默认会利用名为 value 的 prop 和名为 input 的事件,v-model的值将会传入子组件中的prop
#自定义组件的-v-model
2、vue中div可编辑光标处插入内容
electron+vue中实现截图功能
主要使用的是微信截图dll,通过node执行即可
screenshot() { return new promise((resolve) => { const { execfile } = require('child_process') var screenwin = execfile('./static/printscr.exe') screenwin.on('exit', function(code) { let pngs = require('electron').clipboard.readimage().topng() let imgdata = new buffer.from(pngs, 'base64') let imgs = 'data:image/png;base64,' + btoa(new uint8array(imgdata).reduce((data, byte) => data + string.fromcharcode(byte), '')) resolve(imgs) }) }) },
总结
以上所述是小编给大家介绍的electron+vue实现div contenteditable截图功能,希望对大家有所帮助