实现1:
基于canvas 实现:
<template>
<view class="componentBox">
<!-- <view class="water_top" v-show="false">
<canvas id="watermark" type="2d"></canvas>
</view> -->
<slot></slot>
<view class="background" :style="{ zIndex, backgroundSize: `${(gapX + width) * 1.15}rpx`, backgroundImage: `url(${base64Url})` }"> </view>
</view>
</template>
<script>
/**
* @author: 1580043700@qq.com - Zhang Jun
* @date: 2023/02/18 10:00
* @description: 水印组件
*/
export default {
components: {},
props: {
content: {
type: String,
default: "人人都是生活家",
},
style: {
type: Object,
default: () => ({}),
},
markStyle: {
type: Object,
default: () => ({}),
},
zIndex: {
type: Number,
default: 10,
},
zIndex: {
type: Number,
default: 10,
},
gapX: {
type: Number,
default: 480,
},
gapX: {
type: Number,
default: 140,
},
width: {
type: Number,
default: 240,
},
height: {
type: Number,
default: 120,
},
},
data() {
return {
base64Url: "",
};
},
computed: {},
methods: {
initData() {
const { gapX = 212, gapY = 222, height, width, rotate = -25, fontFamily = "sans-serif", fontStyle = "normal", fontWeight = "normal", fontColor = "rgba(0,0,0,.15)", fontSize = 38, offsetLeft, offsetTop, content } = this;
// uni.createSelectorQuery()
// .in(this)
// .select("#watermark")
// .fields({ node: true, size: true })
// .exec(res => {
// let canvas = res[0]?.node;
//离屏渲染
const canvas = wx.createOffscreenCanvas({type: '2d', width, height})
if (canvas) {
const ctx = canvas.getContext("2d");
const ratio = this.getPixelRatio(ctx);
// const dpr = uni.getSystemInfoSync().pixelRatio;
const dpr = 3;
canvas.width = width * dpr;
canvas.height = height * dpr;
const canvasOffsetLeft = offsetLeft || gapX / 2;
const canvasOffsetTop = offsetTop || gapY / 2;
if (ctx) {
// 旋转字符 rotate
ctx.translate(canvasOffsetLeft * ratio, canvasOffsetTop * ratio * dpr);
ctx.rotate((Math.PI / 180) * Number(rotate));
const markHeight = height * ratio;
const markSize = Number(fontSize) * ratio;
// ctx.font = `${fontStyle} normal ${fontWeight} ${markSize}px/${markHeight}px ${fontFamily}`;
ctx.font = `${fontStyle} normal ${fontWeight} 38px/38px ${fontFamily}`;
ctx.fillStyle = fontColor;
ctx.fillText(content, -gapX / 2 + fontSize / 2, 0);
ctx.scale(dpr, dpr);
try {
this.base64Url = canvas.toDataURL();
} catch (error) {}
} else {
console.error("当前环境不支持Canvas");
}
} else {
console.error("当前环境不支持createOffscreenCanvas");
}
// });
},
getPixelRatio(context) {
return 1;
},
},
created() {},
mounted() {
this.initData();
},
destroyed() {},
};
</script>
<style scoped lang="scss">
.componentBox {
position: relative;
width: 100vw;
.background {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
pointer-events: none;
background-attachment: fixed;
background-repeat: repeat;
background-origin: content-box;
background-position: center;
}
}
</style>
实现2:
场景:部分手机对canvas支持不友好,PC端小程序对canvas接口不支持,所以放弃canvas实现。
uniapp代码:
<template>
<view class="componentBox">
<slot></slot>
<view class="backgroundBox">
<view class="background" v-for="item in domList" :style="[item]" :key="item">{{ content }} </view>
</view>
</view>
</template>
<script>
/**
* @author: 1580043700@qq.com - Zhang Jun
* @date: 2023/02/19 10:00
* @description: 水印组件
*/
export default {
components: {},
props: {
content: {
type: String,
default: "人人都是生活家",
},
zIndex: {
type: Number,
default: 999,
},
gapX: {
type: Number,
default: 0,
},
gapY: {
type: Number,
default: 20,
},
width: {
type: Number,
default: 0,
},
height: {
type: Number,
default: 80,
},
alpha: {
type: Number,
default: 0.4,
},
color: {
type: String,
default: "#aaa",
},
fontSize: {
type: Number,
default: 24,
},
angle: {
type: Number,
default: 20,
},
},
data() {
return {
domList: [],
};
},
computed: {},
methods: {
initData() {
uni.getSystemInfo({
success: res => {
let { screenWidth, screenHeight } = res;
let { gapX = 0, gapY = 0, width, height, color, alpha, fontSize, angle, zIndex } = this;
let heightNum = Math.ceil(screenHeight / (gapY * 2 + height));
let widthNum = Math.ceil(screenWidth / (gapX * 2 + (width || screenWidth / 2)));
let num = heightNum * widthNum;
for (let i = 0; i < num; i++) {
let mask_div = {};
mask_div.transform = "rotate(-" + angle + "deg)";
mask_div.visibility = "";
mask_div.overflow = "hidden";
mask_div.margin = `${gapY}px ${gapX}px`;
mask_div.zIndex = zIndex;
mask_div.pointerEvents = "none";
mask_div.opacity = alpha;
mask_div.fontSize = `${fontSize}rpx`;
mask_div.fontFamily = "微软雅黑";
mask_div.color = color;
mask_div.width = (width || screenWidth / 2) + "px";
mask_div.height = height + "px";
this.domList.push(mask_div);
}
},
});
},
},
created() {},
mounted() {
this.initData();
},
destroyed() {},
};
</script>
<style scoped lang="scss">
.componentBox {
position: relative;
width: 100vw;
.backgroundBox {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
pointer-events: none;
display: flex;
flex-wrap: wrap;
z-index: 10;
.background {
box-sizing: border-box;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
pointer-events: none;
background-attachment: fixed;
background-repeat: repeat;
background-origin: content-box;
background-position: center;
}
}
}
</style>
效果:
image.png
网友评论