修改动态 svg
This commit is contained in:
36
src/components/icon/back/index.vue
Normal file
36
src/components/icon/back/index.vue
Normal file
@@ -0,0 +1,36 @@
|
||||
<template>
|
||||
<!-- <div style='width: 12px;'></div>-->
|
||||
<!-- <el-icon color='black' class='backIcon'>-->
|
||||
<!-- <close @click='go(-1)' />-->
|
||||
<!-- </el-icon>-->
|
||||
<el-button @click='go(-1)' :class='{positionStyle:custom,ml10:true}' :icon='Back'>返回</el-button>
|
||||
</template>
|
||||
|
||||
<script setup lang='ts'>
|
||||
import { useRouter } from 'vue-router'
|
||||
import { Back } from '@element-plus/icons-vue'
|
||||
|
||||
const { go } = useRouter()
|
||||
defineProps(['custom'])
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.backIcon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
font-size: 25px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.backIcon:hover {
|
||||
border-radius: 25px;
|
||||
background-color: lightgrey;
|
||||
}
|
||||
|
||||
.positionStyle {
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
top: 20px;
|
||||
}
|
||||
</style>
|
||||
4
src/components/icon/index.ts
Normal file
4
src/components/icon/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import Icon from './src/Icon.vue'
|
||||
import IconSelect from './src/IconSelect.vue'
|
||||
|
||||
export { Icon, IconSelect }
|
||||
@@ -1,43 +1,44 @@
|
||||
<script lang="ts">
|
||||
import { createVNode, resolveComponent, defineComponent, computed, type CSSProperties } from 'vue'
|
||||
import svg from '@/components/icon/svg/index.vue'
|
||||
import { isExternal } from '@/utils/common'
|
||||
export default defineComponent({
|
||||
name: 'Icon',
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: '18px'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#000000'
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const iconStyle = computed((): CSSProperties => {
|
||||
const { size, color } = props
|
||||
let s = `${size.replace('px', '')}px`
|
||||
return {
|
||||
fontSize: s,
|
||||
color: color
|
||||
}
|
||||
})
|
||||
|
||||
if (props.name.indexOf('el-icon-') === 0) {
|
||||
return () =>
|
||||
createVNode('el-icon', { class: 'icon el-icon', style: iconStyle.value }, [
|
||||
createVNode(resolveComponent(props.name))
|
||||
])
|
||||
} else if (props.name.indexOf('local-') === 0 || isExternal(props.name)) {
|
||||
return () => createVNode(svg, { name: props.name, size: props.size, color: props.color })
|
||||
} else {
|
||||
return () => createVNode('i', { class: [props.name, 'icon'], style: iconStyle.value })
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
<script lang="ts">
|
||||
import { createVNode, resolveComponent, defineComponent, computed, type CSSProperties } from 'vue'
|
||||
import svg from '@/components/icon/svg/index.vue'
|
||||
import { isExternal } from '@/utils/common'
|
||||
export default defineComponent({
|
||||
name: 'Icon',
|
||||
props: {
|
||||
name: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: '18px'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#000000'
|
||||
}
|
||||
},
|
||||
setup(props) {
|
||||
const iconStyle = computed((): CSSProperties => {
|
||||
const { size, color } = props
|
||||
let s = `${size.replace('px', '')}px`
|
||||
return {
|
||||
fontSize: s,
|
||||
color: color
|
||||
}
|
||||
})
|
||||
if(props.name){
|
||||
if (props.name.indexOf('el-icon-') === 0) {
|
||||
return () =>
|
||||
createVNode('el-icon', { class: 'icon el-icon', style: iconStyle.value }, [
|
||||
createVNode(resolveComponent(props.name))
|
||||
])
|
||||
} else if (props.name.indexOf('local-') === 0 || isExternal(props.name)) {
|
||||
return () => createVNode(svg, { name: props.name, size: props.size, color: props.color })
|
||||
} else {
|
||||
return () => createVNode('i', { class: [props.name, 'icon'], style: iconStyle.value })
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
87
src/components/icon/src/Icon.vue
Normal file
87
src/components/icon/src/Icon.vue
Normal file
@@ -0,0 +1,87 @@
|
||||
<script lang="ts" setup>
|
||||
import { CSSProperties ,ref,toRef,computed,watch} from 'vue'
|
||||
import { propTypes } from '@/utils/propTypes'
|
||||
import Iconify from '@purge-icons/generated'
|
||||
import { useDesign } from '@/hooks/web/useDesign'
|
||||
|
||||
defineOptions({ name: 'Icon' })
|
||||
|
||||
const { getPrefixCls } = useDesign()
|
||||
|
||||
const prefixCls = getPrefixCls('icon')
|
||||
|
||||
const props = defineProps({
|
||||
// icon name
|
||||
icon: propTypes.string,
|
||||
// icon color
|
||||
color: propTypes.string,
|
||||
// icon size
|
||||
size: propTypes.number.def(16),
|
||||
// icon svg class
|
||||
svgClass: propTypes.string.def('')
|
||||
})
|
||||
|
||||
const elRef = ref<ElRef>(null)
|
||||
|
||||
const isLocal = computed(() => props.icon.startsWith('svg-icon:'))
|
||||
|
||||
const symbolId = computed(() => {
|
||||
return unref(isLocal) ? `#icon-${props.icon.split('svg-icon:')[1]}` : props.icon
|
||||
})
|
||||
|
||||
const getIconifyStyle = computed(() => {
|
||||
const { color, size } = props
|
||||
return {
|
||||
fontSize: `${size}px`,
|
||||
height: '1em',
|
||||
color
|
||||
}
|
||||
})
|
||||
|
||||
const getSvgClass = computed(() => {
|
||||
const { svgClass } = props
|
||||
return `iconify ${svgClass}`
|
||||
})
|
||||
|
||||
const updateIcon = async (icon: string) => {
|
||||
if (unref(isLocal)) return
|
||||
|
||||
const el = unref(elRef)
|
||||
if (!el) return
|
||||
|
||||
await nextTick()
|
||||
|
||||
if (!icon) return
|
||||
|
||||
const svg = Iconify.renderSVG(icon, {})
|
||||
if (svg) {
|
||||
el.textContent = ''
|
||||
el.appendChild(svg)
|
||||
} else {
|
||||
const span = document.createElement('span')
|
||||
span.className = 'iconify'
|
||||
span.dataset.icon = icon
|
||||
el.textContent = ''
|
||||
el.appendChild(span)
|
||||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => props.icon,
|
||||
(icon: string) => {
|
||||
updateIcon(icon)
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ElIcon :class="prefixCls" :color="color" :size="size">
|
||||
<svg v-if="isLocal" :class="getSvgClass" aria-hidden="true">
|
||||
<use :xlink:href="symbolId" />
|
||||
</svg>
|
||||
|
||||
<span v-else ref="elRef" :class="$attrs.class" :style="getIconifyStyle">
|
||||
<span :class="getSvgClass" :data-icon="symbolId"></span>
|
||||
</span>
|
||||
</ElIcon>
|
||||
</template>
|
||||
229
src/components/icon/src/IconSelect.vue
Normal file
229
src/components/icon/src/IconSelect.vue
Normal file
@@ -0,0 +1,229 @@
|
||||
<script lang="ts" setup>
|
||||
import { CSSProperties ,ref,toRef,computed,watch} from 'vue'
|
||||
import { cloneDeep } from 'lodash-es'
|
||||
import { IconJson } from '@/components/Icon/src/data'
|
||||
|
||||
defineOptions({ name: 'IconSelect' })
|
||||
|
||||
type ParameterCSSProperties = (item?: string) => CSSProperties | undefined
|
||||
|
||||
const props = defineProps({
|
||||
modelValue: {
|
||||
require: false,
|
||||
type: String
|
||||
}
|
||||
})
|
||||
const emit = defineEmits<{ (e: 'update:modelValue', v: string) }>()
|
||||
|
||||
const visible = ref(false)
|
||||
const inputValue = toRef(props, 'modelValue')
|
||||
const iconList = ref(IconJson)
|
||||
const icon = ref('add-location')
|
||||
const currentActiveType = ref('ep:')
|
||||
// 深拷贝图标数据,前端做搜索
|
||||
const copyIconList = cloneDeep(iconList.value)
|
||||
|
||||
const pageSize = ref(96)
|
||||
const currentPage = ref(1)
|
||||
|
||||
// 搜索条件
|
||||
const filterValue = ref('')
|
||||
|
||||
const tabsList = [
|
||||
{
|
||||
label: 'Element Plus',
|
||||
name: 'ep:'
|
||||
},
|
||||
{
|
||||
label: 'Font Awesome 4',
|
||||
name: 'fa:'
|
||||
},
|
||||
{
|
||||
label: 'Font Awesome 5 Solid',
|
||||
name: 'fa-solid:'
|
||||
}
|
||||
]
|
||||
|
||||
const pageList = computed(() => {
|
||||
if (currentPage.value === 1) {
|
||||
return copyIconList[currentActiveType.value]
|
||||
?.filter((v) => v.includes(filterValue.value))
|
||||
.slice(currentPage.value - 1, pageSize.value)
|
||||
} else {
|
||||
return copyIconList[currentActiveType.value]
|
||||
?.filter((v) => v.includes(filterValue.value))
|
||||
.slice(
|
||||
pageSize.value * (currentPage.value - 1),
|
||||
pageSize.value * (currentPage.value - 1) + pageSize.value
|
||||
)
|
||||
}
|
||||
})
|
||||
const iconCount = computed(() => {
|
||||
return copyIconList[currentActiveType.value] == undefined
|
||||
? 0
|
||||
: copyIconList[currentActiveType.value].length
|
||||
})
|
||||
|
||||
const iconItemStyle = computed((): ParameterCSSProperties => {
|
||||
return (item) => {
|
||||
if (inputValue.value === currentActiveType.value + item) {
|
||||
return {
|
||||
borderColor: 'var(--el-color-primary)',
|
||||
color: 'var(--el-color-primary)'
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
function handleClick({ props }) {
|
||||
currentPage.value = 1
|
||||
currentActiveType.value = props.name
|
||||
emit('update:modelValue', currentActiveType.value + iconList.value[currentActiveType.value][0])
|
||||
icon.value = iconList.value[currentActiveType.value][0]
|
||||
}
|
||||
|
||||
function onChangeIcon(item) {
|
||||
icon.value = item
|
||||
emit('update:modelValue', currentActiveType.value + item)
|
||||
visible.value = false
|
||||
}
|
||||
|
||||
function onCurrentChange(page) {
|
||||
currentPage.value = page
|
||||
}
|
||||
|
||||
watch(
|
||||
() => {
|
||||
return props.modelValue
|
||||
},
|
||||
() => {
|
||||
if (props.modelValue && props.modelValue.indexOf(':') >= 0) {
|
||||
currentActiveType.value = props.modelValue.substring(0, props.modelValue.indexOf(':') + 1)
|
||||
icon.value = props.modelValue.substring(props.modelValue.indexOf(':') + 1)
|
||||
}
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => {
|
||||
return filterValue.value
|
||||
},
|
||||
() => {
|
||||
currentPage.value = 1
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="selector">
|
||||
<ElInput v-model="inputValue" @click="visible = !visible">
|
||||
<template #append>
|
||||
<ElPopover
|
||||
:popper-options="{
|
||||
placement: 'auto'
|
||||
}"
|
||||
:visible="visible"
|
||||
:width="350"
|
||||
popper-class="pure-popper"
|
||||
trigger="click"
|
||||
>
|
||||
<template #reference>
|
||||
<div
|
||||
class="h-32px w-40px flex cursor-pointer items-center justify-center"
|
||||
@click="visible = !visible"
|
||||
>
|
||||
<Icon :icon="currentActiveType + icon" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<ElInput v-model="filterValue" class="p-2" clearable placeholder="搜索图标" />
|
||||
<ElDivider border-style="dashed" />
|
||||
|
||||
<ElTabs v-model="currentActiveType" @tab-click="handleClick">
|
||||
<ElTabPane
|
||||
v-for="(pane, index) in tabsList"
|
||||
:key="index"
|
||||
:label="pane.label"
|
||||
:name="pane.name"
|
||||
>
|
||||
<ElDivider border-style="dashed" class="tab-divider" />
|
||||
<ElScrollbar height="220px">
|
||||
<ul class="ml-2 flex flex-wrap px-2">
|
||||
<li
|
||||
v-for="(item, key) in pageList"
|
||||
:key="key"
|
||||
:style="iconItemStyle(item)"
|
||||
:title="item"
|
||||
class="icon-item mr-2 mt-1 w-1/10 flex cursor-pointer items-center justify-center border border-solid p-2"
|
||||
@click="onChangeIcon(item)"
|
||||
>
|
||||
<Icon :icon="currentActiveType + item" />
|
||||
</li>
|
||||
</ul>
|
||||
</ElScrollbar>
|
||||
</ElTabPane>
|
||||
</ElTabs>
|
||||
<ElDivider border-style="dashed" />
|
||||
|
||||
<ElPagination
|
||||
:current-page="currentPage"
|
||||
:page-size="pageSize"
|
||||
:total="iconCount"
|
||||
background
|
||||
class="h-10 flex items-center justify-center"
|
||||
layout="prev, pager, next"
|
||||
small
|
||||
@current-change="onCurrentChange"
|
||||
/>
|
||||
</ElPopover>
|
||||
</template>
|
||||
</ElInput>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.el-divider--horizontal {
|
||||
margin: 1px auto !important;
|
||||
}
|
||||
|
||||
.tab-divider.el-divider--horizontal {
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.icon-item {
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
border-color: var(--el-color-primary);
|
||||
transform: scaleX(1.05);
|
||||
transition: all 0.4s;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-tabs__nav-next) {
|
||||
font-size: 15px;
|
||||
line-height: 32px;
|
||||
box-shadow: -5px 0 5px -6px #ccc;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__nav-prev) {
|
||||
font-size: 15px;
|
||||
line-height: 32px;
|
||||
box-shadow: 5px 0 5px -6px #ccc;
|
||||
}
|
||||
|
||||
:deep(.el-input-group__append) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__item) {
|
||||
height: 30px;
|
||||
font-size: 12px;
|
||||
font-weight: normal;
|
||||
line-height: 30px;
|
||||
}
|
||||
|
||||
:deep(.el-tabs__header),
|
||||
:deep(.el-tabs__nav-wrap) {
|
||||
position: static;
|
||||
margin: 0;
|
||||
}
|
||||
</style>
|
||||
1962
src/components/icon/src/data.ts
Normal file
1962
src/components/icon/src/data.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,71 +1,71 @@
|
||||
import { readFileSync, readdirSync } from 'fs'
|
||||
|
||||
let idPerfix = ''
|
||||
const iconNames: string[] = []
|
||||
const svgTitle = /<svg([^>+].*?)>/
|
||||
const clearHeightWidth = /(width|height)="([^>+].*?)"/g
|
||||
const hasViewBox = /(viewBox="[^>+].*?")/g
|
||||
const clearReturn = /(\r)|(\n)/g
|
||||
// 清理 svg 的 fill
|
||||
const clearFill = /(fill="[^>+].*?")/g
|
||||
|
||||
function findSvgFile(dir: string): string[] {
|
||||
const svgRes = []
|
||||
const dirents = readdirSync(dir, {
|
||||
withFileTypes: true,
|
||||
})
|
||||
for (const dirent of dirents) {
|
||||
iconNames.push(`${idPerfix}-${dirent.name.replace('.svg', '')}`)
|
||||
if (dirent.isDirectory()) {
|
||||
svgRes.push(...findSvgFile(dir + dirent.name + '/'))
|
||||
} else {
|
||||
const svg = readFileSync(dir + dirent.name)
|
||||
.toString()
|
||||
.replace(clearReturn, '')
|
||||
.replace(clearFill, 'fill=""')
|
||||
.replace(svgTitle, ($1, $2) => {
|
||||
let width = 0
|
||||
let height = 0
|
||||
let content = $2.replace(clearHeightWidth, (s1: string, s2: string, s3: number) => {
|
||||
if (s2 === 'width') {
|
||||
width = s3
|
||||
} else if (s2 === 'height') {
|
||||
height = s3
|
||||
}
|
||||
return ''
|
||||
})
|
||||
if (!hasViewBox.test($2)) {
|
||||
content += `viewBox="0 0 ${width} ${height}"`
|
||||
}
|
||||
return `<symbol id="${idPerfix}-${dirent.name.replace('.svg', '')}" ${content}>`
|
||||
})
|
||||
.replace('</svg>', '</symbol>')
|
||||
svgRes.push(svg)
|
||||
}
|
||||
}
|
||||
return svgRes
|
||||
}
|
||||
|
||||
export const svgBuilder = (path: string, perfix = 'local') => {
|
||||
if (path === '') return
|
||||
idPerfix = perfix
|
||||
const res = findSvgFile(path)
|
||||
return {
|
||||
name: 'svg-transform',
|
||||
transformIndexHtml(html: string) {
|
||||
/* eslint-disable */
|
||||
return html.replace(
|
||||
'<body>',
|
||||
`
|
||||
<body>
|
||||
<svg id="local-icon" data-icon-name="${iconNames.join(
|
||||
','
|
||||
)}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
|
||||
${res.join('')}
|
||||
</svg>
|
||||
`
|
||||
)
|
||||
/* eslint-enable */
|
||||
},
|
||||
}
|
||||
}
|
||||
import { readFileSync, readdirSync } from 'fs'
|
||||
|
||||
let idPerfix = ''
|
||||
const iconNames: string[] = []
|
||||
const svgTitle = /<svg([^>+].*?)>/
|
||||
const clearHeightWidth = /(width|height)="([^>+].*?)"/g
|
||||
const hasViewBox = /(viewBox="[^>+].*?")/g
|
||||
const clearReturn = /(\r)|(\n)/g
|
||||
// 清理 svg 的 fill
|
||||
const clearFill = /(fill="[^>+].*?")/g
|
||||
|
||||
function findSvgFile(dir: string): string[] {
|
||||
const svgRes = []
|
||||
const dirents = readdirSync(dir, {
|
||||
withFileTypes: true,
|
||||
})
|
||||
for (const dirent of dirents) {
|
||||
iconNames.push(`${idPerfix}-${dirent.name.replace('.svg', '')}`)
|
||||
if (dirent.isDirectory()) {
|
||||
svgRes.push(...findSvgFile(dir + dirent.name + '/'))
|
||||
} else {
|
||||
const svg = readFileSync(dir + dirent.name)
|
||||
.toString()
|
||||
.replace(clearReturn, '')
|
||||
.replace(clearFill, 'fill=""')
|
||||
.replace(svgTitle, ($1, $2) => {
|
||||
let width = 0
|
||||
let height = 0
|
||||
let content = $2.replace(clearHeightWidth, (s1: string, s2: string, s3: number) => {
|
||||
if (s2 === 'width') {
|
||||
width = s3
|
||||
} else if (s2 === 'height') {
|
||||
height = s3
|
||||
}
|
||||
return ''
|
||||
})
|
||||
if (!hasViewBox.test($2)) {
|
||||
content += `viewBox="0 0 ${width} ${height}"`
|
||||
}
|
||||
return `<symbol id="${idPerfix}-${dirent.name.replace('.svg', '')}" ${content}>`
|
||||
})
|
||||
.replace('</svg>', '</symbol>')
|
||||
svgRes.push(svg)
|
||||
}
|
||||
}
|
||||
return svgRes
|
||||
}
|
||||
|
||||
export const svgBuilder = (path: string, perfix = 'local') => {
|
||||
if (path === '') return
|
||||
idPerfix = perfix
|
||||
const res = findSvgFile(path)
|
||||
return {
|
||||
name: 'svg-transform',
|
||||
transformIndexHtml(html: string) {
|
||||
/* eslint-disable */
|
||||
return html.replace(
|
||||
'<body>',
|
||||
`
|
||||
<body>
|
||||
<svg id="local-icon" data-icon-name="${iconNames.join(
|
||||
','
|
||||
)}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
|
||||
${res.join('')}
|
||||
</svg>
|
||||
`
|
||||
)
|
||||
/* eslint-enable */
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,49 +1,49 @@
|
||||
<template>
|
||||
<div v-if="isUrl" :style="urlIconStyle" class="url-svg svg-icon icon" />
|
||||
<svg v-else class="svg-icon icon" :style="iconStyle">
|
||||
<use :href="iconName" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, type CSSProperties } from 'vue'
|
||||
import { isExternal } from '@/utils/common'
|
||||
interface Props {
|
||||
name: string
|
||||
size: string
|
||||
color: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
name: '',
|
||||
size: '18px',
|
||||
color: '#000000',
|
||||
})
|
||||
|
||||
const s = `${props.size.replace('px', '')}px`
|
||||
const iconName = computed(() => `#${props.name}`)
|
||||
const iconStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
color: props.color,
|
||||
fontSize: s,
|
||||
}
|
||||
})
|
||||
const isUrl = computed(() => isExternal(props.name))
|
||||
const urlIconStyle = computed(() => {
|
||||
return {
|
||||
width: s,
|
||||
height: s,
|
||||
mask: `url(${props.name}) no-repeat 50% 50%`,
|
||||
'-webkit-mask': `url(${props.name}) no-repeat 50% 50%`,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div v-if="isUrl" :style="urlIconStyle" class="url-svg svg-icon icon" />
|
||||
<svg v-else class="svg-icon icon" :style="iconStyle">
|
||||
<use :href="iconName" />
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, type CSSProperties } from 'vue'
|
||||
import { isExternal } from '@/utils/common'
|
||||
interface Props {
|
||||
name: string
|
||||
size: string
|
||||
color: string
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
name: '',
|
||||
size: '18px',
|
||||
color: '#000000',
|
||||
})
|
||||
|
||||
const s = `${props.size.replace('px', '')}px`
|
||||
const iconName = computed(() => `#${props.name}`)
|
||||
const iconStyle = computed((): CSSProperties => {
|
||||
return {
|
||||
color: props.color,
|
||||
fontSize: s,
|
||||
}
|
||||
})
|
||||
const isUrl = computed(() => isExternal(props.name))
|
||||
const urlIconStyle = computed(() => {
|
||||
return {
|
||||
width: s,
|
||||
height: s,
|
||||
mask: `url(${props.name}) no-repeat 50% 50%`,
|
||||
'-webkit-mask': `url(${props.name}) no-repeat 50% 50%`,
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.svg-icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user