Vue+Koa2+mongoose写一个像素绘板的实现方法

GitHub: server | 前端

为什么是绘板:

作为一名前端,总会有意无意接触到 NodeJS 、有意无意会去看文档、有意无意会注意到框架,但真当需要我们需要在工作中善用它时,多半还是要感叹一句“纸上得来终觉浅”。所以一周前我决定进行一个实践尝试,希望能把以往无意中学到的知识融汇贯通,最终选择把以前的一个画板 Demo 重写并添加 server 端。

技术栈

[vue + vuex + vue-router] 页面渲染 + 数据共享 + 路由跳转

[axios] 以 Promise 的方式使用 HTTP 请求

[stylus] CSS 预处理

[element-ui] UI 库

[Webpack] 打包上面这些东西

[koa 2 & koa-generator] NodeJS 框架和框架脚手架

[mongodb & mongoose] 数据库和操作数据库的库

[node-canvas] 服务端数据副本记录

[Socket.io] 实时推送

[pm2] Node 服务部署

[nginx] 部署静态资源访问服务(HTTPS),代理请求

[letsencrypt] 生成免费的 HTTPS 证书

Webpack 之所以也被列出来,是因为本项目作为项目 luwuer.com 的一个模块,需要 webpack 来实现独立打包

node-canvas

安装

node-canvas 是我目前遇到过最难安装的依赖,以至于我根本不想在 Windows 下安装他,它的功能依赖很多系统下默认不存在的包,在 Github 上也能看到很多 issue 的标签是 installation help。以 CentOS 7 纯净版为例,在安装它之前你需要安装以下这些依赖,值得注意的是 npm 文档上提供的命令没有 cairo 。

# centos 前置条件 sudo yum install gcc-c++ cairo cairo-devel pango-devel libjpeg-turbo-devel giflib-devel # 安装本体 yarn add canvas -D

还有一个不明所以的坑,如果前置条件准备就绪后,安装本体仍然一直卡取包这一步(不报错),此时需要单独更新一下 npm

使用示例

参考文档很容易就能掌握基本用法,下方例子中先取到像素点数据生成 ImageData ,然后通过 putImageData 把历史数据画到 canvas 。

const { createCanvas, createImageData } = require('canvas') const canvas = createCanvas(canvasWidth, canvasHeight) const ctx = canvas.getContext('2d') // 初始化 const init = callback => { Dot.queryDots().then(data => { let imgData = new createImageData( Uint8ClampedArray.from(data), canvasWidth, canvasHeight ) // 移除 Smooth ctx.mozImageSmoothingEnabled = false ctx.webkitImageSmoothingEnabled = false ctx.msImageSmoothingEnabled = false ctx.imageSmoothingEnabled = false ctx.putImageData(imgData, 0, 0, 0, 0, canvasWidth, canvasHeight) successLog('canvas render complete !') callback() }) }

Socket.io

本项目在设计上有两个必须用到推送的地方,一是其他用户的建点信息,二是所有用户发送的聊天消息。

client

// socket.io init // transports: [ 'websocket' ] window.socket = io.connect(window.location.origin.replace(/https/, 'wss')) // 接收图片 window.socket.on('dataUrl', data => { this.imageObject.src = data.url this.loadInfo.push('渲染图像...') this.init() }) // 接收其他用户建点 window.socket.on('newDot', data => { this.saveDot( { x: data.index % this.width, y: Math.floor(data.index / this.width), color: data.color }, false ) }) // 接收所有人的最新推送消息 window.socket.on('newChat', data => { if (this.msgs.length === 50) { this.msgs.shift() } this.msgs.push(data) })

server /bin/www

let http = require('http'); let io = require('socket.io') let server = http.createServer(app.callback()) let ws = io.listen(server) server.listen(port) ws.on('connection', socket => { // 建立连接的 client 加入房间 chatroom ,为了下方可以广播 socket.join('chatroom') socket.emit('dataUrl', { url: cv.getDataUrl() }) socket.on('saveDot', async data => { // 推送给其他用户,即广播 socket.broadcast.to('chatroom').emit('newDot', data) saveDotHandle(data) }) socket.on('newChat', async data => { // 推送给所有用户 ws.sockets.emit('newChat', data) newChatHandle(data) }) })

letsencrypt

申请证书

# 获得程序 git clone https://github.com/letsencrypt/letsencrypt cd letsencrypt # 自动生成证书(环境安装完毕后会有两次确认),证书目录 /etc/letsencrypt/live/{输入的第一个域名} 我这里是 /etc/letsencrypt/live/www.luwuer.com/ ./letsencrypt-auto certonly --standalone --email html6@foxmail.com -d -d luwuer.com

自动续期

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/de9d4270f1c72cd66eebf08decae017a.html