vxe-pc-ui
Version:
A vue based PC component library
169 lines (140 loc) • 4.8 kB
text/typescript
import { ref, h, reactive, computed, onMounted, watch, PropType, onUnmounted } from 'vue'
import { defineVxeComponent } from '../../ui/src/comp'
import XEUtils from 'xe-utils'
import { getConfig, createEvent, globalEvents } from '../../ui'
import { toCssUnit } from '../../ui/src/dom'
import { getContentUrl } from './util'
import type { WatermarkReactData, VxeWatermarkEmits, WatermarkMethods, VxeWatermarkPropTypes, WatermarkPrivateMethods, ValueOf, VxeComponentStyleType, WatermarkPrivateRef, VxeWatermarkPrivateComputed, VxeWatermarkConstructor, VxeWatermarkPrivateMethods } from '../../../types'
export default defineVxeComponent({
name: 'VxeWatermark',
props: {
width: String as PropType<VxeWatermarkPropTypes.Width>,
height: String as PropType<VxeWatermarkPropTypes.Height>,
imageUrl: String as PropType<VxeWatermarkPropTypes.ImageUrl>,
rotate: {
type: [Number, String] as PropType<VxeWatermarkPropTypes.Rotate>,
default: () => getConfig().watermark.rotate
},
gap: {
type: [Array, Number, String] as PropType<VxeWatermarkPropTypes.Gap>,
default: () => XEUtils.clone(getConfig().watermark.gap, true)
},
content: [String, Array] as PropType<VxeWatermarkPropTypes.Content>,
font: Object as PropType<VxeWatermarkPropTypes.Font>,
offset: Object as PropType<VxeWatermarkPropTypes.Offset>,
zIndex: [String, Number] as PropType<VxeWatermarkPropTypes.ZIndex>
},
emits: [
] as VxeWatermarkEmits,
setup (props, context) {
const { emit } = context
const xID = XEUtils.uniqueId()
const refElem = ref<HTMLDivElement>()
const reactData = reactive<WatermarkReactData>({
markUrl: ''
})
const refMaps: WatermarkPrivateRef = {
refElem
}
const computeFontOpts = computed(() => {
return XEUtils.assign({}, XEUtils.clone(getConfig().watermark.font, true), props.font)
})
const computeWrapperStyle = computed(() => {
const { width, height, zIndex } = props
const { markUrl } = reactData
const stys: VxeComponentStyleType = {}
if (width) {
stys.width = toCssUnit(width)
}
if (height) {
stys.height = toCssUnit(height)
}
if (markUrl) {
stys.backgroundImage = `url(${markUrl})`
}
if (zIndex) {
stys.zIndex = zIndex
}
return stys
})
const computeMaps: VxeWatermarkPrivateComputed = {
}
const $xeWatermark = {
xID,
props,
context,
reactData,
getRefMaps: () => refMaps,
getComputeMaps: () => computeMaps
} as unknown as VxeWatermarkConstructor & VxeWatermarkPrivateMethods
const dispatchEvent = (type: ValueOf<VxeWatermarkEmits>, params: Record<string, any>, evnt: Event | null) => {
emit(type, createEvent(evnt, { $watermark: $xeWatermark }, params))
}
const collapsePaneMethods: WatermarkMethods = {
dispatchEvent
}
const updateMarkStyle = () => {
const { content, gap, rotate, offset } = props
const el = refElem.value
const fontOpts = computeFontOpts.value
if (el) {
if (content) {
getContentUrl(content, getComputedStyle(el).fontSize, {
font: fontOpts,
rotate,
gap,
offset
}).then(url => {
reactData.markUrl = url
})
}
}
}
const collapsePanePrivateMethods: WatermarkPrivateMethods = {
}
Object.assign($xeWatermark, collapsePaneMethods, collapsePanePrivateMethods)
const renderVN = () => {
const wrapperStyle = computeWrapperStyle.value
return h('div', {
ref: refElem,
class: 'vxe-watermark',
style: wrapperStyle
})
}
watch(() => props.imageUrl, () => {
updateMarkStyle()
})
watch(() => props.content, () => {
updateMarkStyle()
})
watch(() => props.gap, () => {
updateMarkStyle()
})
watch(() => props.rotate, () => {
updateMarkStyle()
})
watch(() => props.width, () => {
updateMarkStyle()
})
watch(() => props.height, () => {
updateMarkStyle()
})
watch(() => props.font, () => {
updateMarkStyle()
})
onMounted(() => {
updateMarkStyle()
globalEvents.on($xeWatermark, 'resize', XEUtils.throttle(() => {
updateMarkStyle()
}, 300, { trailing: true, leading: true }))
})
onUnmounted(() => {
globalEvents.off($xeWatermark, 'resize')
})
$xeWatermark.renderVN = renderVN
return $xeWatermark
},
render () {
return this.renderVN()
}
})