小程序-canvas绘图并保存到系统相册

栏目: Html5 · 发布时间: 5年前

内容简介:开始实现之前先上个效果图/datas/common.js.wxml

开始实现之前先上个效果图

小程序-canvas绘图并保存到系统相册

tips

  1. 网络图片需先配置download域名,可通过wx.getImageInfo转为临时路径;
  2. 个人习惯问题,我习惯使用async-await语法,所以需要引入regenerator这个库,使用方式可网上查。

一、封装通用微信api返回为Promise对象

/datas/common.js

// 封装获取微信图片信息。
export const getWxImageInfo = (imgPath) => {
  return new Promise((resolve, reject) => {
    wx.getImageInfo({
      src: imgPath,
      success: res => {
        resolve(res)
      },
      fail: res => {
        reject(res)
      }
    })
  })
}

// 封装获取节点选择器信息
export const getSelectQurey = (queryStr) => {
  return new Promise(resolve => {
    var query = wx.createSelectorQuery();
    query.select(queryStr).boundingClientRect();
    query.exec(res => {
      resolve(res)
    })
  })
}

// 封装把画布导出生成指定大小的图片
export const canvasToTempFilePath = (width, height, canvasId, fileType = 'jpg') => {
  return new Promise((resolve, reject) => {
    wx.canvasToTempFilePath({
      width,
      height,
      canvasId,
      fileType,
      success: res => {
        resolve(res)
      },
      fail: res => {
        reject(res)
      }
    })
  })
}

// 封装保存图片到系统相册
export const saveImageToPhotosAlbum = (filePath) => {
  return new Promise((resolve, reject) => {
    wx.saveImageToPhotosAlbum({
      filePath,
      success: res => {
        resolve(res)
      },
      fail: res => {
        reject(res)
      }
    })
  })
}
复制代码

二、视图的实现

.wxml

<view class="icon-download" catchtap="getCanvas">点击生成图片</view>

<!-- 二维码大图 -->
<view class='shade' wx:if="{{isShowCanvas}}">
  <view class='qr-code'>
    <canvas class='qr-canvas' canvas-id="qrCanvas" id="qrCanvas"></canvas>
    <view class='qr-btn'>
      <view class='qr-btn-save' catchtap='saveImageToPhotosAlbumFunc'>保存图片,分享到朋友圈</view>
      <view class='qr-btn-cancel' catchtap='hideCanvas'>取消</view>
    </view>
  </view>
</view>
<!-- 二维码大图.end -->

复制代码

.wxss

/* 查看大图 */

.shade {
  width: 100%;
  height: 100%;
  background-color: rgba(240, 235, 235, 0.5);
  position: fixed;
  z-index: 100;
  top: 0;
  left: 0;
}

.qr-code {
  width: 600rpx;
  height: 1000rpx;
  background-color: #fff;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%); /* margin: 30rpx auto; */
}

.qr-canvas {
  display: block;
  background-color: #fff;
  margin: 0 auto;
  width: 600rpx;
  height: 900rpx;
}

.qr-btn {
  width: 600rpx;
  height: 100rpx;
  line-height: 100rpx;
  margin: 0 auto;
  font-size: 28rpx;
  color: #fff;
  display: flex;
  background-color: #658dc5;
}

.qr-btn-save {
  flex: 0 0 500rpx;
  text-align: center;
  border-right: 1rpx solid #fff;
}

.qr-btn-cancel {
  text-align: center;
  flex: 0 0 100rpx;
}

复制代码

三、创建canvas并保存到系统相册

tips

  1. 商品图是正方形的,所以这里商品图的宽高都用canvas的宽
  2. 文字不能换行,这里只是简单的处理了一下
  3. 注意: wx.canvasToTempFilePath(Object object, Object this) 这个的使用,文档有一句话需要注意的:“把当前画布指定区域的内容导出生成指定大小的图片。在 draw() 回调里调用该方法才能保证图片导出成功。”
const app = getApp()
const regeneratorRuntime = app.globalData.regeneratorRuntimeconst
const util = require('../../utils/util.js')
import {
  getSelectQurey,
  getWxImageInfo,
  canvasToTempFilePath,
  saveImageToPhotosAlbum
} from '../../datas/common.js'

Page({
  data: {
    isShowCanvas: false, // 是否显示canvas    
    wxaCode: 'https://xxx..jpg', // 商品小程序码
    goodsImageUrl: 'https://xxx..jpg', // 商品图片    
    canvasTempFilePath: '', // canvas导出生成图片的临时路径  
  },

  // 点击显示要生成的canvas  
  getCanvas(e) {
    if (!this.data.wxaCode) {
      util.showToast('二维码生成失败');
      return;
    }
    this.setData({
      isShowCanvas: true
    }, () => {
      this.createCanvas();
    })
  },

  // 隐藏canvas  
  hideCanvas() {
    this.setData({
      isShowCanvas: false
    })
  },

  // 创建canvas  
  async createCanvas() {
    wx.showLoading({
      title: '图片生成中...'
    })
    const _this = this

    // 创建节点选择器    
    const res = await getSelectQurey('#qrCanvas');

    // canvas的宽高    
    const cvWidth = res[0].width;
    const cvHeight = res[0].height;
    const cvSubValue = cvHeight - cvWidth
    const qrWidth = cvSubValue / 1.5
    const qrMargin = (cvSubValue - qrWidth) / 2
    const qrX = cvWidth - qrWidth - qrMargin / 2
    const qrY = cvWidth + qrMargin
    const shopNameY = cvWidth + cvSubValue - qrWidth

    // 二维码网络图片转临时路径    
    let qrImagePath = '';
    try {
      const wxaCode = _this.data.wxaCode;
      const qrImage = await getWxImageInfo(wxaCode);
      qrImagePath = qrImage.path
    } catch (e) {
      wx.hideLoading();
      this.hideCanvas();
      util.showToast('二维码生成失败');
      return;
    }

    // 商品网络图片转临时路径    
    let goodsImagePath = '/images/default_goods.png';
    const goodsImage = _this.data.goodsImageUrl;
    if (goodsImage) {
      const goodsImageRes = await getWxImageInfo(goodsImage);
      goodsImagePath = goodsImageRes.path;
    }

    // 创建canvas    
    var ctx = wx.createCanvasContext('qrCanvas', _this);

    // 设置背景    
    ctx.setFillStyle('#fff');
    ctx.fillRect(0, 0, cvWidth, cvHeight);

    // 设置商品图片 商品图宽高是一样的    
    ctx.drawImage(goodsImagePath, 0, 0, cvWidth, cvWidth);

    // 设置二维码图片    
    ctx.drawImage(qrImagePath, qrX, qrY, qrWidth, qrWidth);

    // 设置店铺名称    
    const shopName = '我是店铺名称';
    ctx.setFillStyle('black')
    ctx.setFontSize(16)
    ctx.setTextAlign('left')
    ctx.fillText(shopName, 10, shopNameY, cvWidth - qrWidth);

    // 设置商品名称 文字不能换行,这里只是简单的处理了一下    
    const goodsName = '一个名字很长很长的商品就问你怕不怕';
    let goodsName1 = '';
    let goodsName2 = '';
    ctx.setFillStyle('black')
    ctx.setFontSize(14)
    ctx.setTextAlign('left')
    if (goodsName.length <= 10) {
      ctx.fillText(goodsName, 10, shopNameY + 30, cvWidth - qrWidth);
    } else
    if (goodsName.length > 10 && goodsName.length <= 22) {
      goodsName1 = goodsName.substring(0, 10);
      goodsName2 = goodsName.substring(10);
      ctx.fillText(goodsName1, 10, shopNameY + 30, cvWidth - qrWidth);
      ctx.fillText(goodsName2, 10, shopNameY + 50, cvWidth - qrWidth);
    } else {
      goodsName1 = goodsName.substring(0, 10);
      goodsName2 = goodsName.substring(10, 22) + '...';
      ctx.fillText(goodsName1, 10, shopNameY + 30, cvWidth - qrWidth);
      ctx.fillText(goodsName2, 10, shopNameY + 50, cvWidth - qrWidth);
    }

    // 设置提示    
    const tipText = '长按识别小程序,马上下单!';
    ctx.setFillStyle('gray')
    ctx.setFontSize(8)
    ctx.setTextAlign('center')
    ctx.fillText(tipText, cvWidth / 2, cvHeight - 10);

    // 完成    
    ctx.draw(false, () => {
      wx.hideLoading();
      _this.canvasToTempFilePathFunc(cvWidth, cvHeight, 'qrCanvas')
    });
  },

  // 把当前画布指定区域的内容导出生成指定大小的图片  
  async canvasToTempFilePathFunc(cvWidth, cvHeight, qrCanvas) {
    try {
      let res = await canvasToTempFilePath(cvWidth, cvHeight, qrCanvas);
      this.setData({
        canvasTempFilePath: res.tempFilePath
      });
    } catch (error) {
      console.log(error);
      util.showToast(error.errMsg);
    }
  },

  // 保存图片到本地  
  async saveImageToPhotosAlbumFunc() {
    try {
      let res = await saveImageToPhotosAlbum(this.data.canvasTempFilePath);
      console.log(res);
      this.hideCanvas();
      util.showToast('图片保存成功');
    } catch (err) {
      console.log(err);
    }
  }
})
复制代码

写得比较简单,因为主要是方便自己做记录的,所以也没有考虑到过多的使用场景。


以上所述就是小编给大家介绍的《小程序-canvas绘图并保存到系统相册》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Shallows

The Shallows

Nicholas Carr / W. W. Norton & Company / 2010-6-15 / USD 26.95

"Is Google making us stupid?" When Nicholas Carr posed that question, in a celebrated Atlantic Monthly cover story, he tapped into a well of anxiety about how the Internet is changing us. He also crys......一起来看看 《The Shallows》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具