React 手机端生成海报 html2canvas & dom-to-image

海报效果如图:

在这里插入图片描述

过程遇到的问题:

插件问题:

  • html2canvas 不支持 Ios无反应, 支持 Android

  • dom-to-image 支持 Ios无反应, 支持 Android

  • dom-to-image 在【ios】中, 图片部分空白,其他部分可以转成图片

解决方法:【canvas 画 img】
在这里插入图片描述

代码1:

import React, {Component} from 'react' 
import QRCode from 'qrcode.react'
import './shareActivity.less'
import classnames from 'classnames'

class ShareActivity extends Component {
  constructor (props) {
    super(props)
    this.state = {
      shareUrl: '',
      poster: '',
      hideImg: false
    }
  }
  componentWillReceiveProps(state, props) {
    console.log('props', props)
  } 
  componentDidMount () { 
    const _this = this
    const {shareUrl} = this.props
    const posterIndex = Number.parseInt(Math.random()*7 + 1)
    const poster = require(`../../../assets/image/invite/invite-${posterIndex}.jpg`)

    this.setState({ 
      shareUrl, 
      poster 
    }, () => {
      var canvas = document.getElementById("canvasImg")
      var ctx =canvas.getContext('2d')
      var img = new Image()
      img.src= poster   
      img.onload = function(){  
        let domImg = document.getElementById('posterImg').getBoundingClientRect()  
        _this.setState({posterWidth: domImg.width, posterHeight: domImg.height}, () => {
          ctx.drawImage(img,0,0, _this.state.posterWidth, _this.state.posterHeight)   
          // 生成图片 
          _this.props.callback() 
        })   
      }   
    })  

  }
  render () {
    return  (   
      <div id="shareActivity">      
          <canvas width={this.state.posterWidth} height={this.state.posterHeight} id="canvasImg"></canvas>
          <img id="posterImg" className={classnames(['poster', {hideDom: this.state.hideImg}])} src={this.state.poster}/>
          <p className="text">
            <img className="icon-link" src={require('../../../assets/image/icon-link.png')} alt=""/>
            <span>长按发送给朋友</span>
          </p>  
          <QRCode
            value={this.state.shareUrl} 
            fgColor="#000000"
          /> 
      </div> 
    )
  }
} 

export default ShareActivity

代码2:

showCourseShare(show_url) {  
    AntdAlert('', <ShareActivity shareUrl={show_url} callback={function() {
      let canvasImg = document.getElementById('shareActivity')  // activityDom  shareActivity
      if (!canvasImg) { return } 
      domtoimage.toJpeg(canvasImg).then((url) => {  
        if (!canvasImg) { return }    
        canvasImg.innerHTML = `<img class="domToImage" src=${url}>`
      })      
    }}/>)    
  }, 

–end

`html2canvas-pro` 是 `html2canvas` 的商业版本,功能更强大,支持更多 CSS 特性、跨域资源、SVG、WebGL 等。但即便如此,**默认情况下,html2canvas-pro 仍然无法直接截图 iframe 的内容**,尤其是跨域 iframe。 --- ### ✅ 要使用 `html2canvas-pro` 截图 **同源 iframe 内部元素**,需要将 iframe 的内容提取出来插入到当前页面中,再截图。 --- ### ✅ 示例代码(使用 html2canvas-pro 截图 iframe 内部元素) #### ✅ HTML 结构 ```html &lt;iframe id=&quot;myIframe&quot; src=&quot;iframe-content.html&quot;&gt;&lt;/iframe&gt; &lt;div id=&quot;captureArea&quot;&gt;&lt;/div&gt; &lt;button onclick=&quot;captureIframeContent()&quot;&gt;截图 iframe 内容&lt;/button&gt; ``` --- ### ✅ JavaScript 代码(引入 html2canvas-pro) 确保你已正确引入 `html2canvas-pro`: ```html &lt;script src=&quot;https://cdn.jsdelivr.net/npm/html2canvas-pro/dist/html2canvas.min.js&quot;&gt;&lt;/script&gt; ``` --- ### ✅ 截图函数代码 ```js async function captureIframeContent() { const iframe = document.getElementById(&#39;myIframe&#39;); const captureArea = document.getElementById(&#39;captureArea&#39;); if (!iframe.contentDocument) { console.error(&#39;iframe 内容尚未加载完成&#39;); return; } const iframeDoc = iframe.contentDocument || iframe.contentWindow.document; // 清空之前的截图内容 captureArea.innerHTML = &#39;&#39;; // 复制 iframe 的 body 内容到当前页面的 captureArea 中 const importedNode = document.importNode(iframeDoc.body, true); importedNode.style.width = &#39;100%&#39;; importedNode.style.position = &#39;static&#39;; captureArea.appendChild(importedNode); try { // 使用 html2canvas-pro 截图 const canvas = await html2canvas(captureArea, { useCORS: true, // 允许加载跨域图片 allowTaint: false, // 防止跨域污染 imageTimeout: 15000, // 图片加载超时时间 logging: true, // 开启日志调试 backgroundColor: null, // 保持透明背景(如需要) scale: 2 // 提高截图清晰度 }); // 显示截图预览 const imgData = canvas.toDataURL(&#39;image/png&#39;); const img = document.createElement(&#39;img&#39;); img.src = imgData; document.body.appendChild(img); // 保存为 Blob 并上传 canvas.toBlob((blob) =&gt; { if (!blob) { console.error(&#39;生成 Blob 失败&#39;); return; } const file = new File([blob], &#39;iframe-screenshot.png&#39;, { type: &#39;image/png&#39; }); console.log(&#39;截图文件已生成:&#39;, file); // 这里可以调用上传函数 uploadFilePic(file, imgData) }, &#39;image/png&#39;); } catch (error) { console.error(&#39;截图失败:&#39;, error); } } ``` --- ### ✅ 注意事项 - **iframe 必须是同源的**,否则无法访问其 DOM- 如果 iframe 内容是动态加载的(如 Vue/React),请使用 `iframe.onload` 确保内容加载完成后再截图。 - `html2canvas-pro` 支持更多 CSS 特性(如 filter、transform、flex 等),但仍不能直接渲染 iframe 内容。 - 如果你确实需要截图跨域 iframe,请使用 **Puppeteer(服务端截图)** 或 **后端代理截图服务**。 --- ### ✅ 延伸:等待 iframe 加载完成 ```js iframe.onload = () =&gt; { captureIframeContent(); }; ``` ---
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值