react 移动端h5 保存图片到手机相册

有这么一个需求,保存图片到手机相册,真正的保存是调用的sdk原生的接口,这个不是我想讲的重点

我想说的是,如何使用qrcode.react 生成二维码之后再将以canvas画布形式渲染的二维码转成base64链接!

参考自https://blog.csdn.net/qq_42190134/article/details/92218323这位博主

/* global APPID */
import React from 'react'
import { connect } from 'dva'
import { Flex, Button } from 'antd-mobile'
import LoadWrap from '@/components/LoadWrap'
import QRCode from 'qrcode.react'
import NavBar from '@/components/NavBar'
import Bridge from '@/utils/bridge'
import styles from './qrcode.less'
import APIENV from '../env'
import $ from 'jquery';


@connect(({ signIn }) => ({
  detail: signIn.detail
}))
class QRCodePage extends React.Component {
  constructor(props) {
    super(props)
    this._inThisPage = true

    this.vid = props.location.query.id;

    if (this.vid) {
      props.dispatch({
        type: 'signIn/fetchDetail',
        payload: { vid: this.vid }
      })
    }

    this.handleBack = this.handleBack.bind(this)
    this.handleNativeBack = this.handleNativeBack.bind(this)
    this.handleNativeBack()
  }

  componentWillUnmount() {
    this._inThisPage = false
  }

  _downLoad = () => {
    var Qr = document.getElementById('qrid');
    let imgBase64 = Qr.toDataURL("image/png");
    console.log('Qr.toDataURL("image/png")', Qr.toDataURL("image/png"));
    this.saveToAlbum(imgBase64);
  }

  // getBase64Image = (img) => {
  //   var canvas = document.createElement("canvas");
  //   canvas.width = img.width;
  //   canvas.height = img.height;
  //   var ctx = canvas.getContext("2d");
  //   ctx.drawImage(img, 0, 0, img.width, img.height);
  //   var dataURL = canvas.toDataURL("image/png");//修改图片后缀
  //   return dataURL
  // }
  // main = () => {
  //   var img = document.createElement('img');
  //   img.src = $("#h5qrcodeimg").attr('src');//赋予二维码src
  //   img.onload = function () {
  //     var data = this.getBase64Image(img);
  //     console.log(data);
  //     $("#down_qrcode").attr("href", data);//转码后赋予下载按钮(a标签)的href
  //   };
  // }

  handleBack() {
    if (this.props.location.query.backto === 'list') {
      this.props.history.push('/electric')
    } else {
      this.props.history.goBack();
    }
  }

  handleNativeBack() {
    Bridge.onMessage(msg => {
      if (!this._inThisPage) return;
      msg = JSON.parse(msg)
      if (msg && msg.type === 'back') {
        this.handleBack();
      }
    })
  }

  saveToAlbum = (imgBase64) => {
    // 图片预览, 可选参数 saveable:是否显示保存图片按钮, index: 多图情况下指定当前浏览的序号
    if (window.mbBridge) {
      window.mbBridge.mb.image({
        index: 1,
        saveable: true,
        urls: [imgBase64]
      });
    }
  }

  render() {
    const { detail, location } = this.props;
    const info = detail.data || {}
    const query = location.query;
    const src = `${APIENV}/down/app/signin/?name=${query.signInName}&num=${query.index || 1}&signInId=${query.signInId}#/`;

    return (
      <Flex direction="column" align="stretch" className={`${styles.qrcodePage} flex100`}>
        <NavBar
          title="二维码展示"
          handleBack={this.handleBack}
        />

        <Flex.Item className="flex100">
          <div className={styles.headPlace}></div>

          <div className={styles.card}>
            <div id="QR" style={
   
   { padding: '50px 0 45px 0' }}>
              <QRCode id='qrid' value={src} onClick={this._downLoad} size={191} />
            </div>
          </div>

          <div className={styles.saveBtn}>
            <div type="primary" className={styles.btnCss} onClick={this._downLoad}>保存到手机</div>
          </div>
          {/* <LoadWrap data={
   
   {err: {message: '缺少ID参数'}}}/> */}
        </Flex.Item>
      </Flex>

    );
  }

}

export default QRCodePage

 

 

问题来了,如果我想把文案也一起作为图片存储为base64那要怎样做呢?(效果图如下)

关键是yarn add html2canvas

利用html2canvas将div生成base64(html2canvas这边有一个神坑!!!在IOS上,如果你的html2canvas版本不是1.0.0-rc.4,会导致在ios真机上调试时,不执行promise.then回调函数!!!

比如:

再比如:

...无语凝噎 

/* global APPID */
import React from 'react'
import { connect } from 'dva'
import { Flex, Button } from 'antd-mobile'
import LoadWrap from '@/components/LoadWrap'
import QRCode from 'qrcode.react'
import NavBar from '@/components/NavBar'
import Bridge from '@/utils/bridge'
import styles from './qrcode.less'
import APIENV from '../env'
import $ from 'jquery';
import html2canvas from 'html2canvas';


@connect(({ signIn }) => ({
  detail: signIn.detail
}))
class QRCodePage extends React.Component {
  constructor(props) {
    super(props)
    this._inThisPage = true

    this.vid = props.location.query.id;

    if (this.vid) {
      props.dispatch({
        type: 'signIn/fetchDetail',
        payload: { vid: this.vid }
      })
    }

    this.canvas = React.createRef();

    this.handleBack = this.handleBack.bind(this)
    this.handleNativeBack = this.handleNativeBack.bind(this)
    this.handleNativeBack()
  }

  componentDidMount() {
    html2canvas(document.querySelector("#capture")).then(canvas => {
      // document.body.appendChild(canvas);
      let dataImg = canvas.toDataURL();
      this.newImgBase64 = dataImg;
    });
  }

  componentWillUnmount() {
    this._inThisPage = false
  }

  _downLoad = () => {
    console.log('this.newImgBase64===>:', this.newImgBase64);
    this.saveToAlbum(this.newImgBase64);
  }

  handleBack() {
    if (this.props.location.query.backto === 'list') {
      this.props.history.push('/electric')
    } else {
      this.props.history.goBack();
    }
  }

  handleNativeBack() {
    Bridge.onMessage(msg => {
      if (!this._inThisPage) return;
      msg = JSON.parse(msg)
      if (msg && msg.type === 'back') {
        this.handleBack();
      }
    })
  }

  saveToAlbum = (imgBase64) => {
    // 图片预览, 可选参数 saveable:是否显示保存图片按钮, index: 多图情况下指定当前浏览的序号
    if (window.mbBridge && window.mbBridge.mb) {
      console.log('保存图片被触发了!!!');
      window.mbBridge.mb.saveImage(imgBase64);
    }
  }

  render() {
    const { detail, location } = this.props;
    const info = detail.data || {}
    const query = location.query;
    const src = `${APIENV}/down/app/signin/?name=${query.signInName}&num=${query.index || 1}&signInId=${query.signInId}#/`;

    return (
      <Flex direction="column" align="stretch" className={`${styles.qrcodePage} flex100`} style={
   
   { overflow: 'auto' }}>
        <NavBar
          title="二维码展示"
          handleBack={this.handleBack}
        />

        <Flex.Item className={`${styles.column} flex100`} style={
   
   { background: '#F6F6F6', paddingBottom: 30 }}>
          <div id="capture">
            <div className={`${styles.card} ${styles.column}`}>
              <div className={`${styles.column}`} style={
   
   { alignItems: 'flex-start', padding: '25px 25px 0 25px' }}>
                <span className={`${styles.title}`}>{query.signInName}</span>
                <span className={`${styles.date}`}>{query.createAt}</span>
              </div>

              <div id="QR" style={
   
   { padding: '30px 0 35px 0', alignItems: 'center' }} className={styles.column}>
                <QRCode id='qrid' value={src} onClick={this._downLoad} size={260} />
              </div>
              <span className={`${styles.noticeText}`} >使用OA或党建APP扫描二维码签到</span>
            </div>
          </div>

          <div className={styles.saveBtn}>
            <div type="primary" className={styles.btnCss} onClick={this._downLoad}>保存到手机</div>
          </div>
        </Flex.Item>
      </Flex>

    );
  }

}

export default QRCodePage

可以在http://tool.chinaz.com/tools/imgtobase该站点进行转换查看base64是否有效

猜你喜欢

转载自blog.csdn.net/hzxOnlineOk/article/details/108285441