专栏首页h5electron-vue仿微信桌面端|electron聊天实例
原创

electron-vue仿微信桌面端|electron聊天实例

electron-vchat客户端聊天实例是基于electron+vue+vuex+Node+vue-router等技术开发的仿制微信pc桌面聊天项目。实现了消息发送 /表情(光标处插入表情),图片 /视频预览,拖拽上传 /粘贴截图发送 /微信 dll 截图,右键菜单、朋友圈 /红包 /换肤等功能。

技术框架

  • 框架技术:electron + electron-vue + vue
  • 状态管理:Vuex
  • 地址路由:Vue-router
  • 字体图标:阿里 iconfont 字体图标库
  • 弹窗插件:wcPop
  • 打包工具:electron-builder
  • 图片组件:vue-photo-preview
  • 视频组件:vue-video-player

公共组件引入配置

/**
 * @Desc   公共及全局组件配置
 * @about  Q:282310962  wx:xy190310
 */

// 引入公共组件
import winBar from './components/winbar'
import sideBar from './components/sidebar'

// 引入公共样式
import './assets/fonts/iconfont.css'
import './assets/css/reset.css'
import './assets/css/layout.css'

// 引入弹窗wcPop
import wcPop from './assets/js/wcPop/wcPop'
import './assets/js/wcPop/skin/wcPop.css'

// 引入图片预览组件vue-photo-preview
import photoView from 'vue-photo-preview'
import 'vue-photo-preview/dist/skin.css'

// 引入视频播放组件vue-video-player
import videoPlayer from 'vue-video-player'
import 'video.js/dist/video-js.css'

const install = Vue => {
    // 注册组件
    Vue.component('win-bar', winBar)
    Vue.component('side-bar', sideBar)

    // 应用实例
    Vue.use(photoView, {
        // loop: false, //循环
        // fullscreenEl: true, //全屏
        // arrowEl: true, //左右按钮
    })
    Vue.use(videoPlayer)
}

export default install

Electron 是由 Github 开发,用 HTML,CSS 和 JavaScript 来构建跨平台桌面应用程序的一个开源库。更多的介绍及搭建项目环境可去官网查阅。

https://electronjs.org/

https://electron.org.cn/vue/index.html

https://github.com/SimulatedGREG/electron-vue

electron主进程创建窗口

通过electron提供的BrowserWindow对象创建窗体,electron-vue构建项目后,主进程入口页面是src/main/index.js

import { BrowserWindow, app, ipcMain, Tray, Menu } from 'electron'

// 引入主线程公共配置
import Common from './utils/common'

/**
 * Set `__static` path to static files in production
 * https://simulatedgreg.gitbooks.io/electron-vue/content/en/using-static-assets.html
 */
if (process.env.NODE_ENV !== 'development') {
  global.__static = require('path').join(__dirname, '/static').replace(/\\/g, '\\\\')
}

let mainWin
let tray
let forceQuit = false
let logined = false

/**
 * 创建主窗口
 */
function createMainWin() {
  mainWin = new BrowserWindow({
    // 背景颜色
    // backgroundColor: '#ebebeb',
    width: Common.WIN_SIZE_MAIN.width,
    height: Common.WIN_SIZE_MAIN.height,
    title: Common.WIN_TITLE,
    useContentSize: true,
    autoHideMenuBar: true,
    // 无边框窗口
    frame: false,
    resizable: true,
    // 窗口创建的时候是否显示. 默认值为true
    show: false,
    webPreferences: {
      // devTools: false,
      webSecurity: false
    }
  })

  mainWin.setMenu(null)
  mainWin.loadURL(Common.WIN_LOAD_URL())

  mainWin.once('ready-to-show', () => {
    mainWin.show()
    mainWin.focus()
  })

  // 判断最小化到系统托盘
  mainWin.on('close', (e) => {
    if(logined && !forceQuit) {
      e.preventDefault()
      mainWin.hide()
    }else {
      mainWin = null
      app.quit()
    }
  })

  initialIPC()
}

app.on('ready', createMainWin)

app.on('activate', () => {
  if(mainWin === null) {
    createMainWin()
  }
})

app.on('before-quit', () => {
  forceQuit = true
})

app.on('window-all-closed', () => {
  if(process.platform !== 'darwin') {
    app.quit()
  }
})

...

electron实现系统托盘图标及闪烁效果

托盘图标闪烁是通过两个ico文件设置时间戳交替切换

/**
 * electron创建系统托盘图标
 */
let flashTrayTimer = null
let trayIco1 = `${__static}/icon.ico`
let trayIco2 = `${__static}/empty.ico`
let apptray = {
  // 创建托盘图标
  createTray() {
    tray = new Tray(trayIco1)
    const menu = Menu.buildFromTemplate([
      {
        label: '打开主界面',
        icon: `${__static}/tray-ico1.png`,
        click: () => {
          if(mainWin.isMinimized()) mainWin.restore()
          mainWin.show()
          mainWin.focus()
          
          this.flashTray(false)
        }
      },
      {
        label: '关于',
      },
      {
        label: '退出',
        click: () => {
          if(process.platform !== 'darwin') {
            mainWin.show()
            // 清空登录信息
            mainWin.webContents.send('clearLoggedInfo')
            
            forceQuit = true
            mainWin = null
            app.quit()
          }
        }
      },
    ])
    tray.setContextMenu(menu)
    tray.setToolTip('electron-vchat v1.0.0')

    // 托盘点击事件
    tray.on('click', () => {
      if(mainWin.isMinimized()) mainWin.restore()
      mainWin.show()
      mainWin.focus()

      this.flashTray(false)
    })
  },
  // 托盘图标闪烁
  flashTray(bool) {
    let hasIco = false

    if(bool) {
      if(flashTrayTimer) return
      flashTrayTimer = setInterval(() => {
        tray.setImage(hasIco ? trayIco1 : trayIco2)
        hasIco = !hasIco
      }, 500)
    }else {
      if(flashTrayTimer) {
        clearInterval(flashTrayTimer)
        flashTrayTimer = null
      }

      tray.setImage(trayIco1)
    }
  },
  // 销毁托盘图标
  destroyTray() {
    this.flashTray(false)
    tray.destroy()
    tray = null
  }
}

renderer渲染进程里面的页面写法和vue一样,这里不作过多介绍了。

electron实现自定义顶部最大/小化、关闭按钮、无外框窗口

electron 中配置 frame: false 后,就能去除原窗体顶部,原先的顶部操作栏就没有了,需要自定义配置。

// 置顶窗口
handleFixTop() {
	this.isAlwaysOnTop = !this.isAlwaysOnTop
	currentWin.setAlwaysOnTop(this.isAlwaysOnTop)
},

// 最小化
handleMin() {
	currentWin.minimize()
},

// 最大化
handleMax() {
	if(!currentWin.isMaximizable()) return
	if(currentWin.isMaximized()) {
		currentWin.unmaximize()
		this.SET_WINMAXIMIZE(false)
	}else {
		currentWin.maximize()
		this.SET_WINMAXIMIZE(true)
	}
},

项目中使用的是局部拖动css属性 -webkit-app-region: drag

注意:默认设置-webkit-app-region: drag后,下面的元素不能点击操作,可通过设置需点击元素no-drag即可。

electron实现微信编辑器光标处插入表情+截图功能

采用vue中设置div可编辑contenteditable="true" 自定义双向绑定v-model ,定位光标处插入动态表情。

每次插入内容光标定位到最后可参考

function setLastCaret(obj) {
	console.log(obj)
	console.log(window.getSelection)
	console.log(document.selection)
	if (window.getSelection) { //ie11 10 9 ff safari
		obj.focus(); //解决ff不获取焦点无法定位问题
		var range = window.getSelection(); //创建range
		range.selectAllChildren(obj); //range 选择obj下所有子内容
		range.collapseToEnd(); //光标移至最后
	} else if (document.selection) { //ie10 9 8 7 6 5
		var range = document.selection.createRange(); //创建选择对象
		//var range = document.body.createTextRange();
		range.moveToElementText(obj); //range定位到obj
		range.collapse(false); //光标移至最后
		range.select();
	}
}

截图功能是通过Node中的execFile方法执行exe文件,exe调用同级目录下的微信截图dll,调出截图工具

// 可编辑div contenteditable中粘贴发送图片
submitPasteImage{
	let that = this
	this.$refs.editor.addEventListener('paste', function(e) {
		let cbd = e.clipboardData
		let ua = window.navigator.userAgent
		if(!(e.clipboardData && e.clipboardData.items)) return
		
		if(cbd.items && cbd.items.length === 2 && cbd.items[0].kind === "string" && cbd.items[1].kind === "file" &&
			cbd.types && cbd.types.length === 2 && cbd.types[0] === "text/plain" && cbd.types[1] === "Files" &&
			ua.match(/Macintosh/i) && Number(ua.match(/Chrome\/(\d{2})/i)[1]) < 49){
			return;
		}
		for(var i = 0; i < cbd.items.length; i++){
			var item = cbd.items[i];
			console.log(item);
			console.log(item.kind);
			if(item.kind == "file"){
				var blob = item.getAsFile();
				if(blob.size === 0){
					return;
				}
				// 插入图片记录
				var reader = new FileReader();
				reader.readAsDataURL(blob);
				reader.onload = function(){
					var _img = this.result;

					// ***返回图片给父组件
					that.$emit('pasteFn', _img)
				}
			}
		}
	})
},

这里也不作过多详细介绍,之前有过这方面的分享介绍

https://segmentfault.com/a/1190000021510872

基于electron+vue开发聊天实例项目 就介绍差不多了,希望能有些帮助~~ 🐀🐀

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 支付宝小程序弹窗插件开发|仿微信/android/ios弹窗效果

    支付宝小程序弹窗交互组件和微信小程序弹窗功能都差不多,对功能有比较多的限制,尤其想要实现丰富一些的弹窗场景就只能自己写组件实现了。

    andy2018
  • 微信小程序自定义模态弹窗(wcPop)|多种弹窗样式

    在平时微信小程序开发中,弹窗应用场景还是蛮广泛的,如果你刚好项目开发中用到的话,希望对你有用~

    andy2018
  • h5高仿微信web网页版|仿微信聊天项目

    https://blog.csdn.net/xiaoyan_2015/article/details/81750894

    andy2018
  • C++多态

    当类存在虚函数时,编译器会为该类维护一个表,这个表就是虚函数表(vtbl),里面存放了该类虚函数的函数指针。在构造类的时候增加一个虚表指针(vptr)指向对应的...

    用户2929716
  • Python花式编程案例集锦(8):判断吉祥数字

    问题描述:在有些文化中,认为含有8的数字是吉祥数字,能给自己带来好运。要求编写一个函数测试给定的数字是否为吉祥数字。 参考代码: ? 代码运行没有输出,说明两种...

    Python小屋屋主
  • 入门 | 从感知机到深度神经网络,带你入坑深度学习

    机器之心
  • 一种室内定位免采集室内店铺Wi-Fi指纹填充算法

    对于目前最主流的室内Wi-Fi指纹定位技术而言,采集Wi-Fi指纹的覆盖度和新鲜度是决定定位精度最重要的因素。受到成本和导航需求等因素的限制,腾讯地图定位平台目...

    腾讯位置服务
  • Java泛型你看这篇文章就对了

    泛型是Java中一个非常重要的知识点,在Java集合类框架中泛型被广泛应用。本文我们将从零开始来看一下Java泛型的设计,将会涉及到通配符处理,以及让人苦恼的类...

    JAVA葵花宝典
  • Salesforce物联网云(IOT)介绍

    准备好了解物联网世界了吗?这个世界可能是由通过电子学、传感器和软件嵌入的联网的设备和其他物体组成的,物联网的世界是由健身追踪器、应用、汽车、路由器以及无数个其他...

    臭豆腐
  • 新人必备!15个常用EXCEL函数

    本文实际涵盖了15个Excel常用函数,但是按照分类只分了十类。 很难说哪十个函数就绝对最常用,但这么多年来人们的经验总结,一些函数总是会重复出现的。 这些函数...

    CDA数据分析师

扫码关注云+社区

领取腾讯云代金券