|
<template>
|
|
<text class="l-icon" :class="[classes]" :style="[styles, lStyle]" v-if="!isImage && !isIconify && !isSVG" @click="$emit('click')">{{iconCode}}</text>
|
|
<image class="l-icon" :class="[classes]" :style="[styles, lStyle]" v-else-if="(!isSVG && !isIconify) && isImage" :src="iconUrl" @click="$emit('click')"></image>
|
|
<l-svg class="l-icon" :class="[classes]" :style="[styles, lStyle]" v-else :web="web" :color="color" :src="iconUrl" @error="imageError" @load="imageLoad" @click="$emit('click')"></l-svg>
|
|
</template>
|
|
<script lang="ts">
|
|
// @ts-nocheck
|
|
/**
|
|
* LimeIcon 图标
|
|
* @description ICON集
|
|
* @tutorial https://ext.dcloud.net.cn/plugin?id=14057
|
|
* @property {String} name 图标名称
|
|
* @property {String} color 颜色
|
|
* @property {String} size 尺寸
|
|
* @property {String} prefix 字体图标前缀
|
|
* @property {Boolean} inherit 是否继承颜色
|
|
* @property {Boolean} web 原生 app(nvue,uvue) 是否使用web渲染
|
|
* @event {Function} click 点击事件
|
|
*/
|
|
// @ts-nocheck
|
|
import { computed, defineComponent, ref, inject } from '@/uni_modules/lime-shared/vue';
|
|
import icons from '../../static/icons.json';
|
|
import { addUnit } from '@/uni_modules/lime-shared/addUnit';
|
|
|
|
import { isObject } from '@/uni_modules/lime-shared/isObject';
|
|
import IconProps from './props';
|
|
|
|
// #ifdef VUE2 && MP
|
|
import { getClassStr } from '@/uni_modules/lime-shared/getClassStr';
|
|
// #endif
|
|
|
|
// #ifdef APP-NVUE
|
|
import iconSrc from '@/uni_modules/lime-icon/hybrid/html/t3.ttf';
|
|
var domModule = weex.requireModule('dom');
|
|
domModule.addRule('fontFace', {
|
|
'fontFamily': "uniicons",
|
|
'src': "url('" + iconSrc + "')"
|
|
});
|
|
// #endif
|
|
|
|
const name = 'l-icon';
|
|
export default defineComponent({
|
|
name,
|
|
externalClasses: ['l-class'],
|
|
options: {
|
|
addGlobalClass: true,
|
|
virtualHost: true,
|
|
},
|
|
props: IconProps,
|
|
emits: ['click'],
|
|
setup(props, { emit }) {
|
|
const $iconCollection = inject('$iconCollection', null)
|
|
const { $limeIconsHost: $iconsHost } = uni as any
|
|
const IconifyURL = 'https://api.iconify.design/'
|
|
// const isAPP = uni.getSystemInfoSync().uniPlatform == 'app'
|
|
const hasHost = computed(() => `${props.name}`.indexOf('/') !== -1);
|
|
const isIconify = computed(() => !hasHost.value && `${props.name}`.includes(':'))
|
|
const collectionIcon = computed(() => isObject($iconCollection) && $iconCollection.icons[props.name])
|
|
const isImage = computed<boolean>(() : boolean => {
|
|
return /\.(jpe?g|png|gif|bmp|webp|tiff?)$/i.test(props.name) || /^data:image\/(jpeg|png|gif|bmp|webp|tiff);base64,/.test(props.name)
|
|
})
|
|
const isSVG = computed<boolean>(() : boolean => {
|
|
return /\.svg$/i.test(props.name) || props.name.startsWith('data:image/svg+xml') || props.name.startsWith('<svg')
|
|
})
|
|
const classes = computed(() => {
|
|
const { prefix } = props
|
|
const iconPrefix = prefix || name
|
|
const iconName = `${iconPrefix}-${props.name}`
|
|
const isFont = !isImage.value && !isIconify.value && !isSVG.value
|
|
const isImages = isImage.value || isIconify.value || isSVG.value
|
|
const cls = {
|
|
[iconPrefix]: !isImages && prefix,
|
|
[iconName]: !isImages,
|
|
[`${name}--image`]: isImages,
|
|
[`${name}--font`]: isFont,
|
|
// [`is-inherit`]: isIconify.value && (props.color || props.inherit)
|
|
}
|
|
|
|
// #ifdef VUE2 && MP
|
|
return getClassStr(cls)
|
|
// #endif
|
|
|
|
return cls
|
|
})
|
|
const iconCode = computed(() => {
|
|
const isImages = isImage.value || isIconify.value || isSVG.value
|
|
return (!isImages && icons[props.name]) || ''
|
|
})
|
|
const isError = ref(false)
|
|
const cacheMap = new Map<string, string>()
|
|
const iconUrl = computed(() => {
|
|
const hasIconsHost = $iconsHost != null && $iconsHost != ''
|
|
// const hasIconCollection = $iconCollectiont != null
|
|
if (isImage.value) {
|
|
return hasHost.value ? props.name : ($iconsHost ?? '') + props.name
|
|
} else if (isIconify.value) {
|
|
// 防止重绘
|
|
if(cacheMap.has(props.name) && !isError.value) {
|
|
return cacheMap.get(props.name)!
|
|
}
|
|
// 如果存在collectionIcon则使用
|
|
// 如果设置的路径加载失败 就使用网络地址 就使用iconify api
|
|
// !isError.value &&
|
|
const _host = `${hasIconsHost ? $iconsHost : IconifyURL}`
|
|
const _icon = collectionIcon.value || _host + `${props.name}.svg`.replace(/:/g, '/')
|
|
cacheMap.set(props.name, _icon)
|
|
return _icon
|
|
} else if (isSVG.value) {
|
|
return (/\.svg$/i.test(props.name) && hasIconsHost && !hasHost.value ? $iconsHost : '') + props.name.replace(/'/g, '"')
|
|
} else {
|
|
return null
|
|
}
|
|
})
|
|
const styles = computed(() => {
|
|
const style : Record<string, any> = {
|
|
'color': props.color,
|
|
}
|
|
if (typeof props.size == 'number' || props.size) {
|
|
style['font-size'] = addUnit(props.size)
|
|
}
|
|
//#ifdef VUE2
|
|
// VUE2小程序最后一个值莫名的出现undefined
|
|
style['undefined'] = ''
|
|
// #endif
|
|
return style
|
|
})
|
|
const imageLoad = () => {
|
|
isError.value = false
|
|
}
|
|
const imageError = () => {
|
|
isError.value = true
|
|
}
|
|
|
|
return {
|
|
iconCode,
|
|
classes,
|
|
styles,
|
|
isImage,
|
|
isSVG,
|
|
isIconify,
|
|
iconUrl,
|
|
imageLoad,
|
|
imageError
|
|
}
|
|
}
|
|
})
|
|
</script>
|
|
<style lang="scss">
|
|
@import './index.scss';
|
|
</style>
|