1
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,342 @@
|
||||
<script lang="ts" setup>
|
||||
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick } from 'vue'
|
||||
import { getDefaultColor, colorAddDeepen, setBgColorLightByDark, setTextColorLightByDark, isBlackAndWhite } from "../../core/util/xCoreColorUtil.uts"
|
||||
import { fillArrayCssValue, fillArrayCssValueBycolor, fillArrayCssValueByround, checkIsCssUnit, getUid, getUnit } from "../../core/util/xCoreUtil.uts"
|
||||
import { xConfig } from "../../config/xConfig.uts"
|
||||
import { xTween } from "../../core/util/xTween.uts"
|
||||
import { xTweenStatus, xTweenCallbackFunType, xTweenAnimate, xTweenEventCallFunType, xTweenEventCall } from "../../interface.uts"
|
||||
// #ifdef APP|| WEB
|
||||
import remixicon from "./remixicon.uts"
|
||||
// #endif
|
||||
|
||||
/**
|
||||
* @name 图标 xIcon
|
||||
* @description 图标使用的是开源图标:[https://remixicon.com/](https://remixicon.com/),版本是:4.5.0 ,使用时,不用带ri-前缀。
|
||||
* @page /pages/index/icon
|
||||
* @category 常用组件
|
||||
* @constant 平台兼容
|
||||
* | Harmony | H5 | andriod | IOS | 小程序 | UTS | UNIAPP-X SDK | version |
|
||||
| --- | --- | --- | --- | --- | --- | --- | --- |
|
||||
| ☑ | ☑ | ☑️ | ☑️ | ☑️ | ☑️ | 4.76+ | 1.1.18 |
|
||||
*/
|
||||
defineOptions({name:"xIcon"})
|
||||
const emits = defineEmits(['click'])
|
||||
|
||||
type xIconPropsType = {
|
||||
/**
|
||||
* 图标名称,不带ri-前缀
|
||||
* 也可以是本地或者远程图片
|
||||
*/
|
||||
name: string,
|
||||
/**
|
||||
* 图标大小,单位任意,比如"12",12px,12rpx
|
||||
*/
|
||||
fontSize: string,
|
||||
/**
|
||||
* 自定义图标字体,前提是
|
||||
* 你要在appuvue中已经安装好字体文件,
|
||||
* 否则无法使用。
|
||||
* 要让自定图标生效你需要配合code属性一起使用
|
||||
*/
|
||||
fontFamily: string,
|
||||
/**
|
||||
* 图标的16进制字符串,注意不含u
|
||||
* 比如:ea0c,ea14这种,
|
||||
* 如果你提供了code优化解析这,那么name将失效,如果你是纯字体图标使用
|
||||
* 你可以使用这个属性,可以提供性能和自己定义的图标会比较方便。
|
||||
*/
|
||||
code: string,
|
||||
/**
|
||||
* 图标颜色
|
||||
*/
|
||||
color: string,
|
||||
/**
|
||||
* 暗黑时的文本颜色,如果你不提供,将自动反转。
|
||||
* 自动反转是根据亮度反转,色相不变。
|
||||
*/
|
||||
darkColor: string,
|
||||
/**
|
||||
* 是否旋转动画
|
||||
*/
|
||||
spin: boolean,
|
||||
/**
|
||||
* 旋转角度
|
||||
*/
|
||||
rotation: number,
|
||||
/**
|
||||
* 动画时间
|
||||
*/
|
||||
duration: number,
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<xIconPropsType>(), {
|
||||
name: "home-3-fill",
|
||||
fontSize: "16",
|
||||
fontFamily: "remixicon",
|
||||
code: "",
|
||||
color: "black",
|
||||
darkColor: "",
|
||||
spin: false,
|
||||
rotation: 0,
|
||||
duration: 1500,
|
||||
})
|
||||
|
||||
// data -> refs
|
||||
const xIcon = ref<Element | null>(null)
|
||||
const refreshId = ref(1)
|
||||
const id = ref<string>("xIconspin" + getUid())
|
||||
const element = ref<UniElement | null>(null)
|
||||
const rotationDeg = ref<number>(0)
|
||||
const isLoad = ref<boolean>(false)
|
||||
const isdestory = ref<boolean>(false)
|
||||
const status = ref<string>('play')
|
||||
const tid = ref<number>(0)
|
||||
const xt = ref<xTween>(new xTween())
|
||||
const xIcons = ref<UniElement | null>(null)
|
||||
|
||||
// computed replacements
|
||||
const _iconName = computed((): string => {
|
||||
return props.name
|
||||
})
|
||||
|
||||
const _mpcode = computed((): string => {
|
||||
let cname = ''
|
||||
// #ifdef MP
|
||||
cname = props.code==''?('ri-'+props.name):'';
|
||||
// #endif
|
||||
return cname
|
||||
})
|
||||
|
||||
const _isFileImg = computed((): boolean => {
|
||||
if (props.name.lastIndexOf(".") > -1 ||
|
||||
props.name.indexOf("ftp:") > -1 ||
|
||||
props.name.indexOf("https:") > -1 ||
|
||||
props.name.indexOf("http:") > -1 ||
|
||||
props.name.indexOf("data:image") > -1
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
|
||||
const iconName = computed((): string => {
|
||||
if (_isFileImg.value) return props.name
|
||||
let texts = ""
|
||||
try {
|
||||
// #ifdef APP||WEB
|
||||
let codestr = ''
|
||||
if(props.code==''){
|
||||
codestr = remixicon.getString(props.name)!
|
||||
}else{
|
||||
codestr = props.code
|
||||
}
|
||||
// #endif
|
||||
|
||||
// #ifdef APP-ANDROID
|
||||
let codePoint = Integer.parseInt(codestr, 16);
|
||||
let charArray = Character.toChars(codePoint);
|
||||
texts = new String(charArray);
|
||||
// #endif
|
||||
// #ifdef APP-IOS|| WEB||APP-HARMONY
|
||||
texts = String.fromCharCode(parseInt(codestr, 16));
|
||||
// #endif
|
||||
|
||||
// #ifdef MP
|
||||
if(props.code!=''){
|
||||
texts = String.fromCharCode(parseInt(props.code, 16));
|
||||
}
|
||||
// #endif
|
||||
|
||||
} catch (e) {
|
||||
console.error("xicon解析失败。", e)
|
||||
}
|
||||
return texts
|
||||
})
|
||||
|
||||
const _fontSize = computed((): string => {
|
||||
let fontSize = checkIsCssUnit(props.fontSize, xConfig.unit);
|
||||
if (xConfig.fontScale == 1) return fontSize;
|
||||
let sizeNumber = parseInt(fontSize)
|
||||
if (isNaN(sizeNumber)) {
|
||||
sizeNumber = 16
|
||||
}
|
||||
return (sizeNumber * xConfig.fontScale).toString() + getUnit(fontSize)
|
||||
})
|
||||
|
||||
const _color = computed((): string => {
|
||||
let color = props.color==""?'black':props.color;
|
||||
if (xConfig.dark == 'dark') {
|
||||
if (props.darkColor != "") {
|
||||
color = props.darkColor!
|
||||
return getDefaultColor(color)
|
||||
}
|
||||
return setTextColorLightByDark(color)
|
||||
}
|
||||
return getDefaultColor(color);
|
||||
})
|
||||
|
||||
const _spin = computed((): boolean => props.spin)
|
||||
const _rotation = computed((): number => props.rotation)
|
||||
|
||||
function setRadeg() {
|
||||
try {
|
||||
element.value = xIcons.value as UniElement
|
||||
element.value!.style.setProperty("transition-duration", props.duration.toString() + 'ms')
|
||||
element.value!.style.setProperty("transform", `rotate(${_rotation.value}deg)`)
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function playSpin() {
|
||||
if (!_spin.value || isdestory.value) return;
|
||||
|
||||
let elementLocal = xIcons.value as UniElement
|
||||
|
||||
// #ifdef APP || WEB
|
||||
xt.value.pause()
|
||||
xt.value.destroy()
|
||||
xt.value.startRender()
|
||||
xt.value.addAnimate({
|
||||
loop:-1,
|
||||
duration:props.duration,
|
||||
complete:(item:xTweenEventCallFunType)=>{
|
||||
},
|
||||
enter:(item:xTweenEventCallFunType)=>{
|
||||
elementLocal!.style.setProperty("transition-duration", '0ms')
|
||||
elementLocal!.style.setProperty("transform", `rotate(${360 * item.progress}deg)`)
|
||||
},
|
||||
pause:(item:xTweenEventCallFunType)=>{},
|
||||
} as xTweenAnimate)
|
||||
xt.value.play()
|
||||
// #endif
|
||||
}
|
||||
|
||||
function clickListen() {
|
||||
emits("click")
|
||||
}
|
||||
|
||||
|
||||
/** app加载的字体方式 */
|
||||
// https://cdn.tmui.design/public/static/remixicon.ttf
|
||||
function loadFontByX() {
|
||||
isLoad.value = true;
|
||||
|
||||
// uni.loadFontFace({
|
||||
// source: "url('static/remixicon.ttf')",
|
||||
// family: "remixicon",
|
||||
// success() {
|
||||
// this.isLoad = true;
|
||||
// uni.setStorageSync("loadedFontBytmx", "true")
|
||||
// },
|
||||
// fail() {
|
||||
// console.log('loadfontFail.---')
|
||||
// uni.setStorageSync("loadedFontBytmx", "")
|
||||
// },
|
||||
// complete() {
|
||||
// }
|
||||
// })
|
||||
}
|
||||
|
||||
|
||||
// watchers
|
||||
watch(():boolean => props.spin, () => {
|
||||
if (_spin.value) {
|
||||
playSpin();
|
||||
}else{
|
||||
xt.value.pause()
|
||||
xt.value.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
watch(():number => props.rotation, () => {
|
||||
if (_spin.value) return;
|
||||
setRadeg();
|
||||
})
|
||||
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
isdestory.value = true;
|
||||
clearTimeout(tid.value)
|
||||
xt.value.destroy()
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
loadFontByX();
|
||||
isdestory.value = false;
|
||||
if (_spin.value) {
|
||||
playSpin();
|
||||
} else {
|
||||
nextTick(() => {
|
||||
setRadeg();
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
<view class="faceBox">
|
||||
<!-- #endif -->
|
||||
<text
|
||||
v-if="!_isFileImg"
|
||||
@click="clickListen"
|
||||
:id="id"
|
||||
ref="xIcons"
|
||||
class="face"
|
||||
:class="[_spin?'faceSpinIcon':'',_mpcode]"
|
||||
:style="{
|
||||
'font-family': fontFamily,
|
||||
'font-size':_fontSize,
|
||||
'color':_color,
|
||||
'width':_fontSize,
|
||||
'height':_fontSize,
|
||||
'lineHeight':_fontSize
|
||||
}">
|
||||
{{iconName}}
|
||||
</text>
|
||||
<image @click="clickListen" :id="id" v-else ref="xIcons" :style="{width:_fontSize,height:_fontSize}" :src="iconName"></image>
|
||||
<!-- #ifdef MP-WEIXIN -->
|
||||
</view>
|
||||
<!-- #endif -->
|
||||
</template>
|
||||
|
||||
<style scoped >
|
||||
/* #ifdef MP-WEIXIN */
|
||||
.faceBox{
|
||||
display: inline-block;
|
||||
}
|
||||
/* #endif */
|
||||
.face {
|
||||
transition-property: transform;
|
||||
transition-duration: 0ms;
|
||||
transition-timing-function: linear;
|
||||
transform: rotate(0deg);
|
||||
|
||||
text-align: center;
|
||||
/* #ifdef WEB || MP-WEIXIN */
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
line-height: 1 !important;
|
||||
/* #endif */
|
||||
}
|
||||
|
||||
/* #ifdef WEB || MP-WEIXIN */
|
||||
.faceSpinIcon{
|
||||
animation:xFontIconRotate 1s linear infinite ;
|
||||
}
|
||||
@keyframes xFontIconRotate {
|
||||
0%{
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
100%{
|
||||
transform: rotate(360deg);
|
||||
}
|
||||
}
|
||||
/* #endif */
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user