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 表格操作(交替显示、拖动表格行、选择行等)
Jul 29 Javascript
ymPrompt的doHandler方法来实现获取子窗口返回值的方法
Jun 25 Javascript
将Datatable转化成json发送前台实现思路
Sep 06 Javascript
javascript禁用Tab键脚本实例
Nov 22 Javascript
Javascript基础教程之数据类型 (数值 Number)
Jan 18 Javascript
jQuery+Ajax+PHP+Mysql实现分页显示数据实例讲解
Sep 27 Javascript
详解页面滚动值scrollTop在FireFox与Chrome浏览器间的兼容问题
Dec 03 Javascript
Javascript技术栈中的四种依赖注入小结
Feb 27 Javascript
jquery设置表单元素为不可用的简单代码
Jul 04 Javascript
node.js实现的装饰者模式示例
Sep 06 Javascript
vue实现某元素吸顶或固定位置显示(监听滚动事件)
Dec 13 Javascript
功能完善的小程序日历组件的实现
Mar 31 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和数据库结合的一个简单的web实例 代码分析 (php初学者)
2011/07/28 PHP
php中的路径问题与set_include_path使用介绍
2014/02/11 PHP
跨浏览器的 mouseenter mouseleave 以及 compareDocumentPosition的使用说明
2010/05/04 Javascript
IE6浏览器下resize事件被执行了多次解决方法
2012/12/11 Javascript
简单实用的全选反选按钮例子
2013/10/18 Javascript
Javascript实现飞动广告效果的方法
2015/05/25 Javascript
跟我学习javascript的arguments对象
2015/11/16 Javascript
JSP基于Bootstrap分页显示实例解析
2016/06/12 Javascript
easyui tree带checkbox实现单选的简单实例
2016/11/07 Javascript
JavaScript使用简单正则表达式的数据验证功能示例
2017/01/13 Javascript
js css自定义分页效果
2017/02/24 Javascript
JavaScript高阶函数_动力节点Java学院整理
2017/06/28 Javascript
原生JS使用Canvas实现拖拽式绘图功能
2019/06/05 Javascript
layui数据表格跨行自动合并的例子
2019/09/02 Javascript
微信小程序 自定义复选框实现代码实例
2019/09/04 Javascript
Vue 实现一个命令式弹窗组件功能
2019/09/25 Javascript
JS数组方法slice()用法实例分析
2020/01/18 Javascript
[27:53]2014 DOTA2华西杯精英邀请赛 5 24 NewBee VS iG
2014/05/26 DOTA
python爬取w3shcool的JQuery课程并且保存到本地
2017/04/06 Python
python利用百度AI实现文字识别功能
2018/11/27 Python
Python 安装 virturalenv 虚拟环境的教程详解
2020/02/21 Python
Python request操作步骤及代码实例
2020/04/13 Python
Python入门基础之数字字符串与列表
2021/02/01 Python
python装饰器代码深入讲解
2021/03/01 Python
Css3新特性应用之视觉效果实例
2016/12/12 HTML / CSS
澳洲国民品牌乡村路折扣店:Country Road & Trenery Outlet
2018/04/19 全球购物
全球速卖通俄罗斯站:AliExpress俄罗斯
2019/06/17 全球购物
Sperry澳大利亚官网:源自美国帆船鞋创始品牌
2019/07/29 全球购物
文秘专业自荐信
2013/10/14 职场文书
新品发布会策划方案
2014/06/08 职场文书
社区爱国卫生月活动总结
2014/06/30 职场文书
学习十八大的心得体会
2014/09/12 职场文书
党委班子纠正“四风”问题整改措施
2014/10/28 职场文书
求职导师推荐信范文
2015/03/27 职场文书
2016学习雷锋精神活动倡议书
2015/04/27 职场文书
VUE使用draggable实现组件拖拽
2022/04/06 Vue.js