了解更多企业以及行业的动态

立即咨询
您现在所在的位置是: 首页> 资讯> 行业动态
芜湖小程序定制:Web函数自定义实战:构建图象处理函数服务端,客户端缝合方案|昱远信息系统开发
发布:2022-06-07 浏览:99

icebreaker教你定制小程序代码前言

与普通二维码相比,小程序菊花码辨识度高,微信扫一扫即可。

默认情况下,我们可以自定义生成代码的参数,路径,大小,自动或手动配置线条颜色,背景颜色是否透明。

但是,这些配置项往往无法满足我们的定制需求。

例如,我们需要在不破坏小程序代码可识别性的情况下更换中间的标志。怎么做?接下来笔者就一步步教大家。

整理思路

我们首先要了解问题的本质。这实际上是一个图像处理问题,这个工作可以由服务器端和客户端来完成。

所以有2个选项:

服务器生成代码并拼接结果的服务器端处理方案。具体怎么做,有兴趣的同学,可以查看作者的文章Web函数自定义镜像实战:构建图像处理函数

定制微信小程序价格_芜湖小程序定制_定制小程序

服务器生成代码,客户端拼接方案。这就是这篇文章特别提到的。

注:小程序代码一般由服务器调用微信api接口生成

云调用——最简单的代码生成解决方案

众所周知,微信小程序环境中的wxacode.getUnlimited有两种生成方式定制小程序,一种是HTTPS调用 外包小程序定制 ,一种是云调用。

其中 小程序开发系统 ,云调用作为针对场景定制的Serverless解决方案定制小程序,往往可以为我们的开发带来效率提升。我们接下来快速部署一个 getWxacodeUnlimit 函数,为我们提供测试资料。

getWxacodeUnlimit/index.js:

import cloud from 'wx-server-sdk'
cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})
export async function main (event, context) {
  const { scene = '', page, width = 430, autoColor, lineColor, isHyaline } = event
  const result = await cloud.openapi.wxacode.getUnlimited({
    scene,
    page,
    width,
    autoColor,
    lineColor,
    isHyaline
  })
  return result
}
// 笔者使用了打包工具, 大家想直接跑,把 esm 转化为 cjs 即可 

getWxacodeUnlimit/config.json:

{
  "permissions": {
    "openapi": ["wxacode.getUnlimited"]
  }
}

定制小程序_芜湖小程序定制_定制微信小程序价格

有了上面2个代码块,我们的测试功能就部署好了。

将返回的缓冲区转换为本地临时图像

const suffixMap = {
  'image/jpeg': 'jpeg',
  ...
}
export function getPath(filename = 'tmp', contentType = 'image/jpeg') {
  return `${wx.env.USER_DATA_PATH}/${filename}.${suffixMap[contentType] || 'jpeg'}`
}
export function writeFile(buff, contentType = 'image/jpeg', filename = 'tmp') {
  return new Promise((resolve, reject) => {
    const fsm = wx.getFileSystemManager()
    const filePath = getPath(filename, contentType)
    fsm.writeFile({
      filePath,
      data: buff,
      encoding: 'binary',
      success() {
        resolve(filePath)
      },
      fail(error) {
        reject(error)
      }
    })
  })
}
....
// 在需要用到的地方直接
try {
  loading('生成中')
  const result = await getQrcode(scene, option) // 云调用封装function
  return await writeFile(result.buffer, result.contentType, scene) // : string
} catch (e) {
  console.error(e)
} finally {
  loaded()
}

客户端图像处理

说到客户端的图片处理,就不得不提canvas这个原生组件,所以我们只需要用它来衡量一下,把小程序代码中间的Logo部分替换成我们要自定义的图片即可。

测量

这里我们以默认的小程序代码大小 430px * 430px 为例。(为了简单易懂,本案例使用了这个分辨率的小程序代码,如果需要的分辨率不同,可以按比例计算裁剪。)

从图上的注释可以看出,在430px * 430px的分辨率下,上下左右边距为120px,可以计算出中间Logo圆的直径为190px,半径为为 95 像素。

芜湖小程序定制_定制微信小程序价格_定制小程序

这样你就可以轻松愉快地编写代码了。

用画布 2d 实现

1代小程序的api版本已经淘汰定制小程序,现在直接使用type="2d"版本。Api 文档在 MDN 上。

预标签和样式


<canvas
  :class="visible ? '': 'canvas offscreen'"
  type="2d"
  id="canvas"
  :style="{
  width:width+'rpx',
  height:height+'rpx'
  }"
>canvas>

// scss
.canvas.offscreen{ // 2个 class 选择器,增加优先级
  position: absolute;
  bottom: 0;
  left: -9999rpx;
  // 这叫物理离屏渲染,笑~
}

注意:您不能在画布上使用 hidden 或 display:none,它们将导致空白渲染。

核心js实现初始化画布实例和上下文

初始化画布实例和 ctx 上下文:

定制微信小程序价格_芜湖小程序定制_定制小程序

let canvas
let ctx
{...codes...}
onReady(){
  uni
    .createSelectorQuery()
    .in(this)  // 如果canvas在组件中,则需要加这一行
    .select('#canvas')
    .fields({
      node: true,
      size: true
    })
    .exec((res) => {
      if (res[0]) {
        this.canvas = canvas = res[0].node
        this.ctx = ctx = canvas.getContext('2d')
        // 下面可根据设备的 pixelRatio 自行按比例调整,此处为了演示方便,就直接赋值了。
        canvas.width = 430
        canvas.height = 430
      }
    })
}

第一次渲染 - 画布背景

对于第一次渲染,小程序代码作为图像传递到画布中。绘制背景:

async drawBackgroud (orginQrcodeUrl) {
  const [err, res] = await uni.getImageInfo({
    // 这里可以是远程地址(需要配置downloadUrl)
    // 也可以是本地地址(直接返回参数自己)
    // 甚至 cloud:// 前缀的云存储url也可以哟
    src: orginQrcodeUrl 
  })
  if (err) {
    throw err
  }
  const { path } = res
  const img = canvas.createImage()
  img.src = path
  await new Promise((resolve, reject) => {
    img.onload = () => {
      // 下面这一行,把小程序码,整个铺进画布中!
      ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
      resolve()
    }
    img.onerror = (event) => {
      reject(event)
    }
  })
},

第二次渲染 - 裁剪和填充

对于第二次渲染,将背景裁剪为圆形并用图像填充。绘制头像:

async drawAvatar (remoteAvatarUrl) {
  const [err, res] = await uni.getImageInfo({
    // 比如这里我用了云储存里的图像地址 prefix: cloud://
    src: remoteAvatarUrl
  })
  if (err) {
    throw err
  }
  const { path } = res
  const img = canvas.createImage()
  img.src = path
  // 测量数据在这里用上了
  const offsetX = 120 // x 轴偏移 120px
  const offsetY = 120 // y 轴偏移 120px
  const diam = 190 // 圆的直径 (430 - 120* 2) / 2
  const radius = diam / 2 // 圆的半径
  const borderWidth = 2 // 多加2px来把原先logo的纯色边抹除
  const circle = { // 裁剪部分圆的大小属性
    x: offsetX + radius,
    y: offsetY + radius,
    radius: radius + borderWidth 
  }
  await new Promise((resolve, reject) => {
    img.onload = () => {
      ctx.save()
      // 开始! 把原先中间的Logo干掉!
      ctx.arc(circle.x, circle.y, circle.radius, 0, Math.PI 2, false)
      ctx.clip()
      // 结束
      // 开始! 把我们需要的自定义图像,平铺的插入进去!
      ctx.drawImage(
        img,
        offsetX - borderWidth,
        offsetY - borderWidth,
        circle.radius * 2,
        circle.radius * 2
      )
      // 结束
      ctx.restore()
      resolve()
    }
    img.onerror = (event) => {
      reject(event)
    }
  })
},

通过以上步骤,我们可以轻松完成图片处理部分,将中间的默认Logo替换为自定义图片。

预览并下载到本地

定制微信小程序价格_芜湖小程序定制_定制小程序

// 获取 tempFilePath
async getImage () {
  const [err, res] = await uni.canvasToTempFilePath({
    canvas
  })
  if (err) {
    throw err
  }
  return res.tempFilePath
}
// 预览
async preview (src) {
  if (src) {
    uni.previewImage({
      urls: [src]
    })
  }
},
// 保存到相册里
async save (src) {
  try {
    // 先授权,后保存
    await authorize('scope.writePhotosAlbum')
    const [err, res] = await uni.saveImageToPhotosAlbum({
      filePath: src
    })
    if (err) {
      throw err
    }
    this.$success('保存成功!')
  } catch (e) {
    console.error(e)
  }
}

至此,客户端生成自定义小程序代码的完整解决方案就完成了

显示结果

或者在微信搜索程序员名片后,维护名片,上传头像,然后点击下方分享二维码按钮进行预览。

自定义生成转发图片

这篇文章的案例很简单。笔者还写了一个小程序Canvas 2D自定义生成和转发图片,以及自定义分享海报。这些原理在原理上是相似的。

附录

wxacode.getUnlimited 接口文档

【昱远信息系统开发定制】

本站声明: 本文章内容来源于互联网,文章内容仅供用户参考。本公司不能完全保证文章内容的准备性、时效性。如果因本文章对用户造成了任何损失或者损害,本公司将不会承担任何法律责任。如果涉及到版权问题,请提交到wikins@nbyuyuan.com

  • 立即与昱远顾问通话
    电话咨询
  • 在线咨询
  • 扫一扫添加微信
    微信咨询
  • 与昱远顾问QQ咨询
    QQ咨询