uniapp创建组件生成二维码海报

admin 110 0
基于uniapp框架,通过封装可复用组件实现二维码海报生成功能,利用uQRCode等插件生成二维码,结合canvas绘制海报背景、文字及二维码布局,支持自定义样式(尺寸、颜色、Logo),组件提供预览和保存接口,调用uni.saveImageToPhotosAlbum实现海报本地存储,适用于活动推广、商品分享等场景,提升开发效率与用户体验。

Uniapp自定义组件实现二维码海报生成与分享

在移动端应用开发中,生成带二维码的海报已成为一种常见需求,广泛应用于活动推广、用户裂变分享、身份核验、产品展示等多种场景,Uniapp作为一套跨端开发框架,通过一套代码即可编译到iOS、Android、H5、小程序等多个平台,为开发者提供了极大的便利,本文将详细介绍如何基于Uniapp创建自定义组件,实现二维码生成、海报布局设计、跨端适配优化以及分享保存功能,帮助开发者快速构建高质量的海报生成功能。

功能需求与技术选型

核心需求

  1. 二维码生成:根据动态传入的内容(如活动链接、用户ID、文本信息等)生成高质量二维码图片
  2. 海报布局设计:支持自定义背景图、标题文字、描述信息、二维码位置及样式,满足不同业务场景需求
  3. 跨端兼容适配:确保在iOS、Android、H5、小程序等多平台上都能正常显示和保存
  4. 保存与分享功能:支持将生成的海报保存到本地相册,并能调用系统分享接口进行传播

技术选型

  1. 二维码生成:选用qrcode库,该库轻量级、性能优异,支持Canvas绘制,兼容多端环境
  2. 海报绘制:基于Uniapp原生canvas API,确保跨端兼容性最佳,无需额外引入第三方依赖
  3. 图片处理:利用uni.getImageInfo获取图片信息,同时支持本地图片和网络图片资源
  4. 权限处理:通过uni.authorize请求相册写入权限,针对iOS/Android平台进行特殊处理
  5. 性能优化:采用异步加载和缓存机制,避免重复生成相同内容的海报

自定义组件创建

组件目录结构

在Uniapp项目中,建议按照以下结构组织自定义组件:

components/
  └── qrcode-poster/          // 组件文件夹
      ├── qrcode-poster.vue   // 组件模板
      ├── qrcode-poster.js    // 组件逻辑
      ├── qrcode-poster.json  // 组件配置
      └── utils/              // 工具函数
          ├── qrcode-generator.js  // 二维码生成工具
          └── image-loader.js       // 图片加载工具

组件配置(qrcode-poster.json)

{
  "component": true,
  "usingComponents": {}
}

组件核心实现

组件模板(qrcode-poster.vue)

<template>
  <view class="poster-container">
    <!-- 海报画布 -->
    <canvas
      class="poster-canvas"
      canvas-id="posterCanvas"
      :style="{ width: canvasWidth + 'px', height: canvasHeight + 'px' }"
      :disable-scroll="true"
    ></canvas>
    <!-- 加载状态提示 -->
    <view class="loading-mask" v-if="isLoading">
      <text>海报生成中...</text>
    </view>
    <!-- 操作按钮(可选) -->
    <view class="poster-actions" v-if="showActions">
      <button @click="savePoster" class="action-btn save-btn">保存海报</button>
      <button @click="sharePoster" class="action-btn share-btn">分享海报</button>
    </view>
  </view>
</template>
<style>
.poster-container {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.poster-canvas {
  background: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.1);
}
.loading-mask {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  color: #fff;
  border-radius: 8px;
}
.poster-actions {
  margin-top: 20rpx;
  display: flex;
  gap: 20rpx;
}
.action-btn {
  padding: 12rpx 30rpx;
  border-radius: 30rpx;
  font-size: 28rpx;
}
.save-btn {
  background: #07c160;
  color: #fff;
}
.share-btn {
  background: #1989fa;
  color: #fff;
}
</style>

组件逻辑(qrcode-poster.js)

import QRCode from 'qrcode'
import { generateQRCode } from './utils/qrcode-generator'
import { loadImage } from './utils/image-loader'
export default {
  name: 'QrcodePoster',
  props: {
    // 海报配置
    posterConfig: {
      type: Object,
      default: () => ({
        // 画布尺寸(根据平台适配)
        canvasWidth: 375,  // H5/小程序逻辑像素,iOS/Android 物理像素需转换
        canvasHeight: 667,
        // 背景图(支持本地路径/网络地址)
        bgImage: '',
        // 二维码配置
        qrCodeConfig: {
          content: '',
          size: 200,
          color: '#000000',
          backgroundColor: '#ffffff',
          correctLevel: 'M'
        },
        // 文字配置
        title: {
          text: '',
          fontSize: 32,
          color: '#333333',
          bold: true,
          position: { x: 0, y: 100 }
        },
        description: {
          text: '',
          fontSize: 24,
          color: '#666666',
          position: { x: 0, y: 150 },
          maxWidth: 300,
          lineHeight: 1.5
        }
      })
    },
    // 是否显示操作按钮
    showActions: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      isLoading: false,
      canvasContext: null
    }
  },
  mounted() {
    this.initCanvas()
  },
  methods: {
    // 初始化画布
    initCanvas() {
      const query = uni.createSelectorQuery().in(this)
      query.select('#posterCanvas').fields({ node: true, size: true })
        .exec((res) => {
          const canvas = res[0].node
          const ctx = canvas.getContext('2d')
          // 根据平台调整画布尺寸
          const dpr = uni.getSystemInfoSync().pixelRatio || 1
          canvas.width = this.posterConfig.canvasWidth * dpr
          canvas.height = this.posterConfig.canvasHeight * dpr
          ctx.scale(dpr, dpr)
          this.canvasContext = ctx
          this.drawPoster()
        })
    },
    // 绘制海报
    async drawPoster() {
      this.isLoading = true
      const ctx = this.canvasContext
      try {
        // 1. 绘制背景
        if (this.posterConfig.bgImage) {
          const bgImage = await loadImage(this.posterConfig.bgImage)
          ctx.drawImage(bgImage, 0, 0, this.posterConfig.canvasWidth, this.posterConfig.canvasHeight)
        } else {
          ctx.fillStyle = '#ffffff'
          ctx.fillRect(0, 0, this.posterConfig.canvasWidth, this

标签: #uniapp #组件 #二维码 #海报