203 lines
4.5 KiB
Vue
203 lines
4.5 KiB
Vue
<template>
|
|
<div class="md-water-mark">
|
|
<div class="water-mark-container">
|
|
<slot></slot>
|
|
</div>
|
|
<div
|
|
v-if="!!$scopedSlots.watermark || content"
|
|
class="water-mark-list"
|
|
ref="mark"
|
|
>
|
|
<div
|
|
class="water-mark-list-wrapper"
|
|
:style="{
|
|
opacity,
|
|
transform: `rotate(${rotate}deg)`
|
|
}"
|
|
>
|
|
<template v-if="content">
|
|
<canvas ref="canvas" class="water-mark-canvas"></canvas>
|
|
</template>
|
|
<template v-else-if="!!$scopedSlots.watermark">
|
|
<ul
|
|
v-for="i in (repeatY ? repetition : 1)"
|
|
class="water-mark-line"
|
|
:style="{
|
|
marginBottom: spacing,
|
|
}"
|
|
:key="`line-${i}`"
|
|
>
|
|
<li
|
|
v-for="j in (repeatX ? repetition : 1)"
|
|
class="water-mark-item"
|
|
:style="i % 2 === 0 ? {
|
|
marginLeft: repeatX ? spacing : 0,
|
|
} : {
|
|
marginRight: repeatX ? spacing : 0,
|
|
}"
|
|
:key="`item-${j}`"
|
|
>
|
|
<slot
|
|
name="watermark"
|
|
:coord="{row: i, col: j}"
|
|
></slot>
|
|
</li>
|
|
</ul>
|
|
</template>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import {getDpr} from '../_util'
|
|
|
|
const fontSize = 14
|
|
const color = '#858B9C'
|
|
|
|
export default {
|
|
name: 'md-water-mark',
|
|
|
|
props: {
|
|
content: {
|
|
type: String,
|
|
default: '',
|
|
},
|
|
spacing: {
|
|
type: [String, Number],
|
|
default: '20vw',
|
|
},
|
|
repeatX: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
repeatY: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
rotate: {
|
|
type: [String, Number],
|
|
default: -30,
|
|
},
|
|
opacity: {
|
|
type: [String, Number],
|
|
default: 0.1,
|
|
},
|
|
},
|
|
|
|
data() {
|
|
return {
|
|
repetition: process.env.MAND_ENV === 'test' ? 2 : 50,
|
|
}
|
|
},
|
|
|
|
mounted() {
|
|
if (this.content) {
|
|
this.ctx = this.$refs.canvas.getContext('2d')
|
|
this.ratio = Math.max(getDpr(), 2) // min ratio = 2
|
|
|
|
this.$_initCanvas()
|
|
this.$_computedSpacing()
|
|
this.$_draw()
|
|
}
|
|
},
|
|
|
|
methods: {
|
|
$_initCanvas() {
|
|
const {ctx, ratio, $refs} = this
|
|
const {mark, canvas} = $refs
|
|
const {clientWidth, clientHeight} = mark
|
|
|
|
this.ctxWidth = canvas.width = clientWidth * ratio
|
|
this.ctxHeight = canvas.height = clientHeight * ratio
|
|
|
|
ctx.scale(1 / ratio, 1 / ratio)
|
|
},
|
|
|
|
$_computedSpacing() {
|
|
const {spacing, ratio} = this
|
|
|
|
if (typeof spacing === 'number') {
|
|
this.realSpacing = spacing
|
|
return
|
|
}
|
|
const [, amount = 20, unit = 'vw'] = /([0-9]+)([A-Za-z]+)/.exec(spacing)
|
|
|
|
if (unit === 'px') {
|
|
this.realSpacing = amount
|
|
} else if (unit === 'vh') {
|
|
const height = window.screen.height
|
|
this.realSpacing = amount * height / 100
|
|
} else if (unit === 'vw') {
|
|
const width = window.screen.width
|
|
this.realSpacing = amount * width / 100
|
|
}
|
|
|
|
this.realSpacing *= ratio
|
|
},
|
|
|
|
$_draw() {
|
|
const {content, ctx, realSpacing, ratio, ctxWidth, ctxHeight} = this
|
|
|
|
const _fontSize = fontSize * ratio
|
|
const contentLength = content.length * _fontSize
|
|
const xCount = Math.ceil(ctxWidth * ratio / (contentLength + realSpacing))
|
|
const yCount = Math.ceil(ctxHeight * ratio / (_fontSize + realSpacing))
|
|
|
|
ctx.font = `${_fontSize}px DIDIFD-Medium, "Helvetica Neue",Helvetica,"PingFang SC","Hiragino Sans GB","Microsoft YaHei","微软雅黑",Arial,sans-serif`
|
|
ctx.fillStyle = color
|
|
|
|
let ctxX = 0
|
|
let ctxY = 0
|
|
for (let y = 0; y < yCount; y++) {
|
|
ctxX = 0
|
|
for (let x = 0; x < xCount; x++) {
|
|
ctx.fillText(content, ctxX, ctxY)
|
|
ctxX += contentLength
|
|
}
|
|
ctxY += _fontSize + realSpacing
|
|
}
|
|
},
|
|
},
|
|
}
|
|
|
|
</script>
|
|
|
|
<style lang="stylus">
|
|
.md-water-mark
|
|
position relative
|
|
overflow hidden
|
|
|
|
.water-mark-container
|
|
position relative
|
|
z-index 2
|
|
|
|
.water-mark-list
|
|
clearfix()
|
|
absolute-pos()
|
|
position absolute
|
|
filter grayscale(100%)
|
|
display flex
|
|
flex-direction column
|
|
justify-content center
|
|
overflow hidden
|
|
|
|
.water-mark-canvas
|
|
position absolute
|
|
top 0
|
|
left 0
|
|
transform translate3d(-50%, -50%, 0)
|
|
|
|
.water-mark-line
|
|
position relative
|
|
left 50%
|
|
float left
|
|
width 10000%
|
|
display flex
|
|
justify-content center
|
|
transform translateX(-50%)
|
|
|
|
.water-mark-item
|
|
float left
|
|
font-size font-body-large
|
|
color color-text-caption
|
|
</style>
|