-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
24 changed files
with
893 additions
and
169 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
142 changes: 142 additions & 0 deletions
142
packages/nice2cu-ui-mobile-example/src/views/componentsViews/Avatar.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
<template> | ||
<div class="container"> | ||
<n-nav-bar title="Avatar 头像" show-left left-text="" :shadow-buttom="true" fixed-top safe-area-inset-top placeholder></n-nav-bar> | ||
|
||
<section> | ||
<div class="title">基础用法</div> | ||
<div class="content unflex"> | ||
<n-space align="center"> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
</n-space> | ||
</div> | ||
</section> | ||
<section> | ||
<div class="title">尺寸(size)</div> | ||
<div class="content unflex"> | ||
<n-space align="center"> | ||
<n-avatar size="mini" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar size="small" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar size="large" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar size="80" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
</n-space> | ||
</div> | ||
</section> | ||
<section> | ||
<div class="title">形状(round)</div> | ||
<div class="content unflex"> | ||
<n-space align="center"> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar :round="false" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
</n-space> | ||
</div> | ||
</section> | ||
<section> | ||
<div class="title">边框/边框颜色(bordered / borderColor)</div> | ||
<div class="content unflex"> | ||
<n-space align="center"> | ||
<n-avatar bordered src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar bordered border-color="rgb(33, 150, 243)" src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
</n-space> | ||
</div> | ||
</section> | ||
<section> | ||
<div class="title">填充模式(fit)</div> | ||
<div class="content unflex"> | ||
<n-space align="center"> | ||
<n-space direction="column" align="center"> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="fill"></n-avatar> | ||
<span>fill</span> | ||
</n-space> | ||
<n-space direction="column" align="center"> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="contain"></n-avatar> | ||
<span>contain</span> | ||
</n-space> | ||
<n-space direction="column" align="center"> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="cover"></n-avatar> | ||
<span>cover</span> | ||
</n-space> | ||
<n-space direction="column" align="center"> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="none"></n-avatar> | ||
<span>none</span> | ||
</n-space> | ||
<n-space direction="column" align="center"> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp" fit="scale-down"></n-avatar> | ||
<span>scale-down</span> | ||
</n-space> | ||
</n-space> | ||
</div> | ||
</section> | ||
<section> | ||
<div class="title">文字模式 / 背景颜色(color)</div> | ||
<div class="content unflex"> | ||
<n-space align="center"> | ||
<n-avatar color="#e3b4b8">NICE2CU</n-avatar> | ||
<n-avatar color="#c08eaf">卡利斯</n-avatar> | ||
</n-space> | ||
</div> | ||
</section> | ||
<section> | ||
<div class="title">头像分组</div> | ||
<div class="content unflex"> | ||
<n-avatar-group> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar color="#c08eaf">卡利斯</n-avatar> | ||
<n-avatar color="#e3b4b8">NICE2CU</n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadc016afb6.jpg"></n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbffd9ea0.jpg"></n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbff3d163.jpg"></n-avatar> | ||
</n-avatar-group> | ||
</div> | ||
</section> | ||
<section> | ||
<div class="title">最大展示(maxLength)</div> | ||
<div class="content unflex"> | ||
<n-avatar-group :max-length="5"> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar color="#c08eaf">卡利斯</n-avatar> | ||
<n-avatar color="#e3b4b8">NICE2CU</n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadc016afb6.jpg"></n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbffd9ea0.jpg"></n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbff3d163.jpg"></n-avatar> | ||
</n-avatar-group> | ||
</div> | ||
</section> | ||
<section> | ||
<div class="title">纵向展示(vertical)</div> | ||
<div class="content unflex"> | ||
<n-avatar-group vertical> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar color="#c08eaf">卡利斯</n-avatar> | ||
<n-avatar color="#e3b4b8">NICE2CU</n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadc016afb6.jpg"></n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbffd9ea0.jpg"></n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbff3d163.jpg"></n-avatar> | ||
</n-avatar-group> | ||
</div> | ||
</section> | ||
<section> | ||
<div class="title">间距(offset)</div> | ||
<div class="content unflex"> | ||
<n-avatar-group offset="10"> | ||
<n-avatar src="https://bu.dusays.com/2023/06/04/647c4b5936222.webp"></n-avatar> | ||
<n-avatar color="#c08eaf">卡利斯</n-avatar> | ||
<n-avatar color="#e3b4b8">NICE2CU</n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadc016afb6.jpg"></n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbffd9ea0.jpg"></n-avatar> | ||
<n-avatar src="https://bu.dusays.com/2023/08/15/64dadbff3d163.jpg"></n-avatar> | ||
</n-avatar-group> | ||
</div> | ||
</section> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
import { ref } from 'vue'; | ||
const text = ref('卡利斯'); | ||
const clickfun = () => { | ||
text.value = '卡利斯斯特林'; | ||
}; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
<template> | ||
<div | ||
ref="avatarEle" | ||
:class="[bem.b(), innerSize(size) ? bem.m(size as string) : '', round ? bem.m('round') : '', bordered ? bem.m('bordered') : '']" | ||
:style="{ | ||
width: !innerSize(size) ? handleUnit(size) : undefined, | ||
height: !innerSize(size) ? handleUnit(size) : undefined, | ||
borderColor, | ||
backgroundColor: color, | ||
}" | ||
@click="onClick" | ||
> | ||
<template v-if="src"> | ||
<img | ||
v-if="lazy" | ||
v-lazy="{ src: src, loading: loading, error: error, onLoadImg: handleImgLoad, onErrorImg: handleImgError }" | ||
:class="bem.e('image')" | ||
:alt="alt" | ||
:style="{ objectFit: fit }" | ||
/> | ||
<img v-else :class="bem.e('image')" :src="imgSrc" :alt="alt" :style="{ objectFit: fit }" /> | ||
</template> | ||
|
||
<div v-else ref="textEle" :class="bem.e('text')" :style="{ transform: `scale(${scale})` }"> | ||
<slot /> | ||
</div> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { defineComponent, nextTick, onActivated, onMounted, onUpdated, ref } from 'vue'; | ||
import { createNamespace } from '../../utils/create'; | ||
import { handleUnit } from '../../utils/tools'; | ||
import Lazy from '../../directives/lazy'; | ||
import { LazyEventOptions } from '../../directives/lazy'; | ||
import { defaultLoadingImg, defaultLoadingError } from '../../directives/lazy/defaultImg'; | ||
import { AvatarProps, AvatarPropsType, innerSize } from './AvatarProps'; | ||
import './style/avatar.less'; | ||
export default defineComponent({ | ||
name: 'NAvatar', | ||
directives: { Lazy }, | ||
props: AvatarProps, | ||
setup(props: AvatarPropsType) { | ||
const bem = createNamespace('avatar'); | ||
const avatarEle = ref<HTMLElement | null>(); | ||
const textEle = ref<HTMLElement | null>(); | ||
const imgSrc = ref(props.loading ?? defaultLoadingImg); | ||
const scale = ref<number>(1); | ||
let isMounted = false; | ||
const getScale = () => { | ||
if (!avatarEle.value || !textEle.value) { | ||
scale.value = 1; | ||
return; | ||
} | ||
const avatarEleWidth = avatarEle.value.offsetWidth; | ||
const textEleWidth = textEle.value.offsetWidth; | ||
if (avatarEleWidth > textEleWidth) { | ||
scale.value = 1; | ||
} else { | ||
scale.value = avatarEleWidth / textEleWidth; | ||
} | ||
}; | ||
const handleImgLoad = (e: Event) => { | ||
const { onLoad } = props; | ||
if ((e as unknown as LazyEventOptions).status === 'success' && onLoad) { | ||
onLoad(e); | ||
} | ||
}; | ||
const handleImgError = (e: Event) => { | ||
const { onError } = props; | ||
if ((e as unknown as LazyEventOptions).status === 'error' && onError) { | ||
onError(e); | ||
} | ||
}; | ||
const imageLoad = () => { | ||
const { lazy, src, error, onLoad, onError } = props; | ||
if (!lazy) { | ||
let image = new Image(); | ||
image.src = src as string; | ||
image.onerror = (e: Event | string) => { | ||
imgSrc.value = error ?? defaultLoadingError; | ||
if (onError) onError(e as Event); | ||
}; | ||
image.onload = (e: Event | string) => { | ||
imgSrc.value = src as string; | ||
if (onLoad) onLoad(e as Event); | ||
}; | ||
} | ||
}; | ||
if (!props.lazy && props.src) { | ||
imageLoad(); | ||
} | ||
onMounted(() => { | ||
nextTick(() => { | ||
isMounted = true; | ||
getScale(); | ||
}); | ||
}); | ||
onActivated(() => { | ||
if (!isMounted) return; | ||
getScale(); | ||
}); | ||
onUpdated(() => { | ||
getScale(); | ||
}); | ||
return { bem, avatarEle, textEle, imgSrc, innerSize, handleUnit, scale, handleImgLoad, handleImgError }; | ||
}, | ||
}); | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
import { ExtractPropTypes, PropType } from 'vue'; | ||
import { isString, isNumber } from '../../utils/tools'; | ||
|
||
export const innerSize = (size: any): boolean => { | ||
return ['mini', 'small', 'normal', 'large'].includes(size); | ||
}; | ||
|
||
const sizeValidator = (size: any): boolean => { | ||
return innerSize(size) || isString(size) || isNumber(size); | ||
}; | ||
|
||
const fitValidator = (fit: string): boolean => { | ||
return ['fill', 'contain', 'cover', 'none', 'scale-down'].includes(fit); | ||
}; | ||
|
||
export const AvatarProps = { | ||
round: { | ||
type: Boolean, | ||
default: true, | ||
}, | ||
size: { | ||
type: [String, Number] as PropType<'mini' | 'small' | 'normal' | 'large' | number | string>, | ||
validator: sizeValidator, | ||
default: 'normal', | ||
}, | ||
alt: { | ||
type: String, | ||
}, | ||
color: { | ||
type: String, | ||
}, | ||
src: { | ||
type: String, | ||
}, | ||
fit: { | ||
type: String as PropType<'fill' | 'contain' | 'cover' | 'none' | 'scale-down'>, | ||
validator: fitValidator, | ||
default: 'cover', | ||
}, | ||
bordered: { | ||
type: Boolean, | ||
default: false, | ||
}, | ||
borderColor: { | ||
type: String, | ||
}, | ||
loading: { | ||
type: String, | ||
}, | ||
error: { | ||
type: String, | ||
}, | ||
lazy: { | ||
type: Boolean, | ||
default: false, | ||
}, | ||
onLoad: { | ||
type: Function as PropType<(e: Event) => void | Promise<any>>, | ||
}, | ||
onError: { | ||
type: Function as PropType<(e: Event) => void | Promise<any>>, | ||
}, | ||
onClick: { | ||
type: Function as PropType<(e: Event) => void | Promise<any>>, | ||
}, | ||
}; | ||
|
||
export type AvatarPropsType = ExtractPropTypes<typeof AvatarProps>; |
Oops, something went wrong.