uniapp-微信小程序添加頁面水印功能

實現(xiàn)1:
基于canvas 實現(xiàn):


<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("當前環(huán)境不支持Canvas");
                        }
                    } else {
                        console.error("當前環(huán)境不支持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>


實現(xiàn)2:

場景:部分手機對canvas支持不友好,PC端小程序對canvas接口不支持姥饰,所以放棄canvas實現(xiàn)。

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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子镇防,更是在濱河造成了極大的恐慌,老刑警劉巖潮饱,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件营罢,死亡現(xiàn)場離奇詭異,居然都是意外死亡饼齿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進店門蝙搔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缕溉,“玉大人,你說我怎么就攤上這事吃型≈づ福” “怎么了?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵勤晚,是天一觀的道長枉层。 經常有香客問我,道長赐写,這世上最難降的妖魔是什么鸟蜡? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮挺邀,結果婚禮上揉忘,老公的妹妹穿的比我還像新娘。我一直安慰自己端铛,他們只是感情好泣矛,可當我...
    茶點故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著禾蚕,像睡著了一般您朽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上换淆,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天哗总,我揣著相機與錄音几颜,去河邊找鬼。 笑死魂奥,一個胖子當著我的面吹牛菠剩,可吹牛的內容都是我干的。 我是一名探鬼主播耻煤,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼具壮,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了哈蝇?” 一聲冷哼從身側響起棺妓,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎炮赦,沒想到半個月后怜跑,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡吠勘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年性芬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剧防。...
    茶點故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡植锉,死狀恐怖,靈堂內的尸體忽然破棺而出峭拘,到底是詐尸還是另有隱情俊庇,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布鸡挠,位于F島的核電站辉饱,受9級特大地震影響,放射性物質發(fā)生泄漏拣展。R本人自食惡果不足惜彭沼,卻給世界環(huán)境...
    茶點故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望备埃。 院中可真熱鬧溜腐,春花似錦、人聲如沸瓜喇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽乘寒。三九已至望众,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背烂翰。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工夯缺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人甘耿。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓踊兜,卻偏偏與公主長得像,于是被迫代替她去往敵國和親佳恬。 傳聞我的和親對象是個殘疾皇子捏境,可洞房花燭夜當晚...
    茶點故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內容