js複製黏貼功能

执候發表於2024-11-08

一、首先實現一個把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層沒有載入的問題,導致轉換的圖片複製不上

相關文章