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>
相关推荐
励志码农1 小时前
JavaWeb 30 天入门:第二十三天 —— 监听器(Listener)
java·开发语言·spring boot·学习·servlet
天高云淡ylz1 小时前
子网掩码的隐形陷阱:为何能ping通却无法HTTPS访问
开发语言·php
哆啦A梦15881 小时前
[前台小程序] 01 项目初始化
前端·vue.js·uni-app
智码看视界2 小时前
老梁聊全栈系列:(阶段一)架构思维与全局观
java·javascript·架构
希望20173 小时前
Golang Panic & Throw & Map/Channel 并发笔记
开发语言·golang
朗迹 - 张伟3 小时前
Golang安装笔记
开发语言·笔记·golang
yzx9910133 小时前
生活在数字世界:一份人人都能看懂的网络安全生存指南
运维·开发语言·网络·人工智能·自动化
小周同学@3 小时前
谈谈对this的理解
开发语言·前端·javascript
Wiktok4 小时前
Pyside6加载本地html文件并实现与Javascript进行通信
前端·javascript·html·pyside6
一只小风华~4 小时前
Vue:条件渲染 (Conditional Rendering)
前端·javascript·vue.js·typescript·前端框架