electron+vue实现div contenteditable截图功能


Posted in Javascript onJanuary 07, 2020

最近在学习基于electron + electron-vue开发聊天客户端项目时,需要用到编辑器插入表情功能。一般通过input或textarea也能实现,通过插入[笑脸]、(:12 这些标签,展示的时候解析标签就行。

如下图效果:

electron+vue实现div contenteditable截图功能 

在网上找到的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属性实现富文本功能

electron+vue实现div contenteditable截图功能 

实现方式:

单独声明一个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

electron+vue实现div contenteditable截图功能

electron+vue实现div contenteditable截图功能

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截图功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
不能再简单的无闪刷新验证码原理很简单
Nov 05 Javascript
用jquery ajax获取网站Alexa排名的代码
Dec 12 Javascript
JavaScript实用技巧(一)
Aug 16 Javascript
jquery操作checkbox示例分享
Jul 21 Javascript
总结JavaScript的正则与其他语言的不同之处
Aug 25 Javascript
Javascript动画效果(2)
Oct 11 Javascript
微信小程序 less文件编译成wxss文件实现办法
Dec 05 Javascript
基于vue的换肤功能的示例代码
Oct 10 Javascript
angularjs获取到My97DatePicker选中的值方法
Oct 02 Javascript
浅谈Vue CLI 3结合Lerna进行UI框架设计
Apr 14 Javascript
element-ui中Table表格省市区合并单元格的方法实现
Aug 07 Javascript
微信小程序学习总结(三)条件、模板、文件引用实例分析
Jun 04 Javascript
解决vue elementUI中table里数字、字母、中文混合排序问题
Jan 07 #Javascript
Vue程序化的事件监听器(实例方案详解)
Jan 07 #Javascript
微信小程序服务器日期格式化问题
Jan 07 #Javascript
webpack 最佳配置指北(推荐)
Jan 07 #Javascript
微信小程序接入腾讯云验证码的方法步骤
Jan 07 #Javascript
vue实现数据控制视图的原理解析
Jan 07 #Javascript
微信小程序wx.navigateTo方法里的events参数使用详情及场景
Jan 07 #Javascript
You might like
使用Xdebug调试和优化PHP程序之[1]
2007/04/17 PHP
PHP simple_html_dom.php+正则 采集文章代码
2009/12/24 PHP
php循环检测目录是否存在并创建(循环创建目录)
2011/01/06 PHP
PHP企业级应用之常见缓存技术篇
2011/01/27 PHP
奇怪的PHP引用效率问题分析
2012/03/23 PHP
详细解读php的命名空间(一)
2018/02/21 PHP
PHP的RSA加密解密方法以及开发接口使用
2018/02/11 PHP
php 广告点击统计代码(php+mysql)
2018/02/21 PHP
php设计模式之策略模式应用案例详解
2019/06/17 PHP
详解handlebars+require基本使用方法
2016/12/21 Javascript
html5+CSS 实现禁止IOS长按复制粘贴功能
2016/12/28 Javascript
js鼠标移动时禁止选中文字
2017/02/19 Javascript
JS操作时间 - UNIX时间戳的简单介绍(必看篇)
2017/08/16 Javascript
浅谈PDF.js使用心得
2018/06/07 Javascript
Jquery的Ajax技术使用方法
2019/01/21 jQuery
在mpvue框架中使用Vant WeappUI组件库的注意事项【推进】
2019/06/09 Javascript
Vue使用Clipboard.JS在h5页面中复制内容实例详解
2019/09/03 Javascript
vue实现在线翻译功能
2019/09/27 Javascript
vue3实现v-model原理详解
2019/10/09 Javascript
Python二叉树定义与遍历方法实例分析
2018/05/25 Python
Python高级编程之消息队列(Queue)与进程池(Pool)实例详解
2019/11/01 Python
python def 定义函数,调用函数方式
2020/06/02 Python
基于Python实现下载网易音乐代码实例
2020/08/10 Python
Python如何在bool函数中取值
2020/09/21 Python
成绩单公证书
2014/04/10 职场文书
挂牌仪式策划方案
2014/05/18 职场文书
清明节演讲稿
2014/05/27 职场文书
优秀工会工作者事迹材料
2014/06/02 职场文书
小学教师培训方案
2014/06/09 职场文书
销售竞赛活动方案
2014/08/23 职场文书
解放思想大讨论活动心得体会
2014/09/11 职场文书
2014年教育培训工作总结
2014/12/08 职场文书
小学班主任经验交流材料
2014/12/16 职场文书
中秋节随笔
2015/08/15 职场文书
小学一年级数学教学反思
2016/02/16 职场文书
Java 泛型详解(超详细的java泛型方法解析)
2021/07/02 Java/Android