Use taro+canvas para realizar la función para compartir imágenes del subprograma WeChat | Equipo técnico de JD Cloud

Escena de negocios

En el negocio de carga de dos rondas, después de que el usuario termine de cargar, la información relacionada con el pedido se mostrará en la página de detalles del pedido. El usuario hace clic en el botón Compartir para invocar el menú para compartir del subprograma WeChat, y el póster de imagen generado puede se puede compartir con amigos de WeChat o descargar localmente. Los amigos pueden escanear el póster en el código QR para unirse al grupo y recibir descuentos.

Escenarios y funciones de uso: el subprograma Wechat genera imágenes de póster para compartir con amigos y descargar imágenes

Tecnología utilizada: lienzo Taro vue vant

Representación de realización

División de pasos clave

1. Encapsule un componente para compartir carteles poster-share.vue

2. Use el lienzo para dibujar una imagen, dibuje la imagen de fondo, la tarifa, el código QR y otra información en una imagen, en la que la tarifa y el código QR se obtienen dinámicamente

3. Generar una imagen de caché local

4. Evoque la función para compartir de WeChat para realizar las funciones de compartir y descargar

Ahora que los pasos clave están en su lugar, ¡comencemos!

Implementación de código central

1. Parte de la plantilla

Se necesita un dom de lienzo para dibujar imágenes y un dom para almacenar imágenes generadas

P: ¿Por qué es necesario generar dinámicamente canvasId?

Respuesta: evite el problema de duplicación de canvasId causado por el uso de múltiples componentes en una página

<template>
  <div class="poster-share__content">
    <!-- canvas生成的海报图片 -->
    <img
      v-if="posterImg"
      class="poster-share__content--img"
      mode="aspectFit"
      :src="posterImg"
    >
    <!-- 分享海报canvas绘制部分 -->
    <canvas
      class="poster-share__content--cvs"
      :canvas-id="canvasId"
    ></canvas>
  </div>
</template>

2. Parte del estilo

En este escenario empresarial, el usuario no puede ver el lienzo, pero si la visualización del lienzo no se establece en ninguno, no será posible dibujar y se informará el siguiente error, lo que provocará una falla en el dibujo.

Método de implementación: utilice el método de posicionamiento para colocar el lienzo fuera del área visible. El código específico es el siguiente.

.poster-share__content {
  position: absolute;
  right: -9999px;
  top: -9999px;
  width: 560px;
  height: 852px;
  opacity: 0;
  z-index: -1;

  &--img {
    width: 100%;
    height: 100%;
  }

  &--cvs {
    width: 100%;
    height: 100%;
  }
}


3. La parte central js

Comience a escribir la implementación central ~

El componente principal pasa parámetros para controlar si el componente secundario comienza a dibujarse y se notifica al componente principal que cambie el estado después de dibujar el componente secundario.

  name: 'CpPosterShare',
  model: {
    prop: 'value',
    event: 'update:value',
  },
  props: {
    value: {
      type: Boolean,
      default: false,
    },
    config: {
      type: Object,
      default: () => ({}),
    },
  },
  data () {
    return {
      isDraw: false, // 是否开始绘制海报
      posterImg: '', // 生成的海报图片地址
      canvasId: `canvasId${ Math.random() }`,
      screenWidth: null, // 屏幕宽度
    }
  },
  watch: {
    value: {
      handler (val) {
        this.isDraw = val
      },
      immediate: true,
    },
    isDraw (val) {
      this.$emit('update:value', val)
      if (val) {
        this.init()
      }
    },
  },

En primer lugar, lo que estamos haciendo es un programa pequeño. Poner imágenes en el código fuente del programa pequeño aumentará el tamaño del paquete, y las imágenes deben descargarse de Internet, por lo que es necesario encapsular un método público. para obtener la información de la imagen. Taro proporciona el método getImageInfo para devolver información como el ancho original, la altura y la ruta local de la imagen.

// 加载图片
loadImg (src) {
  return newPromise((resolve, reject) => {
    Taro.getImageInfo({
      src,
    }).then((res) => {
      resolve({ ...res })
    }).catch((err) => {
      reject(err)
    })
  })
}


Este escenario empresarial implica dibujar varias imágenes, incluidas imágenes de fondo e imágenes de códigos QR. Debe cargar varias imágenes antes de poder comenzar a dibujar.

const promiseParams = [this.loadImg(BgImage), this.loadImg(QRcode)]
const promiseAll = Promise.all(promiseParams.map((item) =>item.catch(() =>null)))

promiseAll.then((res) => {
  this.draw(res)
}).catch((err) => {
  console.log(err)
})

Empieza a dibujar~

Cree un objeto CanvasContext de contexto de dibujo de lienzo, llame al método Taro.createCanvasContext(canvasId) proporcionado por Taro para dibujar la imagen de fondo, dibujar el precio y dibujar el código QR, que no se describirá aquí. Después de completar todo el dibujo, exporte el contenido en el lienzo para generar una imagen. Taro proporciona el método canvasToTempFilePath, que debe llamarse en la devolución de llamada draw() para garantizar que la imagen se exporte correctamente y devuelve la ruta temporal del imagen generada.

ctx.draw(false, () => {
  Taro.canvasToTempFilePath({
    canvasId:this.canvasId,
  }).then((res) => {
    this.posterImg = res.tempFilePath

    // 唤起分享菜单
    this.showShareImageMenu()
  }).catch((err) => {
    console.log('海报生成失败', err)
    Taro.showToast({
      title: '海报生成失败',
      icon: 'error',
    })
  }).finally(() => {
    Taro.hideLoading()
    this.isDraw = false
  })
})

Una vez que la imagen local se haya generado correctamente, se invocará la ventana emergente del menú para compartir proporcionada por WeChat y la imagen se podrá enviar a amigos, recopilar y guardar en el álbum. Taro proporciona el método showShareImageMenu para evocar la ventana emergente del menú para compartir, y el parámetro de entrada es la ruta de la imagen local.

showShareImageMenu () {
  if (Taro.showShareImageMenu) {
    Taro.showShareImageMenu({
      path:this.posterImg,
    }).then().catch((err) => {
      console.log(err)
      const { errMsg } = err
      // 取消操作  errMsg === 'showShareImageMenu:fail cancel'
      // 拒绝授权  errMsg: "showShareImageMenu:fail auth deny"
      if (errMsg === 'showShareImageMenu:fail auth deny') {
        authorize({
          scope:'writePhotosAlbum',
          showModal:true,
          authName:'保存图片到相册',
          success: () => {
            this.downloadImg()
          },
        })
      }
    }).finally(() => {
      this.isDraw = false
    })
  } else {
    Taro.showToast({
      title:'小程序版本不支持该功能',
      icon:'error',
    })
  }
}


Cuando el usuario haga clic para enviar a un amigo, se invocará un cuadro de diálogo de WeChat y la imagen del póster generada se pegará y compartirá con amigos;

Haga clic en el favorito, la imagen del póster se agregará a la lista de favoritos, lo cual es conveniente para ver la próxima vez;

Haga clic en Guardar en álbum y aparecerá una ventana emergente para obtener autorización para guardar imágenes. Si el usuario hace clic en Permitir, la imagen del póster se guardará en el álbum local.

Si el usuario hace clic en Rechazar por primera vez en la ventana emergente de autorización de guardar imagen y luego hace clic en compartir para descargar nuevamente, se requiere una ventana emergente de solicitud de autorización para indicarle al usuario si desea abrir la configuración para autorizar, como se muestra abajo.

Taro proporciona el método Taro.openSetting para abrir la página de configuración del subprograma. Después de que el usuario habilite la autorización "Agregar al álbum", llame al método Taro.saveImageToPhotosAlbum proporcionado por Taro para descargar las imágenes localmente.

Ventana emergente de solicitud de autorización página de configuración mensaje de descarga

La implementación específica del método para juzgar si el usuario ha habilitado la autorización es la siguiente:

/**
 * 权限获取流程
 * @param scope       权限英文名称
 * @param success     授权成功的回调
 * @param fail        授权失败的回调
 * @param showModal   授权失败是否展示对话框提示
 * @param authName    授权失败是否展示对话框提示展示的授权名称
 *  // 例子:开启用户的相册权限
    authorize({
      scope: 'writePhotosAlbum',
      showModal: true,
      authName: '保存图片到相册',
      success () {
        console.log('授权成功')
      },
    })
*/
export async function authorize (options) {
  const {
    scope, success, fail, showModal = false, authName = '',
  } = options
  try {
    const scopeName = `scope.${ scope }`
    const auth = await Taro.getSetting()
    if (!auth.authSetting[scopeName]) {
      Taro.authorize({ scope: scopeName }).then((res) => {
        if (res.errMsg === 'authorize:ok' && success) success()
      }, () => {
        if (showModal && authName) {
          Taro.showModal({
            title: '授权提示',
            content: `您拒绝了${ authName }权限,是否打开设置去授权?`,
          }).then((res) => {
            if (res.confirm) {
              Taro.openSetting().then((res2) => {
                if (res2.authSetting[scopeName] && success) {
                  success()
                } else if (fail) {
                  fail()
                }
              })
            } else {
              fail && fail()
            }
          }).catch((res) => {
            fail && fail(res)
          })
        } else {
          fail && fail()
        }
      })
    } else {
      success && success()
    }
  } catch (err) {
    fail && fail(err)
  }
}

En este punto, la implementación específica está completa ~ los componentes se pueden usar en la página

referencia de componente

<poster-share
  v-model="draw"  // 是否开始绘制海报海报
  config="config"  // 海报配置信息
/>


registro de problemas

Encontró algunos problemas durante el proceso de desarrollo, regístrelo

Fenómeno: haga clic en Compartir para generar una imagen de lienzo. La herramienta de desarrollo es normal siempre, la máquina ios es normal siempre, algunas máquinas Android son normales siempre, algunas máquinas Android, cancelan después de hacer clic en compartir, y la operación se repite, y la imagen no se generará varias veces

Mensaje de error: "errMsg": "canvasToTempFilePath:fail:create bitmap falló"

Solución de posicionamiento de error: el lienzo debe mostrarse todo el tiempo y no puede mostrarse: ninguno

Autor: JD Retail Zhang Mengyu

Fuente de contenido: comunidad de desarrolladores de JD Cloud

{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/u/4090830/blog/8805062
Recomendado
Clasificación