mirror of
https://gitee.com/vant-contrib/vant.git
synced 2025-04-24 10:20:19 +08:00
feat(Watermark): add new Watermark component (#11721)
* feat(watermark): add watermark component * docs(watermark): i18n * feat(watermark): revoke useless url * feat(watermark): add opacity, replace fullPage default to true, replace Zindex default to 100, replace fontColor default to #dedee0 * test(watermark): add watermark snap test * docs(watermark): fix opacity and default value
This commit is contained in:
parent
cac003cef5
commit
69b113717f
119
packages/vant/src/watermark/README.md
Normal file
119
packages/vant/src/watermark/README.md
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# Watermark
|
||||||
|
|
||||||
|
### Intro
|
||||||
|
|
||||||
|
Add watermark for page.
|
||||||
|
|
||||||
|
### Install
|
||||||
|
|
||||||
|
Register component globally via `app.use`, refer to [Component Registration](#/en-US/advanced-usage#zu-jian-zhu-ce) for more registration ways.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createApp } from 'vue';
|
||||||
|
import { Watermark } from 'vant';
|
||||||
|
|
||||||
|
const app = createApp();
|
||||||
|
app.use(Watermark);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### Basic Usage
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- text watermark -->
|
||||||
|
<van-watermark content="Vant" />
|
||||||
|
|
||||||
|
<!-- image watermark -->
|
||||||
|
<van-watermark image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Gap
|
||||||
|
|
||||||
|
Use `gapX` `gapY` attributes to control the gap between two watermark slice.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
:gap-x="20"
|
||||||
|
:gap-y="10"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Opacity
|
||||||
|
|
||||||
|
Use `opacity` attribute to control the entirety opacity.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
:opacity="0.5"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Custom Rotate
|
||||||
|
|
||||||
|
Use `rotate` attribute to control the rotate of watermark. Default value is `-22`.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
rotate="22"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Display Range
|
||||||
|
|
||||||
|
Use the `fullPage` attribute to control the display range of the watermark.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark
|
||||||
|
:full-page="true"
|
||||||
|
content="vant watermark"
|
||||||
|
font-color="rgba(0, 0, 0, 0.15)"
|
||||||
|
>
|
||||||
|
</van-watermark>
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTML Watermark
|
||||||
|
|
||||||
|
Use the `default slot` to pass HTML directly. Inline styles are supported, and self-closing tags are not supported.
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark :width="150">
|
||||||
|
<div style="background: linear-gradient(45deg, #000 0, #000 50%, #fff 50%)">
|
||||||
|
<p style="mix-blend-mode: difference; color: #fff">Vant watermark</p>
|
||||||
|
</div>
|
||||||
|
</van-watermark>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| Attribute | Description | Type | Default |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| width | Watermark width | _number_ | 100 |
|
||||||
|
| height | Watermark height | _number_ | 100 |
|
||||||
|
| zIndex | Watermark's z-index | _number_ | 100 |
|
||||||
|
| content | Text watermark content | _string_ | - |
|
||||||
|
| image | Image watermark content. If `content` and `image` are passed at the same time, use the `image` watermark first | _string_ | - |
|
||||||
|
| fullPage | Whether to display the watermark in full screen | _boolean_ | true |
|
||||||
|
| gapX | Horizontal spacing between watermarks | _number_ | 0 |
|
||||||
|
| gapY | Vertical spacing between watermarks | _number_ | 0 |
|
||||||
|
| fontColor | Color of text watermark | _string_ | #dcdee0 |
|
||||||
|
| opacity | opacity of watermark | _number_ | 1 |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| Attribute | Description |
|
||||||
|
| --- | --- |
|
||||||
|
| default | Content of HTML watermark. Inline styles are supported, and self-closing tags are not supported. This slot is invalid if `content` or `image` is passed |
|
||||||
|
|
||||||
|
### Types
|
||||||
|
|
||||||
|
The component exports the following type definitions:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { WaterProps } from 'vant';
|
||||||
|
```
|
119
packages/vant/src/watermark/README.zh-CN.md
Normal file
119
packages/vant/src/watermark/README.zh-CN.md
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
# Watermark 水印
|
||||||
|
|
||||||
|
### 介绍
|
||||||
|
|
||||||
|
页面上添加特定的文字或图案,可用于防止信息盗用
|
||||||
|
|
||||||
|
### 引入
|
||||||
|
|
||||||
|
通过以下方式来全局注册组件,更多注册方式请参考[组件注册](#/zh-CN/advanced-usage#zu-jian-zhu-ce)。
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { createApp } from 'vue';
|
||||||
|
import { Watermark } from 'vant';
|
||||||
|
|
||||||
|
const app = createApp();
|
||||||
|
app.use(Watermark);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 代码演示
|
||||||
|
|
||||||
|
### 基础用法
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- 文字水印 -->
|
||||||
|
<van-watermark content="Vant" />
|
||||||
|
|
||||||
|
<!-- 图片水印 -->
|
||||||
|
<van-watermark image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg" />
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义间隔
|
||||||
|
|
||||||
|
通过 `gapX` `gapY` 属性来控制重复水印之间的间隔。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
:gap-x="20"
|
||||||
|
:gap-y="10"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义透明度
|
||||||
|
|
||||||
|
通过 `opacity` 属性来控制水印的整体透明度。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
:opacity="0.5"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自定义倾斜角度
|
||||||
|
|
||||||
|
通过 `rotate` 属性来控制水印的倾斜角度,默认值为`-22`。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
rotate="22"
|
||||||
|
/>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 显示范围
|
||||||
|
|
||||||
|
通过 `fullPage` 属性来控制水印的显示范围。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark
|
||||||
|
:full-page="true"
|
||||||
|
content="vant watermark"
|
||||||
|
font-color="rgba(0, 0, 0, 0.15)"
|
||||||
|
>
|
||||||
|
</van-watermark>
|
||||||
|
```
|
||||||
|
|
||||||
|
### HTML 水印
|
||||||
|
|
||||||
|
通过默认插槽可以直接传入 HTML,HTML 样式仅支持行内样式同时不支持传入自闭合标签。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<van-watermark :width="150">
|
||||||
|
<div style="background: linear-gradient(45deg, #000 0, #000 50%, #fff 50%)">
|
||||||
|
<p style="mix-blend-mode: difference; color: #fff">Vant watermark</p>
|
||||||
|
</div>
|
||||||
|
</van-watermark>
|
||||||
|
```
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
### Props
|
||||||
|
|
||||||
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| width | 水印宽度 | _number_ | 100 |
|
||||||
|
| height | 水印高度 | _number_ | 100 |
|
||||||
|
| zIndex | 水印的 z-index | _number_ | 100 |
|
||||||
|
| content | 文字水印的内容 | _string_ | - |
|
||||||
|
| image | 图片水印的内容,如果与 content 同时传入,优先使用图片水印 | _string_ | - |
|
||||||
|
| fullPage | 水印是否全屏显示 | _boolean_ | false |
|
||||||
|
| gapX | 水印水平间隔 | _number_ | 0 |
|
||||||
|
| gapY | 水印垂直间隔 | _number_ | 0 |
|
||||||
|
| fontColor | 文字水印的颜色 | _string_ | #dcdee0 |
|
||||||
|
| opacity | 水印的透明度 | _number_ | 1 |
|
||||||
|
|
||||||
|
### Slots
|
||||||
|
|
||||||
|
| 名称 | 说明 |
|
||||||
|
| --- | --- |
|
||||||
|
| default | HTML 水印的内容,仅支持行内样式同时不支持传入自闭合标签,存在 content 或 image 时此插槽无效 |
|
||||||
|
|
||||||
|
### 类型定义
|
||||||
|
|
||||||
|
组件导出以下类型定义:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import type { WaterProps } from 'vant';
|
||||||
|
```
|
184
packages/vant/src/watermark/Watermark.tsx
Normal file
184
packages/vant/src/watermark/Watermark.tsx
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
import {
|
||||||
|
defineComponent,
|
||||||
|
nextTick,
|
||||||
|
onUnmounted,
|
||||||
|
ref,
|
||||||
|
watch,
|
||||||
|
watchEffect,
|
||||||
|
type ExtractPropTypes,
|
||||||
|
} from 'vue';
|
||||||
|
import {
|
||||||
|
createNamespace,
|
||||||
|
makeNumberProp,
|
||||||
|
makeNumericProp,
|
||||||
|
makeStringProp,
|
||||||
|
truthProp,
|
||||||
|
} from '../utils';
|
||||||
|
|
||||||
|
const [name, bem] = createNamespace('watermark');
|
||||||
|
|
||||||
|
export const watermarkProps = {
|
||||||
|
width: makeNumberProp(100),
|
||||||
|
height: makeNumberProp(100),
|
||||||
|
rotate: makeNumericProp(-22),
|
||||||
|
zIndex: makeNumberProp(100),
|
||||||
|
content: String,
|
||||||
|
image: String,
|
||||||
|
fullPage: truthProp,
|
||||||
|
gapX: makeNumberProp(0),
|
||||||
|
gapY: makeNumberProp(0),
|
||||||
|
fontColor: makeStringProp('#dcdee0'),
|
||||||
|
opacity: makeNumberProp(1),
|
||||||
|
};
|
||||||
|
|
||||||
|
export type WatermarkProps = ExtractPropTypes<typeof watermarkProps>;
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name,
|
||||||
|
|
||||||
|
props: watermarkProps,
|
||||||
|
|
||||||
|
setup(props, { slots }) {
|
||||||
|
const svgElRef = ref<HTMLDivElement>();
|
||||||
|
|
||||||
|
const watermarkUrl = ref('');
|
||||||
|
const imageBase64 = ref('');
|
||||||
|
const renderWatermark = () => {
|
||||||
|
const svgInner = () => {
|
||||||
|
if (props.image) {
|
||||||
|
return (
|
||||||
|
<image
|
||||||
|
href={imageBase64.value}
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width={props.width}
|
||||||
|
height={props.height}
|
||||||
|
style={{
|
||||||
|
transformOrigin: 'center',
|
||||||
|
transform: `rotate(${props.rotate}deg)`,
|
||||||
|
}}
|
||||||
|
></image>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<foreignObject x="0" y="0" width={props.width} height={props.height}>
|
||||||
|
<div
|
||||||
|
// @ts-ignore
|
||||||
|
xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
style={{
|
||||||
|
transform: `rotate(${props.rotate}deg)`,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.content ? (
|
||||||
|
<span
|
||||||
|
style={{
|
||||||
|
color: props.fontColor,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{props.content}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
slots?.default?.()
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</foreignObject>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const svgWidth = props.width + props.gapX;
|
||||||
|
const svgHeight = props.height + props.gapY;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
viewBox={`0 0 ${svgWidth} ${svgHeight}`}
|
||||||
|
width={svgWidth}
|
||||||
|
height={svgHeight}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
style={{
|
||||||
|
padding: `0 ${props.gapX}px ${props.gapY}px 0`,
|
||||||
|
opacity: props.opacity,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{svgInner()}
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeImageToBase64 = (url: string) => {
|
||||||
|
const canvas = document.createElement('canvas');
|
||||||
|
const image = new Image();
|
||||||
|
image.crossOrigin = 'anonymous';
|
||||||
|
image.referrerPolicy = 'no-referrer';
|
||||||
|
image.onload = () => {
|
||||||
|
canvas.width = image.naturalWidth;
|
||||||
|
canvas.height = image.naturalHeight;
|
||||||
|
const ctx = canvas.getContext('2d');
|
||||||
|
ctx?.drawImage(image, 0, 0);
|
||||||
|
imageBase64.value = canvas.toDataURL();
|
||||||
|
};
|
||||||
|
image.src = url;
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeSvgToBlobUrl = (svgStr: string) => {
|
||||||
|
const svgBlob = new Blob([svgStr], {
|
||||||
|
type: 'image/svg+xml;charset=utf-8',
|
||||||
|
});
|
||||||
|
return URL.createObjectURL(svgBlob);
|
||||||
|
};
|
||||||
|
|
||||||
|
watchEffect(() => {
|
||||||
|
if (props.image) {
|
||||||
|
makeImageToBase64(props.image);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => [
|
||||||
|
imageBase64.value,
|
||||||
|
props.content,
|
||||||
|
props.fontColor,
|
||||||
|
props.height,
|
||||||
|
props.width,
|
||||||
|
props.rotate,
|
||||||
|
props.gapX,
|
||||||
|
props.gapY,
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
// 路径为 renderWatermark渲染的实际HTML => SVG字符串转换为blob图片 => 放到background-image中。
|
||||||
|
nextTick(() => {
|
||||||
|
if (svgElRef.value) {
|
||||||
|
if (watermarkUrl.value) {
|
||||||
|
URL.revokeObjectURL(watermarkUrl.value);
|
||||||
|
}
|
||||||
|
watermarkUrl.value = makeSvgToBlobUrl(svgElRef.value.innerHTML);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
{
|
||||||
|
immediate: true,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
if (watermarkUrl.value) {
|
||||||
|
URL.revokeObjectURL(watermarkUrl.value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => (
|
||||||
|
<div
|
||||||
|
class={bem()}
|
||||||
|
style={{
|
||||||
|
position: props.fullPage ? 'fixed' : 'absolute',
|
||||||
|
backgroundImage: `url(${watermarkUrl.value})`,
|
||||||
|
zIndex: props.zIndex,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div style={{ display: 'none' }} ref={svgElRef}>
|
||||||
|
{renderWatermark()}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
141
packages/vant/src/watermark/demo/index.vue
Normal file
141
packages/vant/src/watermark/demo/index.vue
Normal file
@ -0,0 +1,141 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import VanButton from '../../button';
|
||||||
|
import VanWatermark from '..';
|
||||||
|
import { useTranslate } from '../../../docs/site';
|
||||||
|
|
||||||
|
const t = useTranslate({
|
||||||
|
'zh-CN': {
|
||||||
|
customOpacity: '自定义透明度',
|
||||||
|
customGap: '自定义间隔',
|
||||||
|
customImage: '自定义图片',
|
||||||
|
customRotate: '自定义倾斜角度',
|
||||||
|
displayRange: '显示范围',
|
||||||
|
htmlWatermark: 'HTML 水印',
|
||||||
|
textWatermark: '文字水印',
|
||||||
|
imageWatermark: '图片水印',
|
||||||
|
switch: '切换',
|
||||||
|
},
|
||||||
|
'en-US': {
|
||||||
|
customOpacity: 'Custom opacity',
|
||||||
|
customGap: 'Custom Gap',
|
||||||
|
customRotate: 'Custom Rotate',
|
||||||
|
displayRange: 'Display Range',
|
||||||
|
htmlWatermark: 'HTML Watermark',
|
||||||
|
textWatermark: 'Text Watermark',
|
||||||
|
imageWatermark: 'Image Watermark',
|
||||||
|
switch: 'Swtich',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const baseWatermarkFlag = ref<'text' | 'image'>('text');
|
||||||
|
const fullPage = ref(false);
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<demo-block :title="t('basicUsage')">
|
||||||
|
<div class="demo-watermark-wrapper">
|
||||||
|
<div style="position: relative; z-index: 9999">
|
||||||
|
<van-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
baseWatermarkFlag = 'text';
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>{{ t('textWatermark') }}</van-button
|
||||||
|
>
|
||||||
|
<van-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
baseWatermarkFlag = 'image';
|
||||||
|
}
|
||||||
|
"
|
||||||
|
style="margin: 0 var(--van-padding-md)"
|
||||||
|
>{{ t('imageWatermark') }}</van-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<van-watermark
|
||||||
|
content="Vant"
|
||||||
|
v-if="baseWatermarkFlag === 'text'"
|
||||||
|
:full-page="false"
|
||||||
|
></van-watermark>
|
||||||
|
<van-watermark
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
v-if="baseWatermarkFlag === 'image'"
|
||||||
|
:full-page="false"
|
||||||
|
></van-watermark>
|
||||||
|
</div>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('customGap')">
|
||||||
|
<div class="demo-watermark-wrapper">
|
||||||
|
<van-watermark
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
:gap-x="20"
|
||||||
|
:gap-y="10"
|
||||||
|
:full-page="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('customOpacity')">
|
||||||
|
<div class="demo-watermark-wrapper">
|
||||||
|
<van-watermark
|
||||||
|
:full-page="false"
|
||||||
|
:opacity="0.5"
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
>
|
||||||
|
</van-watermark>
|
||||||
|
</div>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('customRotate')">
|
||||||
|
<div class="demo-watermark-wrapper">
|
||||||
|
<van-watermark
|
||||||
|
image="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
|
||||||
|
rotate="22"
|
||||||
|
:full-page="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('displayRange')">
|
||||||
|
<div class="demo-watermark-wrapper">
|
||||||
|
<van-button
|
||||||
|
@click="
|
||||||
|
() => {
|
||||||
|
fullPage = !fullPage;
|
||||||
|
}
|
||||||
|
"
|
||||||
|
>
|
||||||
|
{{ t('switch') }}
|
||||||
|
</van-button>
|
||||||
|
<van-watermark
|
||||||
|
:full-page="fullPage"
|
||||||
|
content="vant watermark"
|
||||||
|
font-color="rgba(0, 0, 0, 0.15)"
|
||||||
|
>
|
||||||
|
</van-watermark>
|
||||||
|
</div>
|
||||||
|
</demo-block>
|
||||||
|
|
||||||
|
<demo-block :title="t('htmlWatermark')">
|
||||||
|
<div class="demo-watermark-wrapper">
|
||||||
|
<van-watermark :width="150" :full-page="false">
|
||||||
|
<div
|
||||||
|
style="background: linear-gradient(45deg, #000 0, #000 50%, #fff 50%)"
|
||||||
|
>
|
||||||
|
<p style="mix-blend-mode: difference; color: #fff">Vant watermark</p>
|
||||||
|
</div>
|
||||||
|
</van-watermark>
|
||||||
|
</div>
|
||||||
|
</demo-block>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less">
|
||||||
|
.demo-watermark-wrapper {
|
||||||
|
position: relative;
|
||||||
|
height: 150px;
|
||||||
|
background-color: var(--van-background-2);
|
||||||
|
padding: var(--van-padding-md);
|
||||||
|
}
|
||||||
|
</style>
|
8
packages/vant/src/watermark/index.less
Normal file
8
packages/vant/src/watermark/index.less
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
.van-watermark {
|
||||||
|
background-repeat: repeat;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
13
packages/vant/src/watermark/index.ts
Normal file
13
packages/vant/src/watermark/index.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import { withInstall } from '../utils';
|
||||||
|
import _Watermark from './Watermark';
|
||||||
|
|
||||||
|
export const Watermark = withInstall(_Watermark);
|
||||||
|
export default Watermark;
|
||||||
|
export { watermarkProps } from './Watermark';
|
||||||
|
export type { WatermarkProps } from './Watermark';
|
||||||
|
|
||||||
|
declare module 'vue' {
|
||||||
|
export interface GlobalComponents {
|
||||||
|
VanWatermark: typeof Watermark;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`watermark should render content 1`] = `
|
||||||
|
<div class="van-watermark"
|
||||||
|
style="position: fixed; background-image: url(); z-index: 100;"
|
||||||
|
>
|
||||||
|
<div style="display: none;">
|
||||||
|
<svg viewbox="0 0 100 100"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
style="padding: 0px 0px 0px 0px; opacity: 1;"
|
||||||
|
>
|
||||||
|
<foreignObject x="0"
|
||||||
|
y="0"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
>
|
||||||
|
<div xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
style="transform: rotate(-22deg);"
|
||||||
|
>
|
||||||
|
<span style="color: red;">
|
||||||
|
Vant
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</foreignObject>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`watermark should render html 1`] = `
|
||||||
|
<div class="van-watermark"
|
||||||
|
style="position: fixed; background-image: url(); z-index: 100;"
|
||||||
|
>
|
||||||
|
<div style="display: none;">
|
||||||
|
<svg viewbox="0 0 100 100"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
style="padding: 0px 0px 0px 0px; opacity: 1;"
|
||||||
|
>
|
||||||
|
<foreignObject x="0"
|
||||||
|
y="0"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
>
|
||||||
|
<div xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
style="transform: rotate(-22deg);"
|
||||||
|
>
|
||||||
|
vant watermark test
|
||||||
|
</div>
|
||||||
|
</foreignObject>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`watermark should render image 1`] = `
|
||||||
|
<div class="van-watermark"
|
||||||
|
style="position: fixed; background-image: url(); z-index: 100;"
|
||||||
|
>
|
||||||
|
<div style="display: none;">
|
||||||
|
<svg viewbox="0 0 100 100"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
style="padding: 0px 0px 0px 0px; opacity: 0.5;"
|
||||||
|
>
|
||||||
|
<image href="base64Url"
|
||||||
|
x="0"
|
||||||
|
y="0"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
style="transform-origin: center; transform: rotate(-22deg);"
|
||||||
|
>
|
||||||
|
</image>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`watermark test false value fullPage 1`] = `
|
||||||
|
<div class="van-watermark"
|
||||||
|
style="position: absolute; background-image: url(); z-index: 100;"
|
||||||
|
>
|
||||||
|
<div style="display: none;">
|
||||||
|
<svg viewbox="0 0 100 100"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
style="padding: 0px 0px 0px 0px; opacity: 1;"
|
||||||
|
>
|
||||||
|
<foreignObject x="0"
|
||||||
|
y="0"
|
||||||
|
width="100"
|
||||||
|
height="100"
|
||||||
|
>
|
||||||
|
<div xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
style="transform: rotate(-22deg);"
|
||||||
|
>
|
||||||
|
vant watermark test
|
||||||
|
</div>
|
||||||
|
</foreignObject>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`watermark test width, height, rotate, zIndex 1`] = `
|
||||||
|
<div class="van-watermark"
|
||||||
|
style="position: fixed; background-image: url(); z-index: 200;"
|
||||||
|
>
|
||||||
|
<div style="display: none;">
|
||||||
|
<svg viewbox="0 0 20 20"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
style="padding: 0px 0px 0px 0px; opacity: 1;"
|
||||||
|
>
|
||||||
|
<foreignObject x="0"
|
||||||
|
y="0"
|
||||||
|
width="20"
|
||||||
|
height="20"
|
||||||
|
>
|
||||||
|
<div xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
style="transform: rotate(20deg);"
|
||||||
|
>
|
||||||
|
vant watermark test
|
||||||
|
</div>
|
||||||
|
</foreignObject>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
107
packages/vant/src/watermark/test/index.spec.ts
Normal file
107
packages/vant/src/watermark/test/index.spec.ts
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
// @ts-nocheck
|
||||||
|
import { Watermark } from '..';
|
||||||
|
import { mount } from '../../../test';
|
||||||
|
|
||||||
|
describe('watermark', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
const createElement = document.createElement.bind(document);
|
||||||
|
document.createElement = (tagName: string) => {
|
||||||
|
if (tagName === 'canvas') {
|
||||||
|
return {
|
||||||
|
...createElement(tagName),
|
||||||
|
getContext: () => {
|
||||||
|
() => {};
|
||||||
|
},
|
||||||
|
toDataURL: () => 'base64Url',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return createElement(tagName);
|
||||||
|
};
|
||||||
|
global.URL.createObjectURL = jest.fn(() => 'run to here');
|
||||||
|
global.Image = class {
|
||||||
|
crossOrigin = 'anonymous';
|
||||||
|
|
||||||
|
referrerPolicy = 'no-referrer';
|
||||||
|
|
||||||
|
naturalWidth = 800;
|
||||||
|
|
||||||
|
naturalHeight = 550;
|
||||||
|
|
||||||
|
onload: () => void = () => {};
|
||||||
|
|
||||||
|
// just mock to trigge onload
|
||||||
|
_src = '';
|
||||||
|
|
||||||
|
get src() {
|
||||||
|
return this._src;
|
||||||
|
}
|
||||||
|
|
||||||
|
set src(val) {
|
||||||
|
this._src = val;
|
||||||
|
this.onload();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render content', () => {
|
||||||
|
const wrapper = mount(Watermark, {
|
||||||
|
props: {
|
||||||
|
content: 'Vant',
|
||||||
|
fontColor: 'red',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render image', () => {
|
||||||
|
const wrapper = mount(Watermark, {
|
||||||
|
props: {
|
||||||
|
content: 'Vant',
|
||||||
|
image: 'https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg',
|
||||||
|
opacity: 0.5,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should render html', () => {
|
||||||
|
const wrapper = mount(Watermark, {
|
||||||
|
slots: {
|
||||||
|
default: () => 'vant watermark test',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test width, height, rotate, zIndex', () => {
|
||||||
|
const wrapper = mount(Watermark, {
|
||||||
|
props: {
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
rotate: 20,
|
||||||
|
zIndex: 200,
|
||||||
|
},
|
||||||
|
slots: {
|
||||||
|
default: () => 'vant watermark test',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('test false value fullPage', () => {
|
||||||
|
const wrapper = mount(Watermark, {
|
||||||
|
props: {
|
||||||
|
fullPage: false,
|
||||||
|
},
|
||||||
|
slots: {
|
||||||
|
default: () => 'vant watermark test',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(wrapper.html()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
@ -344,6 +344,10 @@ location.href = location.href.replace('youzan.github.io', 'vant-ui.github.io');
|
|||||||
path: 'text-ellipsis',
|
path: 'text-ellipsis',
|
||||||
title: 'TextEllipsis 文本省略',
|
title: 'TextEllipsis 文本省略',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'watermark',
|
||||||
|
title: 'Watermark 水印',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -784,6 +788,10 @@ location.href = location.href.replace('youzan.github.io', 'vant-ui.github.io');
|
|||||||
path: 'text-ellipsis',
|
path: 'text-ellipsis',
|
||||||
title: 'TextEllipsis',
|
title: 'TextEllipsis',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'watermark',
|
||||||
|
title: 'Watermark',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user