在uniapp中我想在根节点下添加一个全局水印组件
我尝试在app.vue中添加但是没有生效
App.vue
本身并不是一个页面,而是应用的根组件。要在所有页面中显示全局水印组件,可以使用以下方法:
在 components
目录下创建一个 Watermark.vue
文件,并添加以下代码:
<!-- components/Watermark.vue -->
<template>
<view class="watermark-box" :style="{ backgroundImage: `url(${watermark})`, backgroundSize: `auto ${height}px` }">
<canvas id="watermark" class="watermark" canvas-id="watermark" />
</view>
</template>
<script>
export default {
name: 'Watermark',
data() {
return {
watermark: '',
width: '',
height: ''
};
},
mounted() {
this.initWatermark();
},
methods: {
initWatermark() {
const watermarkText = '水印';
const ctx = uni.createCanvasContext('watermark');
const fontSize = 14;
const rotateRad = 30 * Math.PI / 180;
const cosRad = Math.cos(rotateRad);
const sinRad = Math.sin(rotateRad);
const { width: fontRealWidth } = ctx.measureText(watermarkText);
const recWidth = Math.ceil(fontRealWidth * cosRad + fontSize * sinRad);
const recHeight = Math.ceil(fontSize * cosRad + fontRealWidth * sinRad);
const width = parseInt(recWidth * 2);
const height = parseInt(recHeight * 2.5);
const x = parseInt((width - recWidth) / 2);
const y = parseInt((height + recHeight) / 2);
this.width = width;
this.height = height;
ctx.width = this.width;
ctx.height = this.height;
ctx.setGlobalAlpha(0.3);
ctx.setFontSize(fontSize);
ctx.setFillStyle('#c8c8c8');
ctx.translate(x, y);
ctx.rotate(-rotateRad);
ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
ctx.fillText(watermarkText, 0, 0);
ctx.draw(true, () => {
uni.canvasToTempFilePath({
canvasId: 'watermark',
width: this.width,
height: this.height,
quality: 1,
fileType: 'png',
success: (res) => {
this.watermark = res.tempFilePath;
}
});
});
}
}
};
</script>
<style scoped>
.watermark-box {
overflow: hidden;
width: 100%;
height: 100vh;
pointer-events: none;
position: fixed;
top: 0;
left: 0;
background-repeat: repeat;
}
.watermark {
z-index: -1;
}
</style>
在 App.vue 中使用 router-view: 虽然 App.vue 没有传统的 template 部分,但你可以在 render 函数中使用 router-view 来显示当前匹配的路由组件
在 App.vue
中引入并使用水印组件:
<!-- App.vue -->
<template>
<view>
<Watermark />
<router-view />
</view>
</template>
<script>
import Watermark from '@/components/Watermark.vue';
export default {
components: {
Watermark
}
};
</script>
在全局样式文件中(如 App.vue
或 main.css
),确保没有覆盖水印组件的样式:
/* App.vue 或 main.css 中 */
body, html {
height: 100%;
margin: 0;
padding: 0;
}
// --snip--
import { readFileSync } from 'fs';
import { resolve } from 'path';
// 为所有页面插入<watermark />组件, 再去编译
export default function insertWaterMarkPlugin() {
return {
name: 'insert-water-mark-plugin',
async transform(code, id) {
if (id.endsWith('.vue')) {
const filePath = resolve(id);
if (filePath.includes('src\\packages\\') || filePath.includes('src\\pages\\')) {
const fileContent = readFileSync(filePath, 'utf-8');
const modifiedCode = fileContent.replace(
'<template>',
'<template><watermark />'
);
return {
code: modifiedCode,
map: null
}
}
}
return null
}
};
}
export default defineConfig({
plugins: [
insertWaterMarkPlugin(), // 加这一行
uni()
]
})
1 回答5.3k 阅读✓ 已解决
3 回答1.5k 阅读✓ 已解决
2 回答3.6k 阅读
1 回答2.2k 阅读✓ 已解决
1 回答1.4k 阅读✓ 已解决
2 回答2.1k 阅读
uni-app 中
App.vue
本身不是页面,这里不能编写视图元素,也就是没有<template>
。👉 App.vue/App.uvue | uni-app官网
社区有一个解决方案 vue-inset-loader。不过需要改造成 CLI构建的项目 才行。而且构建成非小程序产物的话,还需要改一下 vue-inset-loader/main/index.js 中的代码,去掉
weixin
的判断。