记录ios微信环境下长按图片识别二维码出现的问题。

214 阅读1分钟

故事的开始

事情是这样的,项目中需要一个页面,有一个全屏满铺的背景图,左下角展示一些用户信息,右下角展示通过某个 url 生成的二维码。如下:

image.png

遇到问题

开发技术栈是 Vue3 ,很快做完交付测试。在 android 手机上没有任何问题,而在 ios 手机的微信浏览器中长按时,大概率并不能识别到二维码,而是可以拖动背景图片、分享背景图片等。

解决

试错了一些解决方案,如img { -webkit-touch-callout: none !important; }、强制刷新等。最后想到笨方法,将整个 DOM 转换成图片展示。代码如下:


<template>
  <div
    class="relative text-16px min-h-100vh bg-#fff text-#fff"
    ref="mainRef"
    v-if="!mainImg"
  >
    <img :src="bgUrl" class="w-100vw" />
    <div class="absolute top-640px left-30px">
      用户信息
    </div>
    <div class="absolute top-590px right-30px">
      <canvas ref="qrCodeRef" class="w-80px! h-80px!"></canvas>
      <div class="text-center mt-5px text-12px">长按参与活动</div>
    </div>
  </div>
  <div v-else>
    <img :src="mainImg" alt="" class="w-100vw" />
  </div>
</template>

<script setup lang="ts">
import html2canvas from 'html2canvas'
import QRCode from 'qrcode'

//创建 canvas 方法,放到 common utils 中 
export const createBaseCanvas = (
  scale: number,
  width: number,
  height: number
) => {
  // 构造 canvas
  const canvas = document.createElement('canvas')
  canvas.width = width * scale
  canvas.height = height * scale
  const context = canvas.getContext('2d')
  if (context) {
    context.imageSmoothingEnabled = false
    context.scale(scale, scale)
  }
  return canvas
}

const mainRef = ref()
const mainImg = ref()

// html to canvas
onMounted(() => {
  setTimeout(() => {
    const width = mainRef.value.offsetWidth
    const height = mainRef.value.offsetHeight
    const scale = window.devicePixelRatio
    const canvas = createBaseCanvas(scale, width, height)

    html2canvas(mainRef.value, {
      useCORS: true,
      scrollY: 0,
      scrollX: 0,
      width,
      height,
      logging: false,
      scale: 1,
      canvas
    }).then((canvas: any) => {
      try {
        mainImg.value = canvas.toDataURL('image/png')
      } catch (err) {
        console.log(err)
      }
    })
  })
})

// 二维码生成
const qrCodeRef = ref()
onMounted(() => {
  QRCode.toCanvas(
    qrCodeRef.value,
    `${window.origin}/test`,
    (error) => {
      if (error) console.error(error)
    }
  )
})

const bgUrl = ref('https://cn.bing.com/images/search?view=detailV2&ccid=nFHrgJLw&id=1C6CFB20DA6F79811343267FF9E2E09CF7848EAD&thid=OIP.nFHrgJLwPjkJyZ7FIf5lVgHaFQ&mediaurl=https%3a%2f%2fimg.haote.com%2fupload%2fpic%2fimage%2f20190327%2f20190327172547_54242.png&exph=535&expw=754&q=%e8%94%a1%e5%be%90%e5%9d%a4%e6%89%93%e7%af%ae%e7%90%83%e5%9b%be%e7%89%87&simid=608021607027395562&FORM=IRPRST&ck=E80686FAA1AF81CB66543EFB6E00864F&selectedIndex=0&idpp=overlayview&ajaxhist=0&ajaxserp=0')
</script>

结尾

当下就想到这个解决办法了,如果有更好的解决办法,恳请评论区指教,感谢!