从 PWA 通过社交媒体分享图像

Share image via social media from PWA

在我的 Nuxt PWA 中,我有一个函数可以使用 this package 将我的 HTML 转换为 Canvas。生成的图像是 base 64。现在我希望能够通过以下方式共享该图像:Whatsapp、Facebook、电子邮件、Instagram 等。我找到了几个软件包,但它们似乎都不支持仅共享文件 URLs 和文本。

这是我的分享功能:

shareTicket(index) {
  html2canvas(this.$refs['ticket-' + index][0], {
    backgroundColor: '#efefef',
    useCORS: true, // if the contents of screenshots, there are images, there may be a case of cross-domain, add this parameter, the cross-domain file to solve the problem
  }).then((canvas) => {
    let url = canvas.toDataURL('image/png') // finally produced image url

    if (navigator.share) {
      navigator.share({
        title: 'Title to be shared',
        text: 'Text to be shared',
        url: this.url,
      })
    }
  })

当我取出 if (navigator.share) 条件时,我在控制台中收到一条错误消息,指出 navigator.share 不是一个函数。我在某处读到它只适用于 HTTPS,所以我上传到我的登台服务器并尝试但仍然遇到同样的错误。

需要说明的是,我希望能够共享生成的图像本身,而不是 URL。

我在我的一个应用程序的 share() 函数中有以下代码的变体,如果在客户端上执行它可以正常工作。

const share = async() => {
  if (!('share' in navigator)) {
    return;
  }
  // `element` is the HTML element you want to share.
  // `backgroundColor` is the desired background color.
  const canvas = await html2canvas(element, {
    backgroundColor,
  });
  canvas.toBlob(async (blob) => {
    // Even if you want to share just one file you need to 
    // send them as an array of files.
    const files = [new File([blob], 'image.png', { type: blob.type })];
    const shareData = {
      text: 'Some text',
      title: 'Some title',
      files,
    };
    if (navigator.canShare(shareData)) {
      try {
        await navigator.share(shareData);
      } catch (err) {
        if (err.name !== 'AbortError') {
          console.error(err.name, err.message);      
        }
      }
    } else {
      console.warn('Sharing not supported', shareData);            
    }
  });
};

告诉我这个 URL 是否适合你:https://nuxt-share-social-media.netlify.app
如果是,您可以在此处找到 Github 存储库:https://github.com/kissu/so-share-image-bounty

密码是

<template>
  <div>
    <div id="capture" ref="element" style="padding: 10px; background: #f5da55">
      <h4 style="color: #000">Hello world!</h4>
    </div>

    <br />
    <br />
    <button @click="share">share please</button>
  </div>
</template>

<script>
import html2canvas from 'html2canvas'

export default {
  methods: {
    share() {
      // iife here
      ;(async () => {
        if (!('share' in navigator)) {
          return
        }
        // `element` is the HTML element you want to share.
        // `backgroundColor` is the desired background color.
        const canvas = await html2canvas(this.$refs.element)
        canvas.toBlob(async (blob) => {
          // Even if you want to share just one file you need to
          // send them as an array of files.
          const files = [new File([blob], 'image.png', { type: blob.type })]
          const shareData = {
            text: 'Some text',
            title: 'Some title',
            files,
          }
          if (navigator.canShare(shareData)) {
            try {
              await navigator.share(shareData)
            } catch (err) {
              if (err.name !== 'AbortError') {
                console.error(err.name, err.message)
              }
            }
          } else {
            console.warn('Sharing not supported', shareData)
          }
        })
      })()
    },
  },
}
</script>

灵感来自@denvercoder9!


有关答案的更多信息

  • 我使用了 an IIFE,因为我不确定整个事情是如何工作的,但它在 method 环境中工作得很好!
  • 我添加了一个缺失的 async 因为 ESlint 以防你想在
  • 之后做点什么
  • 我使用了 $refs,因为这就是你应该如何 select Vue 生态系统中 DOM 的特定部分
  • 我对一些东西进行了条带化​​以保持简单,托管在 Netlify 上以获得一些简单的 HTTPS 并在 Chrome (v91) 上对其进行了测试,工作非常好!
  • 这里再次 the link Web 共享的 MDN 文档 API。

兼容性

这是我对浏览器的体验(在 MDN 示例和我的应用程序上测试,结果完全相同)

where working
iPad chrome yes
iPad firefox yes
iPad safari yes
windows chrome yes
windows firefox no
android chrome yes
android firefox no
desktop linux chrome no
desktop linux firefox no

对我来说,这是一个仅限移动设备的功能(就像 Android)。但看起来甚至一些桌面浏览器也在处理这个问题。我不得不承认,我什至在 Windows.
上看到这个作品我真的很惊讶 这是来自 Google 的一个有趣的 post 与此兼容性相关:https://web.dev/web-share/#browser-support

再看一遍MDN,上面写着

The navigator.share() method of the Web Share API invokes the native sharing mechanism of the device.

所以,我猜“(桌面)设备”大多不支持共享 API。

TLDR:这完全按预期工作,但到目前为止兼容性确实很差。