vue+html2canvas避坑

351 阅读1分钟
<template>
  <div id="singlePosterHtml" class="SingleCanvasContranier" v-show="flag">
    <!-- 顶部背景 S-->
    <img class="exAgg-header" :src="topImg" alt="" />
    <!-- E -->
    <div class="floatContainer">
      <!-- 咨询版块 S -->
      <div class="contenText">
        <div class="flobox">
          <div
            class="flobox-inner"
            v-if="Item.userPic && Item.userName && Item.userJob"
          >
            <van-image class="atvar" :src="Item.userPic" alt="">
              <template v-slot:loading>
                <img
                  class="header-placeholder"
                  src="https://www1.pcauto.com.cn/2010/price/img/slt/800x600.jpg"
                /> </template
            ></van-image>
            <div class="sGroup">
              <div class="info">
                <span class="name">{{ Item.userName }}</span>
                <span class="accout">{{ Item.userJob }}</span>
              </div>
            </div>
          </div>
          <div class="innerTime">
            <div class="innerTime-detail">{{ Item.pubDate }}</div>
          </div>
        </div>
        <div class="innertxt">
          {{ Item.content }}
        </div>
        <div class="imgWrapper">
          <van-image
            radius="2px"
            fit="cover"
            v-if="Item.newsType === 3"
            :src="Item.video.cover"
            alt=""
          >
            <template v-slot:loading>
              <img
                class="header-placeholder"
                src="https://www1.pcauto.com.cn/2010/price/img/slt/800x600.jpg"
              /> </template
          ></van-image>
          <van-image
            radius="2px"
            width="100%"
            height="100%"
            fit="cover"
            v-else
            :src="Item.imgArr[0]"
            alt=""
          >
            <template v-slot:loading>
              <img
                class="header-placeholder"
                src="https://www1.pcauto.com.cn/2010/price/img/slt/800x600.jpg"
              /> </template
          ></van-image>
        </div>
      </div>
    </div>
    <!-- 二维码 -->
    <div class="qrcode" @click="methods.createQrcode">
      <img class="comlogo" :src="pcautoImg" alt="" />
      <div class="centertxt">
        <span>扫码查看</span>
        <span class="tpmag">更多最新快讯</span>
      </div>
      <div class="qcoder" id="qrcodeImg2"></div>
    </div>
  </div>
  <!-- E -->
</template>

<script lang="ts">
import { defineComponent, onMounted, reactive, toRefs, watch } from 'vue'
import QRCode from 'qrcodejs2'
import html2canvas from 'html2canvas'
import {
  getImageUrl,
  isAndroid,
  isiOS,
  splteParamsUrl,
} from '@utils/mixins/index'
import { Toast } from 'vant'

interface DataProps {
  posterImg: string
  flag: boolean
}

export default defineComponent({
  name: 'wholepagecanvas',
  props: {
    Item: {
      type: Object,
      default: () => null,
    },
  },
  setup(props) {
    const data: DataProps = reactive({
      posterImg: '', // 最终生成的海报图片
      flag: false,
      topImg: getImageUrl('topImg2.png'),
      pcautoImg: getImageUrl('pcauto.png'),
    })

    // 定义相关方法
    const methods = {
      /*
       * 海报与二维码
       */
      createSingleQrcode() {
        // flag:避免不生成图片
        data.flag = true
        // 拼装地址  防止地址过长二维码扫描不了
        const myUrl = splteParamsUrl() + `?id=${props.Item?.id}`
        console.log('myUrl', myUrl)
        Toast.loading({
          duration: 0,
          message: '海报生成中...',
          forbidClick: true,
        })
        // 生成二维码
        const qrcodeImgEl = document.getElementById('qrcodeImg2') as HTMLElement
        qrcodeImgEl.innerHTML = ''
        let qrcode = new QRCode(qrcodeImgEl, {
          width: 55,
          height: 55,
          colorDark: '#000000',
          colorLight: '#ffffff',
          correctLevel: QRCode.CorrectLevel.L,
        })
        // 生成二维码
        qrcode.makeCode(myUrl)
        // 生成海报 加个延时 尽量确保页面数据最新
        setTimeout(() => {
          methods.createPoster()
        }, 600)
      },

      /**
       * 海报生成
       * */
      createPoster() {
        console.log(
          'window.pageYOffset',
          window.pageYOffset,
          document.body.scrollHeight,
        )
        // 生成海报
        const domObj = document.getElementById(
          'singlePosterHtml',
        ) as HTMLElement
        html2canvas(domObj, {
          useCORS: true, // 是否允许图片跨域
          allowTaint: true,
          scrollY: 0,
          scrollX: 0,
          logging: false, // 日志
          width: domObj.offsetWidth, // 图片宽度
          height: domObj.offsetHeight,
          y: domObj.getBoundingClientRect().top + window.scrollY,
          scale: 2,
        }).then(canvas => {
          // 在微信里,可长按保存或转发
          data.posterImg = canvas.toDataURL('image/png')
          console.log(data.posterImg)
          Toast.loading({
            type: 'success',
            duration: 1000,
            message: '海报生成完成',
            forbidClick: true,
            onClose: () => {
              data.flag = false
              if (isAndroid()) {
                window.PCJSKit.returnShareStr(data.posterImg)
              } else if (isiOS()) {
                window.webkit.messageHandlers.PCJSKit.postMessage({
                  data: data.posterImg,
                  functionName: 'returnShareStr:',
                })
              }
            },
          })
        })
      },
    }
    watch(props, (newProps, oldProps) => {
      props = newProps
    })
    // onMounted
    onMounted(() => {
      // console.log('object');
    })

    return {
      methods,
      ...toRefs(data),
    }
  },
})
</script>

<style scoped lang="scss">
@import './index.scss';
</style>

vue + html2canvas 避坑: html2canvas插件版本不能用最新的 ios会出现兼容性问题 建议用^1.0.0-rc.4版本 并且加上图二的配置才兼容

wecom-temp-06258107a22d092d790658fa083d1e6d.png