Demo: 给图片添加自定义水印并下载

给图片添加自定义水印并下载

javascript 复制代码
<template>
  <div class="wrap">
    <div class="optea">
      <p>水印文字</p>
      <el-input v-model="watermarkOptions.text" placeholder="请输入水印内容"></el-input>
      <p>字体颜色</p>
      <el-color-picker v-model="watermarkOptions.color"></el-color-picker>
      <p>旋转角度</p>
      <el-slider v-model="watermarkOptions.rotate" :min="0" :max="360"></el-slider>
      <p>透明度</p>
      <el-slider v-model="watermarkOptions.alpha" :min="0" :max="100"></el-slider>
      <p>文本间距</p>
      <el-slider v-model="watermarkOptions.width" :min="0" :max="100"></el-slider>
      <p>字体大小</p>
      <el-slider v-model="watermarkOptions.fontSize" :min="0" :step="0.5" :max="50"></el-slider>
    </div>
    <div class="previewImage">
      <el-button
        @click="handleDown"
        class="download-btn"
        type="primary"
        plain
        icon="el-icon-download"
        >下载水印图片</el-button
      >
      <div class="preview" ref="previewImg">
        <img :src="preImg" alt="" />
        <div class="watermark" :style="{ background: paint }"></div>
      </div>
    </div>
  </div>
</template>
<script setup>
import DomToImage from 'dom-to-image'
import { ref, reactive, computed } from 'vue'

const previewImg = ref(null)
const watermarkOptions = reactive({
  text: '仅供 xxx 验证使用',
  fontSize: 10,
  width: 5,
  color: '#000000',
  alpha: 35,
  rotate: 35
})

defineProps({
  preImg: {
    type: String,
    default: ''
  }
})

const handleDown = () => {
  let node = previewImg.value
  DomToImage.toPng(node)
    .then(function (dataUrl) {
      var oLink = document.createElement('a')
      oLink.download = '水印图片.png'
      oLink.href = dataUrl
      oLink.click()
    })
    .catch(function (error) {
      console.error('oops, something went wrong!', error)
    })
}

const paint = computed(() => {
  const wordWidth = watermarkOptions.fontSize * watermarkOptions.text.split('').length
  const width = wordWidth + watermarkOptions.width

  let svgText = `
    <svg xmlns="http://www.w3.org/2000/svg" width="${width}px" height="${width}px">
    <text x="50%" y="50%"
        alignment-baseline="middle"
        text-anchor="middle"
        stroke="${watermarkOptions.color}"
        opacity="${watermarkOptions.alpha / 100}"
        transform="translate(${width / 2}, ${width / 2}) rotate(${
          watermarkOptions.rotate
        }) translate(-${width / 2}, -${width / 2})"
        font-weight="100"
        font-size="${watermarkOptions.fontSize}"
        font-family="microsoft yahe"
        >
        ${watermarkOptions.text}
    </text>
   </svg>`
  return `url(data:image/svg+xml;base64,${btoa(unescape(encodeURIComponent(svgText)))})`
})
</script>

<style lang="scss" scoped>
.wrap {
  padding: 10px 20px;
  display: flex;
  justify-content: flex-start;
  align-items: center;

  .optea {
    // width: 500px;
    margin-right: 20px;

    p {
      margin: 5px 0;
      margin-bottom: 10px;
      font-weight: 600;
    }
  }

  .previewImage {
    .download-btn {
      margin: 0 15px 15px;
    }

    .preview {
      position: relative;
      min-width: 520px;
      max-height: 800px;

      img {
        width: 100%;
        max-height: 800px;
      }

      .watermark {
        position: absolute;
        left: 0;
        top: 0;
        width: 100%;
        height: 100%;
      }
    }
  }
}
</style>
相关推荐
烛阴10 小时前
从0到1掌握盒子模型:精准控制网页布局的秘诀
前端·javascript·css
七八书13 小时前
Vue3 组件通信全解析:从基础到进阶的实用指南
vue.js
用户38022585982413 小时前
vue3源码解析:模块总览
vue.js
Danny_FD13 小时前
React中可有可无的优化-对象类型的使用
前端·javascript
LeeAt14 小时前
从Promise到async/await的逻辑演进
前端·javascript
前端Hardy14 小时前
HTML&CSS:3D 轮播图全攻略
前端·javascript
前端Hardy14 小时前
7 个技巧助你写出优雅高效的 JavaScript 异步代码
前端·javascript·面试
等一个晴天丶14 小时前
element-ui elemant-plus el-tree展开按钮变成加减号
vue.js
HelloWord14 小时前
从零到一搭建vue3+ts项目
前端·vue.js
走向终结的前端15 小时前
vue中再搞一下SSE的使用
前端·javascript