201 lines
5.3 KiB
Vue
201 lines
5.3 KiB
Vue
<template>
|
|
<view
|
|
:class="classPrefix + ' ' + tClass"
|
|
:style="tools._style([customStyle])"
|
|
>
|
|
<block v-if="content">
|
|
{{ content }}
|
|
</block>
|
|
<slot name="content" />
|
|
<slot />
|
|
<canvas
|
|
:id="canvasId"
|
|
:canvas-id="canvasId"
|
|
type="2d"
|
|
:style="canvasStyle"
|
|
/>
|
|
<view
|
|
:class="movable ? 'watermark-move' : ''"
|
|
:style="tools._style(watermarkStyle)"
|
|
/>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import tools from '../common/utils.wxs';
|
|
import watermarkProps from './props';
|
|
import { prefix } from '../common/config';
|
|
import { uniComponent } from '../common/src/index';
|
|
import { appBaseInfo, nextTick } from '../common/utils';
|
|
import generateBase64Url from './utils/generateBase64Url';
|
|
import randomMovingStyle from './utils/randomMovingStyle';
|
|
|
|
const name = `${prefix}-watermark`;
|
|
|
|
export default uniComponent({
|
|
name,
|
|
options: {
|
|
styleIsolation: 'shared',
|
|
},
|
|
externalClasses: [`${prefix}-class`],
|
|
props: {
|
|
...watermarkProps,
|
|
},
|
|
data() {
|
|
return {
|
|
classPrefix: name,
|
|
tools,
|
|
watermarkStyle: {},
|
|
initialed: false,
|
|
canvasId: `watermark-canvas-${Math.random().toString(36)
|
|
.slice(2, 11)}`,
|
|
};
|
|
},
|
|
computed: {
|
|
canvasStyle() {
|
|
let result = 'width: 100px; height: 100px;';
|
|
let shouldHide = true;
|
|
|
|
// #ifdef APP-PLUS || MP-ALIPAY
|
|
if (!this.initialed) {
|
|
shouldHide = false;
|
|
}
|
|
// #endif
|
|
|
|
if (shouldHide) {
|
|
result += 'display: none;';
|
|
}
|
|
return result;
|
|
},
|
|
},
|
|
watch: {
|
|
watermarkContent: 'renderWatermark',
|
|
movable: 'renderWatermark',
|
|
rotate: 'renderWatermark',
|
|
x: 'renderWatermark',
|
|
y: 'renderWatermark',
|
|
width: 'renderWatermark',
|
|
height: 'renderWatermark',
|
|
alpha: 'renderWatermark',
|
|
lineSpace: 'renderWatermark',
|
|
moveInterval: 'renderWatermark',
|
|
zIndex: 'renderWatermark',
|
|
offset: 'renderWatermark',
|
|
removable: 'renderWatermark',
|
|
isRepeat: 'renderWatermark',
|
|
layout: 'renderWatermark',
|
|
},
|
|
async mounted() {
|
|
await nextTick();
|
|
this.renderWatermark();
|
|
},
|
|
methods: {
|
|
watermarkColor() {
|
|
return appBaseInfo.theme === 'dark'
|
|
? 'rgba(238, 238, 238, 0.1)'
|
|
: 'rgba(0, 0, 0, 0.1)';
|
|
},
|
|
renderWatermark() {
|
|
const query = uni.createSelectorQuery().in(this);
|
|
|
|
query
|
|
.select(`#${this.canvasId}`)
|
|
.fields({ node: true, size: true })
|
|
.exec(async (res) => {
|
|
if (!res[0]?.node) {
|
|
console.error('Canvas node not found');
|
|
return;
|
|
}
|
|
const canvas = res[0].node;
|
|
const gapX = this.movable ? 0 : this.x;
|
|
const gapY = this.movable ? 0 : this.y;
|
|
const offset = this.offset || [];
|
|
const offsetLeft = offset[0] || gapX / 2;
|
|
const offsetTop = offset[1] || gapY / 2;
|
|
|
|
const bgImageOptions = {
|
|
width: this.width,
|
|
height: this.height,
|
|
rotate: this.movable ? 0 : this.rotate,
|
|
lineSpace: this.lineSpace,
|
|
alpha: this.alpha,
|
|
gapX,
|
|
gapY,
|
|
watermarkContent: this.watermarkContent,
|
|
offsetLeft,
|
|
offsetTop,
|
|
watermarkColor: this.watermarkColor(),
|
|
layout: this.layout,
|
|
};
|
|
generateBase64Url.call(
|
|
this,
|
|
canvas,
|
|
this.canvasId,
|
|
bgImageOptions,
|
|
(base64Url, backgroundSize) => {
|
|
let animationVars = {};
|
|
if (this.movable) {
|
|
const {
|
|
left0,
|
|
left25,
|
|
left50,
|
|
left75,
|
|
top0,
|
|
top25,
|
|
top50,
|
|
top75,
|
|
} = randomMovingStyle();
|
|
animationVars = {
|
|
'--watermark-left-0': left0,
|
|
'--watermark-left-25': left25,
|
|
'--watermark-left-50': left50,
|
|
'--watermark-left-75': left75,
|
|
'--watermark-top-0': top0,
|
|
'--watermark-top-25': top25,
|
|
'--watermark-top-50': top50,
|
|
'--watermark-top-75': top75,
|
|
'--watermark-animation-duration': `${
|
|
(this.moveInterval * 4) / 60
|
|
}s`,
|
|
};
|
|
}
|
|
|
|
this.watermarkStyle = {
|
|
zIndex: this.zIndex,
|
|
position: 'absolute',
|
|
left: 0,
|
|
right: 0,
|
|
top: 0,
|
|
bottom: 0,
|
|
width: '100%',
|
|
height: '100%',
|
|
backgroundSize: `${
|
|
backgroundSize?.width || gapX + this.width
|
|
}px`,
|
|
pointerEvents: 'none',
|
|
backgroundRepeat: this.movable ? 'no-repeat' : 'repeat',
|
|
backgroundImage: `url('${base64Url}')`,
|
|
...animationVars,
|
|
};
|
|
},
|
|
() => {
|
|
this.initialed = true;
|
|
},
|
|
).catch((e) => {
|
|
console.log('e', e);
|
|
});
|
|
});
|
|
},
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
@import './watermark.css';
|
|
|
|
/* diff with td-mini */
|
|
.watermark-move {
|
|
animation: watermark var(--watermark-animation-duration, 100s) linear infinite;
|
|
}
|
|
</style>
|