|
@@ -0,0 +1,101 @@
|
|
|
+<template>
|
|
|
+ <div class="image-watermark">
|
|
|
+ <img v-if="dataUrl" :src="dataUrl" />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ name: "image-watermark",
|
|
|
+ props: {
|
|
|
+ url: String,
|
|
|
+ content: String,
|
|
|
+ },
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ loading: false,
|
|
|
+ errorMsg: "",
|
|
|
+ dataUrl: "",
|
|
|
+ };
|
|
|
+ },
|
|
|
+ mounted() {
|
|
|
+ this.initData();
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async initData() {
|
|
|
+ if (!this.url) return;
|
|
|
+
|
|
|
+ this.loading = true;
|
|
|
+
|
|
|
+ const image = await this.loadingImg(this.url).catch(() => {});
|
|
|
+ if (!image) {
|
|
|
+ this.loading = false;
|
|
|
+ this.errorMsg = "图片载入失败!";
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ const canvas = document.createElement("canvas");
|
|
|
+ const ctx = canvas.getContext("2d");
|
|
|
+
|
|
|
+ canvas.width = image.naturalWidth;
|
|
|
+ canvas.height = image.naturalHeight;
|
|
|
+ ctx.drawImage(image, 0, 0);
|
|
|
+
|
|
|
+ this.drawWatermark(ctx, { width: canvas.width, height: canvas.height });
|
|
|
+
|
|
|
+ canvas.toBlob((val) => {
|
|
|
+ this.loading = false;
|
|
|
+ if (!val) return;
|
|
|
+ this.dataUrl = URL.createObjectURL(val);
|
|
|
+ });
|
|
|
+ },
|
|
|
+ loadingImg(url) {
|
|
|
+ return new Promise((reslove, reject) => {
|
|
|
+ const img = new Image();
|
|
|
+ img.src = url;
|
|
|
+ img.onload = () => {
|
|
|
+ reslove(img);
|
|
|
+ };
|
|
|
+ img.onerror = (e) => {
|
|
|
+ reject(e);
|
|
|
+ };
|
|
|
+ });
|
|
|
+ },
|
|
|
+ drawWatermark(ctx, { width, height }) {
|
|
|
+ const angle = (315 * Math.PI) / 180;
|
|
|
+ const fontSize = 100;
|
|
|
+ ctx.font = `${fontSize}px serif`;
|
|
|
+ ctx.fillStyle = "rgba(212,212,212,0.5)";
|
|
|
+
|
|
|
+ // 获取内容的宽度
|
|
|
+ const cInfo = ctx.measureText(this.content);
|
|
|
+
|
|
|
+ const initWH = [50, 50];
|
|
|
+ const spacing = [width / 3, height / 3];
|
|
|
+ const spaceSize = Math.max(width, height) * 1.5;
|
|
|
+ const spaceWH = [cInfo.width + spacing[0], fontSize + spacing[1]];
|
|
|
+ const wCount = Math.ceil(spaceSize / spaceWH[0]);
|
|
|
+ const hCount = Math.ceil(spaceSize / spaceWH[1]);
|
|
|
+
|
|
|
+ ctx.translate(-width / 2, height / 2);
|
|
|
+ ctx.rotate(angle);
|
|
|
+
|
|
|
+ for (let i = 0; i < wCount; i++) {
|
|
|
+ for (let j = 0; j < hCount; j++) {
|
|
|
+ const x = initWH[0] + i * spaceWH[0];
|
|
|
+ const y = initWH[1] + j * spaceWH[1];
|
|
|
+ ctx.fillText(this.content, x, y);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+};
|
|
|
+</script>
|
|
|
+
|
|
|
+<style>
|
|
|
+.image-watermark img {
|
|
|
+ display: block;
|
|
|
+ width: 100%;
|
|
|
+ height: auto;
|
|
|
+}
|
|
|
+</style>
|