合同小程序前端代码仓库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

236 lines
5.5 KiB

<template>
<!-- #ifdef APP-NVUE -->
<web-view class="l-svg" ref="webRef" @error="error" @pagefinish="loaded" @onPostMessage="message"
src="/uni_modules/lime-svg/hybrid/html/index.html"></web-view>
<!-- <l-svg-x v-else :src="src" :color="color" @load="onLoad" @error="onError"></l-svg-x> -->
<!-- #endif -->
<!-- #ifndef APP-NVUE -->
<view class="l-svg" :class="{'is-inherit': isInherit}" :style="[styles]" @click="$emit('click')">
<image class="l-svg-img" :src="path" @load="onLoad" @error="onError"></image>
</view>
<!-- #endif -->
</template>
<script lang="ts">
import SvpProps from './props'
import { defineComponent, ref, computed, watchEffect, getCurrentInstance } from './vue'
import { pathToDataUrl, svgToDataUrl } from './utils'
export default defineComponent({
name: 'l-svg',
props: SvpProps,
emits: ['load', 'error', 'click'],
setup(props, { emit }) {
const path = ref('')
// #ifndef APP-NVUE
const isInherit = computed(() : boolean => {
return props.color != ''
})
// #endif
const formatUrl = (url: string, action:string):string => {
if(url.indexOf(`'`) > 0) return `${action}("${url}")`
return `${action}('${url}')`
}
const instance = getCurrentInstance()!.proxy!
const imageURL = ref(null)
const styles = computed(() => {
const style: Record<string, any> = {}
// #ifndef APP-NVUE
if (path.value != '') {
const image = formatUrl(imageURL.value ?? path.value, 'url')// + ';'
if (isInherit.value) {
style['-webkit-mask-image'] = image
style['mask-image'] = image
} else {
style['background-image'] = image
}
}
// #endif
if (props.color != '') {
style['color'] = props.color
}
//#ifdef VUE2
// VUE2小程序最后一个值莫名的出现undefined
style['undefined'] = ''
// #endif
return style
})
const onLoad = (e) => {
// #ifdef WEB
imageURL.value = instance.$el.querySelector('img').src
// #endif
emit('load')
}
const onError = () => {
emit('error')
}
// APP
// #ifdef APP-NVUE
const webRef = ref(null)
const setSvgSrc = () => {
if (path.value != '') {
webRef.value?.evalJS(formatUrl(path.value, 'setSrc'));
}
}
const setSvgColor = () => {
if (props.color != '' && path.value != '') {
webRef.value?.evalJS(`setStyle({"--color": "${props.color}"})`);
}
}
const error = () => {
emit('error')
}
const loaded = () => {
watchEffect(() => {
if (props.src == '') return
if (props.src.startsWith('<')) {
path.value = props.src
} else if (props.src.startsWith('/static')) {
pathToDataUrl(props.src).then(res => {
path.value = res;
setSvgSrc()
setSvgColor()
}).catch(err => {
emit('error')
console.warn("[lime-svg]" + props.src + JSON.stringify(err))
})
} else {
path.value = props.src
}
setSvgSrc()
setSvgColor()
})
}
const message = (e) => {
const data = e.detail.data[0]
const event = data?.event
const eventDetaill = data?.data
if (event == 'click') {
emit('click', eventDetaill)
} else if (event == 'load') {
emit('load', eventDetaill)
} else if (event == 'error') {
emit('error', eventDetaill)
}
}
// #endif
// 小程序 WEB
// #ifndef APP-NVUE
watchEffect(() => {
if (props.src == '') return
if (props.src.startsWith('<svg')) {
path.value = svgToDataUrl(props.src)
} else if (props.src.startsWith('/static')) {
// #ifdef WEB
path.value = props.src
// #endif
// #ifdef APP-VUE
path.value = props.src.slice(1)
// #endif
// #ifndef WEB || APP-VUE
pathToDataUrl(props.src).then(res => {
path.value = res;
}).catch(err => {
emit('error')
console.warn("[lime-svg]" + props.src + JSON.stringify(err))
})
// #endif
} else {
path.value = props.src
}
})
// #endif
return {
path,
onLoad,
onError,
// #ifdef APP-NVUE
webRef,
error,
loaded,
message,
// #endif
// #ifndef APP-NVUE
isInherit,
styles
// #endif
}
}
})
</script>
<style lang="scss">
/* #ifndef APP-NVUE */
:host {
display: inline-flex;
}
/* #endif */
.l-svg {
// display: flex;
// align-self: flex-start;
/* #ifdef APP-NVUE */
flex: 1;
/* #endif */
/* #ifndef APP-NVUE */
display: inline-flex;
width: 100%;
height: 100%;
flex: 1;
/* #endif */
/* #ifndef APP-NVUE */
:deep(svg) {
width: 100%;
height: 100%;
}
&-img {
// opacity: 0;
mix-blend-mode: lighten;
width: 100%;
height: 100%;
}
&.is-inherit {
// background-image: var(--svg);//linear-gradient(#f09, #09f, #f0f);
// background-blend-mode: lighten;
// background-size: cover;
// background-size: 100% 100%;
// background-repeat: no-repeat;
// -webkit-mask-image: var(--svg);
// mask-image: var(--svg);
-webkit-mask-repeat: no-repeat;
mask-repeat: no-repeat;
-webkit-mask-size: 100% 100%;
mask-size: 100% 100%;
// -webkit-mask-mode: alpha;
// mask-mode: alpha;
background-color: currentColor; //var(currentColor, transparent);
// background-blend-mode: multiply;
}
&:not(.is-inherit) {
// background: var(--svg) no-repeat;
background-repeat: no-repeat;
background-size: 100% 100%;
background-color: transparent;
image {
mix-blend-mode: inherit;
opacity: 0;
}
}
/* #endif */
/* #ifdef APP-PLUS */
/* #endif */
}
</style>