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 相关文章推荐
javascript真的不难-回顾一下基础知识
Jan 15 Javascript
javascript中this做事件参数相关问题解答
Mar 17 Javascript
IE与FF下javascript获取网页及窗口大小的区别详解
Jan 14 Javascript
使用jquery菜单插件HoverTree仿京东无限级菜单
Dec 18 Javascript
javascript实现模拟时钟的方法
May 13 Javascript
jQuery表格插件datatables用法详解
Nov 23 Javascript
浅谈jQuery绑定事件会叠加的解决方法和心得总结
Oct 26 Javascript
js获取浏览器和屏幕的各种宽度高度
Feb 22 Javascript
Vue之mixin全局的用法详解
Aug 22 Javascript
vue 登录滑动验证实现代码
Aug 24 Javascript
viewer.js一个强大的基于jQuery的图像查看插件(支持旋转、缩放)
Apr 01 jQuery
Javascript的promise,async和await的区别详解
Mar 24 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
php生成过去100年下拉列表的方法
2015/07/20 PHP
PHP防止图片盗用(盗链)的方法小结
2016/11/11 PHP
PHP实现的pdo连接数据库并插入数据功能简单示例
2019/03/30 PHP
[原创]IE view-source 无法查看看源码 JavaScript看网页源码
2009/07/19 Javascript
php gethostbyname获取域名ip地址函数详解
2010/01/24 Javascript
复选框全选与全不选操作实现思路
2013/08/18 Javascript
JS实现金额转换(将输入的阿拉伯数字)转换成中文的实现代码
2013/09/30 Javascript
深入理解JavaScript系列(30):设计模式之外观模式详解
2015/03/03 Javascript
全面了解JavaScript对象进阶
2016/07/19 Javascript
JavaScript  event对象整理及详细介绍
2016/10/10 Javascript
JavaScript随机生成颜色的方法
2016/10/15 Javascript
node学习记录之搭建web服务器教程
2017/02/16 Javascript
微信小程序中使用ECharts 异步加载数据实现图表功能
2018/07/13 Javascript
Promise.all中对于reject的处理方法
2018/08/01 Javascript
vue项目实现设置根据路由高亮对应的菜单项操作
2020/08/06 Javascript
Vue.js暴露方法给WebView的使用操作
2020/09/07 Javascript
[01:27]2014DOTA2展望TI 剑指西雅图IG战队专访
2014/06/30 DOTA
[56:47]Ti4 循环赛第三日 iG vs Liquid
2014/07/12 DOTA
[03:22]DAC最前线(第二期)—DOTA2亚洲邀请赛主赛场周边及线路探访
2015/01/24 DOTA
python django集成cas验证系统
2014/07/14 Python
基于python爬虫数据处理(详解)
2017/06/10 Python
对python list 遍历删除的正确方法详解
2018/06/29 Python
Python实现基于PIL和tesseract的验证码识别功能示例
2018/07/11 Python
Django框架文件上传与自定义图片上传路径、上传文件名操作分析
2019/05/10 Python
150行Python代码实现带界面的数独游戏
2020/04/04 Python
使用phonegap克隆和删除联系人的实现方法
2017/03/31 HTML / CSS
有机婴儿毛毯和衣服:Monica + Andy
2020/03/01 全球购物
家长给孩子的评语
2014/01/30 职场文书
幼儿教育感言
2014/02/05 职场文书
大学生活自我评价
2014/04/09 职场文书
课前三分钟演讲稿
2014/04/24 职场文书
2014年质检员工作总结
2014/11/18 职场文书
2014年教师业务工作总结
2014/12/19 职场文书
委托公证书样本
2015/01/23 职场文书
2015年暑期社会实践活动总结
2015/03/27 职场文书
MySQL慢查询中的commit慢和binlog中慢事务的区别
2022/06/16 MySQL