|
@@ -6,12 +6,16 @@
|
|
|
:class="innerClass"
|
|
:class="innerClass"
|
|
|
@click="handleClick"
|
|
@click="handleClick"
|
|
|
>
|
|
>
|
|
|
|
|
+ <view v-if="showBackgroundEffect" :style="(backgroundEffectStyle as any)">
|
|
|
|
|
+ </view>
|
|
|
|
|
+ <view v-if="showBackgroundEffect" :style="(backgroundEffectStyle2 as any)">
|
|
|
|
|
+ </view>
|
|
|
<image
|
|
<image
|
|
|
:style="{
|
|
:style="{
|
|
|
- width: style.width,
|
|
|
|
|
- height: style.height,
|
|
|
|
|
|
|
+ width: precentOrFull(style.width),
|
|
|
|
|
+ height: precentOrFull(style.height),
|
|
|
}"
|
|
}"
|
|
|
- :mode="($attrs.mode as any)"
|
|
|
|
|
|
|
+ :mode="(mode as any)"
|
|
|
:lazyLoad="$attrs.lazyLoad"
|
|
:lazyLoad="$attrs.lazyLoad"
|
|
|
:fadeShow="$attrs.fadeShow"
|
|
:fadeShow="$attrs.fadeShow"
|
|
|
:webp="$attrs.webp"
|
|
:webp="$attrs.webp"
|
|
@@ -69,6 +73,10 @@ export interface ImageProps {
|
|
|
* 是否显示灰色占位,默认是
|
|
* 是否显示灰色占位,默认是
|
|
|
*/
|
|
*/
|
|
|
showGrey?: boolean,
|
|
showGrey?: boolean,
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 在填充模式下是否显示背景模糊样式,默认是
|
|
|
|
|
+ */
|
|
|
|
|
+ showBackgroundEffect?: boolean,
|
|
|
width?: string|number,
|
|
width?: string|number,
|
|
|
height?: string|number,
|
|
height?: string|number,
|
|
|
/**
|
|
/**
|
|
@@ -92,17 +100,20 @@ export interface ImageProps {
|
|
|
*/
|
|
*/
|
|
|
touchable?: boolean,
|
|
touchable?: boolean,
|
|
|
/**
|
|
/**
|
|
|
- * 图片是否有圆角
|
|
|
|
|
|
|
+ * 图片是否有圆型(50%圆角)
|
|
|
|
|
+ * @default false
|
|
|
*/
|
|
*/
|
|
|
round?: boolean,
|
|
round?: boolean,
|
|
|
/**
|
|
/**
|
|
|
- * 当round为true的圆角大小,默认是50%
|
|
|
|
|
|
|
+ * 圆角大小
|
|
|
|
|
+ * @default 0
|
|
|
*/
|
|
*/
|
|
|
radius?: string|number,
|
|
radius?: string|number,
|
|
|
/**
|
|
/**
|
|
|
* 内部样式
|
|
* 内部样式
|
|
|
*/
|
|
*/
|
|
|
innerStyle?: object;
|
|
innerStyle?: object;
|
|
|
|
|
+ mode?: 'aspectFill' | 'aspectFit' | 'widthFix' | 'heightFix' | 'top' | 'bottom' | 'left' | 'right' | 'center',
|
|
|
innerClass?: string,
|
|
innerClass?: string,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -120,14 +131,17 @@ const props = withDefaults(defineProps<ImageProps>(), {
|
|
|
showLoading: () => propGetThemeVar('ImageShowLoading', true),
|
|
showLoading: () => propGetThemeVar('ImageShowLoading', true),
|
|
|
showFailed: () => propGetThemeVar('ImageShowFailed', true),
|
|
showFailed: () => propGetThemeVar('ImageShowFailed', true),
|
|
|
showGrey: () => propGetThemeVar('ImageShowGrey', false),
|
|
showGrey: () => propGetThemeVar('ImageShowGrey', false),
|
|
|
|
|
+ showBackgroundEffect: () => propGetThemeVar('ImageShowBackgroundEffect', true),
|
|
|
loading: false,
|
|
loading: false,
|
|
|
loadingColor: () => propGetThemeVar('ImageLoadingColor', 'border.default'),
|
|
loadingColor: () => propGetThemeVar('ImageLoadingColor', 'border.default'),
|
|
|
loadingSize: () => propGetThemeVar('ImageLoadingSize', 50),
|
|
loadingSize: () => propGetThemeVar('ImageLoadingSize', 50),
|
|
|
touchable: false,
|
|
touchable: false,
|
|
|
round: () => propGetThemeVar('ImageRound', false),
|
|
round: () => propGetThemeVar('ImageRound', false),
|
|
|
- radius: () => propGetThemeVar('ImageRadius', '50%'),
|
|
|
|
|
|
|
+ radius: () => propGetThemeVar('ImageRadius', ''),
|
|
|
})
|
|
})
|
|
|
const emit = defineEmits([ 'click' ]);
|
|
const emit = defineEmits([ 'click' ]);
|
|
|
|
|
+const showBackgroundEffect = computed(() => props.showBackgroundEffect && props.mode === 'aspectFit');
|
|
|
|
|
+
|
|
|
|
|
|
|
|
const isErrorState = ref(false);
|
|
const isErrorState = ref(false);
|
|
|
const isLoadState = ref(true);
|
|
const isLoadState = ref(true);
|
|
@@ -136,7 +150,7 @@ const instance = getCurrentInstance();
|
|
|
|
|
|
|
|
const style = computed(() => {
|
|
const style = computed(() => {
|
|
|
const o : Record<string, any> = {
|
|
const o : Record<string, any> = {
|
|
|
- borderRadius: props.round ? themeContext.resolveThemeSize(props.radius) : '',
|
|
|
|
|
|
|
+ borderRadius: props.round ? '50%' : themeContext.resolveThemeSize(props.radius),
|
|
|
backgroundColor: isErrorState.value || props.showGrey ? themeContext.resolveThemeColor('background.imageBox') : 'transparent',
|
|
backgroundColor: isErrorState.value || props.showGrey ? themeContext.resolveThemeColor('background.imageBox') : 'transparent',
|
|
|
overflow: 'hidden',
|
|
overflow: 'hidden',
|
|
|
width: themeContext.resolveThemeSize(props.width),
|
|
width: themeContext.resolveThemeSize(props.width),
|
|
@@ -145,8 +159,40 @@ const style = computed(() => {
|
|
|
}
|
|
}
|
|
|
return o;
|
|
return o;
|
|
|
});
|
|
});
|
|
|
|
|
+const backgroundEffectStyle = computed(() => ({
|
|
|
|
|
+ position: 'absolute',
|
|
|
|
|
+ left: 0,
|
|
|
|
|
+ right: 0,
|
|
|
|
|
+ top: 0,
|
|
|
|
|
+ bottom: 0,
|
|
|
|
|
+ zIndex: 1,
|
|
|
|
|
+ backgroundPosition: 'center',
|
|
|
|
|
+ backgroundSize: 'cover',
|
|
|
|
|
+ backgroundImage: `url('${props.src || props.defaultImage}')`,
|
|
|
|
|
+ filter: 'blur(3px)',
|
|
|
|
|
+}))
|
|
|
|
|
+const backgroundEffectStyle2 = computed(() => ({
|
|
|
|
|
+ position: 'absolute',
|
|
|
|
|
+ left: 0,
|
|
|
|
|
+ right: 0,
|
|
|
|
|
+ top: 0,
|
|
|
|
|
+ bottom: 0,
|
|
|
|
|
+ zIndex: 1,
|
|
|
|
|
+ backgroundRepeat: 'no-repeat',
|
|
|
|
|
+ backgroundPosition: 'center',
|
|
|
|
|
+ backgroundSize: 'contain',
|
|
|
|
|
+ backgroundImage: `url('${props.src || props.defaultImage}')`,
|
|
|
|
|
+}))
|
|
|
const realWidth = ref(0);
|
|
const realWidth = ref(0);
|
|
|
|
|
|
|
|
|
|
+function precentOrFull(value: string|number) {
|
|
|
|
|
+ if (typeof value === 'number')
|
|
|
|
|
+ return value;
|
|
|
|
|
+ if (typeof value === 'string' && value.endsWith('%'))
|
|
|
|
|
+ return '100%';
|
|
|
|
|
+ return value;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function handleClick() {
|
|
function handleClick() {
|
|
|
if (props.clickPreview) {
|
|
if (props.clickPreview) {
|
|
|
uni.previewImage({
|
|
uni.previewImage({
|