标签 nodejs 下的文章

安装nodejs

sudo apt-get install nodejs
sudo apt-get install npm

全局安装包

sudo npm i -g cnpm

查看全局安装的包

npm list -g --depth 0

全局卸载包

sudo npm uninstall -g cnpm

清理缓存

npm cache clean -f

默认镜像太慢换淘宝镜像

npm config set registry https://registry.npm.taobao.org
现在我常使用cnpm包
检查配置是否成功
npm config get registry

为什么要在服务端装canvas? 因为并不是所有的客户端都能很好的支持canvas(比如微信小程序不能修改自定义字体),所以我们需要一个
能够在服务端生成图片的,然后将图片传输

安装node-canvas

1. 更新编译环境

sudo apt-get install libcairo2-dev libjpeg8-dev libpango1.0-dev libgif-dev build-essential g++ -y

2. 安装node-canvas

npm install -g canvas

3. 测试代码

var Canvas = require('canvas'),
    canvas = new Canvas(300, 200),
    ctx = canvas.getContext('2d'),
    fs = require('fs');
 
var out = fs.createWriteStream(__dirname + '/image.png')
  , stream = canvas.createPNGStream();
 
stream.on('data', function(chunk){
  out.write(chunk);
});
 
//在左边画正方形
ctx.fillStyle = '#A00'    
ctx.fillRect(0, 30,50,50);   
  
 
//在右边画正方形
ctx.fillStyle = '#aaa'    
ctx.fillRect(50, 30, 50, 50);
 
//画文字
ctx.fillStyle = "#000";
ctx.font = "20px Arial";
ctx.fillText("Hello World", 0, 20);
 
//画一个圆
ctx.beginPath();
ctx.arc(30, 110, 20, 0, 2*Math.PI);
ctx.stroke();
ctx.fillStyle = "green";                                                                                                                          
ctx.fill();
ctx.save();  

可能遇到的问题

如果你按上述方法操作,并且运行成功了。那便是极好的

1. 自定义字体

// You need to call it before the Canvas is created
Canvas.registerFont('comicsans.ttf', {family: 'Comic Sans'});

var canvas = new Canvas(500, 500),
  ctx = canvas.getContext('2d');

ctx.font = '12px "Comic Sans"';
ctx.fillText(250, 10, 'Everyone hates this font :(');
不过可能会发现Canvas.registerFont is not a function这是因为npm版本的没有这个函数。

所以你需要去找另一个github版https://github.com/chearon/node-canvas#12971f64a66b

git clone 下来

然后将Canvas = require('canvas')改成require('./node-canvas'),
var canvas = new Canvas(300, 200)改成var canvas = new Canvas.Canvas(300, 200)

2. Error: Cannot find module '../build/Release/canvas.node'

如果遇到这个问题,请cd进你的node-canvas目录执行npm install

如果还是不行,请执行npm install -g node-gyp

然后再cd项目目录执行node-gyp rebuild,then cd 进node-canvas同样执行node-gyp rebuild

如果成功则会出现

编译过程

示例代码

我的项目目录

.
├── 1.html
├── composer.json
├── font
├── fz.ttf
├── img
├── index.js
├── node-canvas
├── node_modules
├── package.json
└── package-lock.json

我的代码

var fs = require('fs'),path = require('path');
var http = require('http'),url = require("url");
var Canvas = require('./node-canvas'),Image = Canvas.Image;
var Fonts = [];
var filePath = path.resolve('./font');

let promise = new Promise(function(resolve, reject) {
  let i=0;
  fs.readdir(filePath,function(err,files){  
    if(err){  
      console.warn(err)  
    }else{
      files.forEach(function(filename){
        Canvas.registerFont(filePath + "/" + filename, {family: "font" + i});
        console.log(i);
        i++;
      });
    }
  });
  
});

promise.then(function() {
  console.log("ASDF");
  Fonts.forEach((Element) =>{
    console.log(Element);
  });
});

console.log('Hi!');


http.createServer(function (req, res) {
  var params = url.parse(req.url, true).query;
  var str = params.str + '\r',site = params.site;
  var row =  1,col = 15,width = 1500;
  row = str.length / 15 + 1;
  var fontsize = width/col;
  var height = fontsize * row + 200;
  if(height < 1000){height = 1000}
  var canvas = new Canvas.Canvas(width, height), ctx = canvas.getContext('2d')
  res.writeHead(200,{"Content-Type": "image/png"});
  ctx.fillStyle = '#FFF';
  ctx.fillRect(0,0,canvas.width, canvas.height);
  ctx.fillStyle = '#000';
  if(row < 2){
    let num = str.length
    fontsize = 1200 / num;
    ctx.font = fontsize + 'px "font'+ site +'"';
    ctx.fillText(str,( width - num * fontsize ) / 2, (height-fontsize)/2 -200 + fontsize);
  }
  else{
    ctx.font = fontsize + 'px "font'+ site +'"';
    for(let i = 0;i < row ; i++){
      ctx.fillText(str.substring(i*15,(i+1)*15), 0, fontsize*(i+1));
    }
  }
  
  fs.readFile(__dirname + '/img/brand.png', function(err, squid){
    if (err) throw err;
    img = new Image;
    img.src = squid;
    ctx.fillStyle = '#42b983';
    ctx.fillRect(0,canvas.height - 230,canvas.width, 230);
    ctx.drawImage(img, canvas.width - img.width / 2 - 50, canvas.height - img.height / 2 - 50, img.width / 2, img.height / 2);
    res.end(canvas.toBuffer());
  });
}).listen(8080);

效果展示

天地玄黄

首先,为什么我们需要这个?

因为微信小程序虽然可以可以绘制svg图片,但是在真机调试的时候却渲染不出来。所以我们需要一个工具(可以将svg转成微信小程序支持的canvas并绘制出来)。

我使用的是touch-wx + vs code 开发。

现已启用该开发模式.因为Ubuntu下经常编译不完整

Touch WX 是什么?

Touch WX

Touch WX是一套完全免费的微信小程序开发框架,包含丰富的UI控件用于官方组件的补充。与Touch UI开发方式很相似,也是通过VSCode编辑器+插件的方式开发,经过编译后输出小程序代码。
与其他小程序框架最主要的区别在于:Touch UI完全是基于小程序官方的自定义组件机制实现,输出的是小程序原始代码,而不是输出开发者完全无法阅读的编译代码。这样当遇到问题时,开发者可以很方便的定位问题所在,还可以基于输出的原始代码继续开发。
当你用Touch UI开发了H5应用,可以直接导入到Touch WX进行转换,稍作调整就能生成小程序。反之也同样,当你Touch WX开发了微信小程序,可以导出为Touch UI工程来生成H5应用。

Touch WX 的特点

Touch WX

我的理解

Touch WX 就是一个可以将特定的nodejs项目编译成微信小程序项目的框架

Touch WX更多操作

更多操作见http://www.touchui.io/touchui_doc_wx/

推荐大家看一下,或许会打开新世界的大门哦!

接下来,我默认你已经看了Touch WX的文档,并且拥有一定的nodejs基础

开始流程

安装parse-svg-path

npm install parse-svg-path --save

引入parse-svg-path

var parse = require('parse-svg-path')

使用parse-svg-path

parse(d)

d为svg中的path值

不了解svg?

请转http://www.w3school.com.cn/svg/svg_intro.asp

如何获得path值?

var options = {
            url:"svg的URL",
            success:function(res){
              const ctx = wx.createCanvasContext('myCanvas')
              ctx.setFillStyle('black')
              var match = res.data.match(/d="(.*?)"/);
              var d = match[1];
              console.log(d);
            }
    }
    wx.request(options); 
上图中d就是path值,我这里使用的是正则表达式查找,而且只有一个path,如不一样,请自行modify

解析后的值

console.log(parse(d));

效果展示

解析之后是一系列的操作序列数组

绘制图形

根据一系列的操作,找到对应的微信小程序绘制API,进行绘制
parse(d).forEach(function (element){
                if(element[0] == "M"){
                  ctx.moveTo(element[1], element[2])
                }else if(element[0] == "Q"){
                  ctx.quadraticCurveTo(element[1], element[2], element[3], element[4])
                }
              });
因为我这里只有M,Q操作所以我只用了两个API,可根据实际情况自行拓展

实例代码

display.wx

<template>
  <view class='page'>
    <canvas canvas-id="myCanvas" style="border: 1px solid;"/>
    <!-- <view class='content'><text class="zhuan" style="font-size:{{fontSize}}pt">{{display}}</text> -->
  <!-- </view> -->
</view>
</template>

<script>
var parse = require('parse-svg-path')
export default {
  config: {
    navigationBarTitleText: '效果展示'
  },
  data: {},
  onLoad: function (options) {
    var str = options.display;
    if(str != null){
      try {
        str=decodeURI(str);
        wx.setStorageSync('display', str)
        console.log("接受到的str:"+str);
      } catch (e) {
        console.log("设置diaplay值错误")
      }
    }  
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady: function () {
  
  },
  saveTemp(){
    console.log("fdsaf");
    wx.canvasToTempFilePath({
      canvasId: 'myCanvas',
      fail: function(res) {
        console.log(res);
      },
      success: function(res) {
        console.log(res.tempFilePath)
        setTimeout(function(){wx.saveImageToPhotosAlbum({
          filePath:res.tempFilePath,
          fail:function(res){
            console.log(res);
          }
          
          });},5000)
        
      },
       
    })
  },
  /**
   * 生命周期函数--监听页面显示
   */
  onShow: function () {
    var that = this;
    
    var options = {
            url:"http://mp.thinkmoon.cn:39999?str=我&site=0",
            success:function(res){
              const ctx = wx.createCanvasContext('myCanvas')
              ctx.setFillStyle('black')
              var match = res.data.match(/d="(.*?)"/);
              var d = match[1];
              console.log(parse(d))
              parse(d).forEach(function (element){
                if(element[0] == "M"){
                  ctx.moveTo(element[1], element[2])
                }else if(element[0] == "Q"){
                  ctx.quadraticCurveTo(element[1], element[2], element[3], element[4])
                }
              });
              ctx.fill();
              ctx.draw(false,()=>{setTimeout(() => {that.saveTemp()},5000);});
            }
    }
    wx.request(options); 
    // wx.getStorage({
    //   key: 'display',
    //   success: function (res) {
    //     console.log("display的值为" + res.data)
    //     that.setData({
    //       display: res.data,
    //       fontSize: wx.getStorageSync('pt')
    //     })
    //   }
    // })
  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide: function () {
  
  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload: function () {
  
  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh: function () {
  
  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom: function () {
  
  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage: function () {
    var str = this.data.display;
    var pages = getCurrentPages()    //获取加载的页面
    var currentPage = pages[pages.length - 1]    //获取当前页面的对象
    var url = currentPage.route
    var inUrl = url + "?display=" + encodeURI(str);
    console.log("分享的链接为"+inUrl);
    return {
      title: '您的好友给您分享了一段篆文',
      path: inUrl,
      success: function (res) {
        // 转发成功
      },
      fail: function (res) {
        // 转发失败
      }
    }
  }
}
</script>

<style lang="less">
.content{
  text-align: center;
}
canvas{
  width: 256px;
  height: 256px;
}

</style>

后记

我这个实例本来是将svg转canvas绘制出来,再转图片,下载到本地的。但是因为draw()函数是异步的所以需要等待。才可以下载成功,否则会出现一片黑的情况,总之感觉各种麻烦。再加上画布的大小难以设置。后我还是选择在服务端生成图片再转发过来。

参考文献

  1. SVG简介
  2. Touch WX开发文档
  3. 微信开发文档Canvas