| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- <template>
- <text
- v-if="!iconData"
- :style="{ color: '#f00', fontSize: '16px' }"
- :class="innerClass"
- >
- {{ icon ? `Missing icon: ${icon}` : 'Empty' }} !
- </text>
- <text
- v-else-if="iconData.type == 'iconfont'"
- :style="style"
- :class="['iconfont', innerClass, iconData.value]"
- />
- <!-- #ifdef H5 || APP-PLUS -->
- <view
- v-else-if="iconData.type == 'svg'"
- :style="{
- ...style,
- display: 'flex'
- }"
- :class="innerClass"
- v-html="iconData.rawSvg"
- />
- <!-- #endif -->
- <!-- #ifndef H5 -->
- <image
- v-else-if="iconData.type == 'svg' && style.color && iconData.rawSvg"
- :style="style"
- :class="innerClass"
- :src="IconUtils.getColoredSvg(iconData.rawSvg, style.color)"
- />
- <image
- v-else-if="iconData.type == 'svg'"
- :style="style"
- :class="innerClass"
- :src="iconData.value"
- />
- <!-- #endif -->
- <WrappedImage
- v-else-if="iconData.type == 'image' && iconData.value"
- :innerStyle="style"
- :innerClass="innerClass"
- :src="iconData.value"
- :showFailed="!noError"
- mode="aspectFill"
- />
- </template>
- <script setup lang="ts">
- import { computed } from 'vue';
- import { IconUtils, type IconItem } from './IconUtils';
- import { useTheme } from '../theme/ThemeDefine';
- import WrappedImage from './Image.vue';
- export interface IconProps {
- /**
- * 图标名称或图片 URL
- */
- icon?: string;
- /**
- * 同 icon 属性
- */
- name?: string;
- /**
- * 图标大小
- */
- size?: number|string;
- /**
- * 图标颜色
- */
- color?: string;
- /**
- * 图标旋转角度
- */
- rotate?: number;
- /**
- * 自定义样式
- */
- innerStyle?: object,
- /**
- * 自定义类名
- */
- innerClass?: string,
- /**
- * 是否不显示错误图标
- */
- noError?: boolean,
- }
- const theme = useTheme();
- const props = withDefaults(defineProps<IconProps>(), {
- size: 45,
- noError: false,
- });
- const icon = computed(() => props.icon || props.name);
- const iconData = computed(() => {
- if (IconUtils.iconCount.value === 0) {
- return {
- type: 'none',
- value: '',
- } as IconItem
- }
- const data = icon.value ? IconUtils.getIconDataFromMap(icon.value) : undefined;
- if (!data && icon.value && icon.value.startsWith('icon-')) {
- return {
- type: 'iconfont',
- value: icon.value,
- fontFamily: 'iconfont',
- } as IconItem
- } else if (!data && icon.value) {
- return {
- type: 'image',
- value: icon.value,
- } as IconItem
- } else if (!data) {
- return {
- type: 'none',
- value: '',
- } as IconItem
- }
- return data;
- });
- const style = computed(() => {
- const size = theme.resolveThemeSize(props.size);
- return {
- flexShrink: 0,
- fontSize: size,
- fontFamily: iconData.value.fontFamily || 'iconfont',
- width: size,
- height: size,
- color: theme.resolveThemeColor(props.color, 'text.content'),
- fill: theme.resolveThemeColor(props.color, 'text.content'),
- transform: props.rotate ? `rotate(${props.rotate}deg)` : undefined,
- overflow: 'visible',
- ...props.innerStyle,
- };
- });
- defineOptions({
- options: {
- virtualHost: true,
- }
- });
- </script>
|