一、首先实现一个把canvas转换为图片,简单点就是把dom转换为图片
1、优先想到的就是html2canvas ,具体使用参考官网
但是它有一个bug,你复制的容器不能使用css3的box-shadow要不然会导致你转换的图片变成白色和灰色相间的背景色,并且无解,
如果有跨域问题,那就继续使用html2canvas

2、dom-to-image 插件也可以将dom转换为图片,并且你容器使用任意css3属性都无影响

安装 npm install dom-to-image --save-dev
使用
import domtoimage from 'dom-to-image'
domtoimage
      .toPng('转换的容器,支持vdom', config)
      .then(baseUrl => {
           waferCopyBigImage.value = baseUrl  //这时候就拿到图片了
       })

二、将图片复制到剪切板

有两种方式
1、document.execCommand('copy')  //这个无兼容问题
2、navigator.clipboard.writeText()  //这个方法不支持在http下面

很多插件都是把这两个集成进去了

<template>
  <div v-if="copySuccess" class="copy-success" :style="menuStyle" @click="copyWaferHandler">
    复制
  </div>
  <div
    ref="waferCopyBigImageContainer"
    :style="{
      width: waferMapContentSize?.width + 'px',
      height: waferMapContentSize?.height + 'px',
      position: 'absolute',
      left: '1000%',
      overflow: 'hidden',
      background: '#fff',
    }"
    v-if="waferCopyBigImage"
  >
    <img width="100%" height="100%" v-if="waferCopyBigImage" :src="waferCopyBigImage" />
  </div>
</template>
<script setup lang="ts" name="WaferCopyContent">
import { ref, nextTick } from 'vue'
import { Message } from '@arco-design/web-vue'
import domtoimage from 'dom-to-image'
import type { IWaferMapSize } from '../wafer-map-canvas'
const props = defineProps<{
  copySuccess: boolean
  waferMapContentSize?: IWaferMapSize
  menuStyle: any
  copyContentBox: HTMLDivElement | null
}>()

const emits = defineEmits<{
  (e: 'copySet', value: boolean): void
}>()
const waferCopyBigImage = ref<string | null>(null)
const waferCopyBigImageContainer = ref<HTMLElement | null>(null)

const copyWaferHandler = e => {
  emits('copySet', false)
  e.stopPropagation()
  e.preventDefault()
  console.log('复制')
  document.execCommand('delete')
  Message.loading('复制中...')
  copyImage()
}

const copyImage = async () => {
  const config = {
    width: props.waferMapContentSize?.width,
    height: props.waferMapContentSize?.height,
    backgroundColor: '#fff',
  }
  if (props && props.copyContentBox) {
    domtoimage
      .toPng(props.copyContentBox, config)
      .then(baseUrl => {
        waferCopyBigImage.value = baseUrl
        Message.clear()
        nextTick(() => {
          const selection = window.getSelection()
          if (!selection) {
            return
          }
          selection.removeAllRanges()

          selection?.empty()
          const range = document.createRange()
          range.selectNode(waferCopyBigImageContainer.value!)
          selection?.addRange(range)
          try {
            document.execCommand('copy')
            Message.info('图片已复制到剪贴板')
          } catch (err: any) {
            Message.error('复制失败:', err)
          }
          if (selection) {
            selection.removeAllRanges()
          }
        })
      })
      .catch(err => {
        Message.clear()
        console.log('转换失败', err)
      })
  }
}
</script>
<style scoped lang="scss">
.copy-success {
  position: absolute;
  padding: 0 10px;
  width: 50px;
  height: 32px;
  text-align: center;
  line-height: 32px;
  cursor: pointer;
  background-color: var(--color-bg-popup);
  border: 1px solid var(--color-fill-3);
  border-radius: var(--border-radius-medium);
  box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1019607843);
}
</style>

复制的时候有个bug
如果遇到要复制两次的时候,一定要记得把你装载的容器加一个v-if,因为会出现数据层实现了,dom层没有加载的问题,导致转换的图片复制不上

posted on 2024-11-08 12:00  执候  阅读(1)  评论(0编辑  收藏  举报