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 相关文章推荐
JQuery上传插件Uploadify使用详解及错误处理
Apr 27 Javascript
jQuery EasyUI API 中文文档 - Pagination分页
Sep 29 Javascript
jquery实现可自动判断位置的弹出层效果代码
Oct 12 Javascript
js阻止浏览器默认行为触发的通用方法(推荐)
May 15 Javascript
用js写的一个路由(简单实例)
Sep 24 Javascript
详解JavaScript时间处理之几个月前或几个月后的指定日期
Dec 21 Javascript
JS使用Date对象实时显示当前系统时间简单示例
Aug 23 Javascript
如何将百度地图包装成Vue的组件的方法步骤
Feb 12 Javascript
vue实现日历备忘录功能
Sep 24 Javascript
基于Taro的微信小程序模板消息-获取formId功能模块封装实践
Jul 15 Javascript
微信小程序吸底区域适配iPhoneX的实现
Apr 09 Javascript
vue 动态组件(component :is) 和 dom元素限制(is)用法说明
Sep 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
PHP5 字符串处理函数大全
2010/03/23 PHP
PHP使用Alexa API获取网站的Alexa排名例子
2014/06/12 PHP
PHP session 会话处理函数
2016/06/06 PHP
php利用header函数下载各种文件
2016/08/24 PHP
PHP htmlspecialchars_decode()函数用法讲解
2019/03/01 PHP
jquery操作select option 的代码小结
2011/06/21 Javascript
javascript中的注释使用与注意事项小结
2011/09/20 Javascript
js操作模态窗口及父子窗口间相互传值示例
2014/06/09 Javascript
js实现文字滚动效果
2016/03/03 Javascript
javascript简单实现等比例缩小图片的方法
2016/07/27 Javascript
微信小程序 详解Page中data数据操作和函数调用
2017/01/12 Javascript
vue router使用query和params传参的使用和区别
2017/11/13 Javascript
Vue中this.$router.push参数获取方法
2018/02/27 Javascript
以v-model与promise两种方式实现vue弹窗组件
2018/05/21 Javascript
node跨域转发 express+http-proxy-middleware的使用
2018/05/31 Javascript
使用Vue-cli 3.0搭建Vue项目的方法
2018/06/07 Javascript
openlayers实现地图弹窗
2020/09/25 Javascript
举例详解Python中循环语句的嵌套使用
2015/05/14 Python
Python中使用装饰器来优化尾递归的示例
2016/06/18 Python
python绘制简单折线图代码示例
2017/12/19 Python
python合并已经存在的sheet数据到新sheet的方法
2018/12/11 Python
在Qt5和PyQt5中设置支持高分辨率屏幕自适应的方法
2019/06/18 Python
Python企业编码生成系统之系统主要函数设计详解
2019/07/26 Python
Django REST Framework之频率限制的使用
2019/09/29 Python
Python: tkinter窗口屏幕居中,设置窗口最大,最小尺寸实例
2020/03/04 Python
虚拟机下载python是否需要联网
2020/07/27 Python
windeln官方海外旗舰店:德淘超人气母婴超市
2017/12/15 全球购物
牛津在线药房:Oxford Online Pharmacy
2020/11/16 全球购物
境外导游求职信
2014/02/27 职场文书
酒店管理求职信范文
2014/04/06 职场文书
中国梦演讲稿范文
2014/08/28 职场文书
党的群众路线教育实践活动总结材料
2014/10/30 职场文书
银行工作心得体会范文
2016/01/23 职场文书
2016年党员创先争优公开承诺书
2016/03/25 职场文书
2016年庆祝六一儿童节活动总结
2016/04/06 职场文书
openstack云计算keystone组件工作介绍
2022/04/20 Servers