vue之原生上传图片加水印并压缩图片大小(2)

该博客介绍了如何在Vue.js环境下实现PC端的图片上传功能,包括图片格式和大小限制,以及图片的压缩和添加水印。通过compressorjs和html2canvas库,实现了图片压缩和水印添加,确保图片质量的同时,增强了图片的版权保护。此外,代码示例详细展示了整个流程,适合前端开发者参考使用。
摘要由CSDN通过智能技术生成

vue之原生上传图片并压缩图片大小

vue之PC原生上传图片加水印

<template>
  <div class="content-box">
    <div class="container">
      <div class="title">
        点击上传图像(支持image/jpg,image/jpeg,image/png,image/gif格式图片且大小不能超过10MB)
      </div>
      <div class="uploadImg">
        <span class="el-icon-plus"></span>
        <input
          :accept="accept"
          type="file"
          class="upload_ipu"
          ref="fileLoad"
          @change="uploadImg"
        />
      </div>
      <div class="imgList">
        <img v-if="imgShow" :src="imgSrc"/>
      </div>
      <!-- 图片上传水印 -->
      <div id="markImg">
        <div class="logo">
          <img src="@/assets/logo.png" />
          图片水印
        </div>
        <p>
          {{ parseTime(fileDate, '{y}-{m}-{d} {h}:{i}:{s}') }}{{
            parseTime(fileDate, '{a}')
          }}
        </p>
        <p>{{ loginName }}</p>
      </div>
    </div>
  </div>
</template>

<script>
import { parseTime } from '@/utils'
import { compressor, addWaterMarker } from '@/utils/waterMarker'
export default {
  props: {
    accept: {
      type: String,
      default: 'image/jpg,image/jpeg,image/png,image/gif'
    }
  },
  data() {
    return {
      imgShow: false,
      imgSrc: '',
      loginName: 'fqniu',
      fileDate: new Date(),
      needWaterMark: true
    }
  },
  created() {
    this.parseTime = parseTime
  },
  methods: {
    createUrl(file) {
      if (window.URL) {
        return window.URL.createObjectURL(file)
      } else if (window.webkitURL) {
        return window.webkitURL.createObjectURL(file)
      } else {
        return null
      }
    },
    async uploadImg() {
      // 这个是元素dom节点
      console.log(this.$refs.fileLoad);
      // 上传文件fileList
      console.log(this.$refs.fileLoad.files);
      let file = this.$refs.fileLoad.files[0]
      let size = file.size / 1024 / 1024
      console.log(file, file.lastModifiedDate)
      if (!this.accept.includes(file.type.toLowerCase())) {
        this.$message.error('图片格式不正确!')
        return false
      }
      if (size > 10) {
        this.$message.error('图片大小不能超过10MB!')
        return false
      }
      // 压缩图片
      if (file.size > 512 * 1024 && file.type.includes('image/')) {
        file = await compressor(file)
      }
      // 添加水印
      if (this.needWaterMark) {
        const fileName = file.name
        file = await addWaterMarker(file, '#markImg', 'leftDown')
        file.name = fileName
      }
      this.imgSrc = this.createUrl(file)
      this.imgShow = true
      this.$message.success('上传成功!')
    }
  }
}
</script>

<style lang="scss" scoped>
.title {
  font-size: 16px;
  color: #aaa;
}
.uploadImg {
  margin-top: 20px;
  border: 1px dashed #d9d9d9;
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  width: 180px;
  height: 180px;
  transition: all 0.2s;
  &:hover {
    border-color: #409eff;
  }
  span {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    line-height: 178px;
    text-align: center;
  }
  .upload_ipu {
    opacity: 0;
    width: 100%;
    height: 100%;
    position: absolute;
    cursor: pointer;
    top: 0;
    left: 0;
    z-index: 2;
  }
  img {
    width: 178px;
    height: 178px;
    position: absolute;
    border-radius: 6px;
    left: 0;
    top: 0;
    z-index: 1;
  }
}
.imgList {
  width: 550px;
  height: 400px;
  img {
    width: 100%;
    height: 100%;
  }
}
// 水印样式
#markImg {
  position: absolute;
  left: -9999999px;
  text-align: left;
  padding: 10px 15px;
  .logo {
    font-weight: 600;
    font-size: 15px;
    color: #ffffff;
    display: flex;
    height: 21px;
    align-items: center;
    justify-content: flex-start;
    img {
      height: 21px;
      margin-right: 5px;
    }
  }
  p {
    margin-top: 6px;
    color: #ffffff;
    font-size: 12px;
    font-weight: 400;
  }
}
</style>

封装水印方法如下

感谢龙哥帮忙指导



import Compressor from 'compressorjs'
import html2canvas from 'html2canvas'


/**
 * 压缩和旋转图片
 * @param {blob} file
 * @param {number} quality  压缩比例
 * @param {number} maxWidth
 * @returns {Promise}
 */
 export function compressor(file, drew, maxWidth = 750, quality = 0.6) {
  return new Promise(resolve => {
    new Compressor(file, {
      strict: false,
      maxWidth,
      quality,
      drew,
      success: resolve,
      error(err) {
        console.log(err.message)
      }
    })
  })
}

/**
 * 添加水印
 * @param {blob} file
 * @param {string} el
 * @returns {Promise}
 */
 export async function addWaterMarker(file, el = '#markImg', direction = 'rightDown') {
  return new Promise(async (resolve, reject) => {
    try {
      const maxWidth = 750
      const img = await blobToImg(file)
      const imgWidth = img.naturalWidth > maxWidth ? maxWidth : img.naturalWidth

      // 生成水印图片
      const markEle = document.querySelector(el)
      const scale = imgWidth * 0.25 / markEle.clientWidth
      // 先缩放水印再转成图片
      markEle.style.transform = `scale(${scale})`
      const markImg = await htmlToCanvas(markEle)

      // 先压缩和旋转图片
      file = await compressor(file, (context, canvas) => {
        if(direction == 'rightDown'){
          // 填充水印 右下角
          context.drawImage(markImg, canvas.width - markImg.width - 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)
        } else {
          // 填充水印 左下角
          context.drawImage(markImg, 15 * scale, canvas.height - markImg.height - 15 * scale, markImg.width, markImg.height)
        }
      }, maxWidth)
      resolve(file)
    } catch (error) {
      reject(error)
    }
  })
}

function blobToImg(blob) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader()
    reader.addEventListener('load', () => {
      let img = new Image()
      img.src = reader.result
      img.addEventListener('load', () => resolve(img))
    })
    reader.readAsDataURL(blob)
  })
}

export function htmlToCanvas(el, backgroundColor = 'rgba(0,0,0,.1)') {
  return new Promise(async (resolve, reject) => {
    try {
      const markImg = await html2canvas(el, {
        scale: 2,
        allowTaint: false,   //允许污染
        useCORS: true,
        backgroundColor //'transparent'  //背景色
      })
      resolve(markImg)
    } catch (error) {
      reject(error)
    }
  })
}

在这里插入图片描述
在这里插入图片描述
以上代码可以直接使用

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值