首页 > 其他分享 >El-Upload组件上传图片并添加水印

El-Upload组件上传图片并添加水印

时间:2024-05-08 23:46:20浏览次数:22  
标签:El style img watermark image Upload 水印 file

背景

有的时候我们需要在上传图片中添加一些水印标识,然后上传至服务器

效果图

代码

需求:

    1. 点击直接预览图片,而不需要使用dialog
    1. 上传图片添加水印后才预览图片
    • 上传图片文件添加水印。使用watermarkjs库转换
    • 将添加水印的图片转换成base64,更新预览图片的内容,否则预览的图片还是旧的
    • 保存添加水印后的文件
    • 自行上传服务器....
<template>
  <div class="app">
    <el-upload
      action=""
      list-type="picture-card"
      :multiple="true"
      :on-change="handleUploadChange"
      :auto-upload="false"
    >
      <i slot="default" class="el-icon-plus"></i>
      <div slot="file" slot-scope="{ file }">
        <img class="el-upload-list__item-thumbnail" :src="file.url" alt="" />

        <span class="el-upload-list__item-actions">
          <span
            class="el-upload-list__item-preview"
            @click="handlePictureCardPreview(file)"
          >
            <i class="el-icon-zoom-in"></i>
            <!-- <el-image
              style="width: 100px; height: 100px"
              :src="dialogImageUrl"
              :preview-src-list="[dialogImageUrl]"
            >
            </el-image> -->
          </span>
          <span class="el-upload-list__item-delete" @click="handleRemove(file)">
            <i class="el-icon-delete"></i>
          </span>
        </span>
      </div>
    </el-upload>
    <!-- 
      预览图片方式1:使用dialog方式
    <el-dialog :visible.sync="dialogVisible">
      <img width="100%" :src="dialogImageUrl" alt="" />
    </el-dialog> -->

    <!-- 预览图片方式2:使用image-viewer -->
    <el-image-viewer
      v-if="imgViewerVisible"
      :url-list="imgList"
      :on-close="closeImgViewer"
    />
    <div class="demo" ref="demoRef"></div>
  </div>
</template>

<script>
import watermark from 'watermarkjs'
import ElImageViewer from 'element-ui/packages/image/src/image-viewer'

export default {
  components: {
    ElImageViewer,
  },
  data() {
    return {
      dialogImageUrl: '',
      dialogVisible: false,
      imgViewerVisible: false,
      imgList: [],
    }
  },
  methods: {
    handlePictureCardPreview(file) {
      // this.dialogImageUrl = file.url
      // this.dialogVisible = true
      this.imgViewerVisible = true
      this.imgList = [file.url]

      // 解决预览放大后滚动鼠标页面跟着滚动的问题
      const m = (e) => {
        e.preventDefault()
      }
      document.body.style.overflow = 'hidden'
      document.addEventListener('touchmove', m, false) // 禁止页面滑动
    },
    closeImgViewer() {
      this.imgViewerVisible = false
      const m = (e) => {
        e.preventDefault()
      }
      document.body.style.overflow = 'auto'
      document.removeEventListener('touchmove', m, true)
    },

    handleRemove(file) {
      console.log(file)
    },
    handleUploadChange(file, fileList) {
      // console.log('file:', file)
      // console.log('fileList:', fileList)
      const upload_file = file.raw

      // 1. 添加单个水印
      // watermark([upload_file])
      //   .image(
      //     watermark.text.upperRight(
      //       'watermark.js',
      //       '48px Josefin Slab',
      //       '#fff',
      //       0.5,
      //       48
      //     )
      //   )
      //   .then((img) => {
      //     img.style.width = '300px'
      //     img.style.height = 'auto'
      //     this.$refs.demoRef.append(img)
      //   })

      // 2. 添加多个水印
      // watermark([upload_file])
      //   .image(
      //     watermark.text.upperRight(
      //       '呵呵呵',
      //       '48px Josefin Slab',
      //       '#fff',
      //       0.5,
      //       48
      //     )
      //   )
      //   .render()
      //   .image(
      //     watermark.text.upperLeft(
      //       '哈哈哈',
      //       '48px Josefin Slab',
      //       '#fff',
      //       0.5,
      //       48
      //     )
      //   )
      //   .then((img) => {
      //     img.style.width = '300px'
      //     img.style.height = 'auto'
      //     this.$refs.demoRef.append(img)
      //   })

      // 3. 自定义添加水印位置,比如:设置在右上角
      // @param {HTMLCanvasElement} canvas
      // @param {TextMetrics} metrics
      // @param {CanvasRenderingContex2D} context - context of the canvas
      // 设置水印的x坐标
      var x = function (canvas, metrics, context) {
        // 微调,比如:-20  根据实际调整
        return canvas.width - metrics.width - 20
      }
      // 设置水印的y坐标
      var y = function (canvas, metrics, context) {
        return metrics.hangingBaseline + 10
      }
      watermark([upload_file])
        .image(
          watermark.text.atPos(
            x,
            y,
            '上传时间:2024-05-08 22:40:10',
            '48px sans-serif',
            '#fff',
            0.8
          )
        )
        .then((img) => {
          // img.style.width = '300px'
          // img.style.height = 'auto'
          this.$refs.demoRef.append(img)
          // 将base64转文件形式
          const watermark_file = this.dataURLtoFile(img.src, file.name)
          // 下载文件
          // this.downloadFile(watermark_file)

          this.transformFileToBase64(watermark_file, file)
        })
    },
    // 将base64转文件
    dataURLtoFile(dataurl, filename) {
      var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
      }
      return new File([u8arr], filename, { type: mime })
    },
    // 下载文件
    downloadFile(file) {
      let aTag = document.createElement('a') //创建一个a标签
      aTag.download = file.name
      let href = URL.createObjectURL(file) //获取url
      aTag.href = href
      aTag.click()
      URL.revokeObjectURL(href) //释放url
    },
    // 将水印文件转换成base64,然后修改原有file对象的url,这样保证预览时图片的url是带有水印的
    transformFileToBase64(watermark_file, file) {
      return new Promise((resolve, reject) => {
        // 读取文件
        const reader = new FileReader()
        //readAsDataURL()方法: 读取文件内容,结果用data:url的字符串形式表示
        reader.readAsDataURL(watermark_file)
        // 读取成功回调
        reader.onload = () => {
          file.url = reader.result
        }
      })
    },
  },
}
</script>

<style lang="less" scoped></style>

第三方库watermarkjs

链接:https://brianium.github.io/watermarkjs/docs.html#image

参考文档

标签:El,style,img,watermark,image,Upload,水印,file
From: https://www.cnblogs.com/it774274680/p/18181172

相关文章

  • Shell编程之条件语句
    目录1.条件测试2.文件测试与整数测试(1)文件测试(2)整数测试3.字符串测试与逻辑测试(1)字符串测试(2)逻辑测试4.if语句(1)if单分支语句(2)if双分支语句(3)if多分支语句5.case分支语句1.条件测试Shell环境根据命令执行后的返回状态值($?)来判断是否执行成功,当返回值为0(真true)时表示成功,返回值为非......
  • Semantic Kernel-1
    入门SemanticKernel:OneApi集成与HelloWorld  合集-AI(2) 1.一键接入大模型:One-Api本地安装配置实操05-072.入门SemanticKernel:OneApi集成与HelloWorld05-08收起 引言从这一章节开始正式进入我们的 SemanticKernel 的学习之旅了。什么是SemanticKer......
  • ExcelDataReader:一个.Net高性能Excel开源读取器
    ExcelDataReader:一个.Net高性能Excel开源读取器来自:编程乐趣推荐一个用于读取MicrosoftExcel文件的高性能开源库。 01项目简介ExcelDataReader是一个功能强大且易于使用的开源项目,提供了丰富的读取API,专门读取Excel文件的数据,特别是处理大数据量的情况。ExcelDataReader......
  • HelloWorld
    随便建造一个文件夹,存放代码。建造一个Java文件文件后缀名为.JavaHello.java【要注意】系统可能没有显示文件名后缀,我们需要手动打开3.编写代码publicclassHello{ publicstaticvoidmain(String[]args){ System.out.print("Hello,World!"); }}编译jav......
  • Selenium4自动化测试2--元素定位By.ID,By.CLASS_NAME,By.TAG_NAME
    三、元素定位方式1-通过id定位,By.IDid属性在HTML中是唯一的,因此使用id定位可以确保找到页面上唯一的元素。由于id是唯一的,浏览器在查找元素时可以快速定位到目标元素,提高了定位的效率。 importtime#pipinstallseleniumfromseleniumimportwebdriverfromselenium......
  • Selenium4自动化测试1--Chrome浏览器和chromedriver
    selenium的介绍Selenium是一个用于Web应用程序测试的强大工具,可以模拟用户在浏览器中的行为。它提供了一组功能丰富的工具和库,使您能够自动化浏览器操作,进行功能测试、回归测试和跨浏览器测试。Selenium原理 它需要模拟浏览器的操作所以需要用到浏览器和浏览器驱动。一、......
  • Elements in iteration expect to have 'v-bind:key' directives.
    当组件中使用v-for时,如果不指定key,则会有红色警告信息。解决方案如下。方案一:绑定key(亲试有效)//方式一<liv-for="(item,index)inlist":key="index">//方式二<liv-for="(item,index)inlist":key="item.id">//方式三<liv-for="(item,in......
  • 条件编译#if、#elif、#ifdef的妙用
    前言—般情况下,C语言源程序中的每一行代码.都要参加编译。但有时候出于对程序代码优化的考虑,希望只对其中一部分内容进行编译,此时就需要在程序中加上条件,让编译器只对满足条件的代码进行编译,将不满足条件的代码舍弃,这就是条件编译。相关的预编译指令如下:条件编译功能预处理程......
  • 使用同事封装好的table(使用el-table),修改表头背景色怎么实现
    花了一下午时间基本功还是比较差参考博客1首先,要修改表头颜色,需要el-table的属性:header-cell-style可以这样写:header-cell-style="{background:'#409EFF',color:'#409EFF'}"而我有两个点需要考虑1)只有部分表头需要修改颜色2)同事封装的组件,对背景颜色使用了!important解决......
  • antd在form中一个select设置另一个select
    需求:所属网络(select)变化的时候,对应空投合约(select)也跟着变化。 constonChainChange=(chainId:any)=>{setCurrChainId(chainId)constcurrOptions=extraObj.airdropContractFormOptions.map((item:any)=>{if(item.network_id===chainId){......