英文:
How do transitions work on Images in Vue JS 3?
问题
I have been unable to apply a fade in transition to an image using Vue JS 3. The transition works fine with text, but the image just loads and renders as it would normally without a transition applied.
I have been trying to create an image loader, which will show a loading spinner until the image is loaded, then fade the loading spinner out and the image in once the image loads. Currently the loading spinner fades out as expected, but the image does not fade in.
Here is what I have in the image element:
<script setup>
import FadeTransition from '../transitions/fade-transition.vue';
import { reactive } from 'vue';
const props = defineProps({
imgUrl: String,
route: String
});
let getURL = function () {
return new URL(props.imgUrl, import.meta.url);
};
let show = reactive({showing: false});
let showImg = function () {
show.showing = true;
};
</script>
<template>
<div class="frame">
<FadeTransition><div v-show="!show.showing" class="loader"></div></FadeTransition>
<RouterLink :to="props.route"><FadeTransition><img v-show="show.showing" class="image" :src="getURL()" @load="showImg()"/></FadeTransition></RouterLink>
</div>
</template>
<style scoped>
.frame {
width: 33.3333%;
aspect-ratio: 1/1;
margin: 0px;
/*inline-block leaves space for descenders (e.g: letter y or g) so space between rows is wrong*/
display: inline-flex;
position: relative;
padding: 6px;
}
.image {
width: calc(100% - 12px);
height: calc(100% - 12px);
position: absolute;
}
.loader {
border: 4px solid var(--grey);
border-top: 4px solid var(--darkGrey);
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 5s linear infinite;
position: absolute;
left: calc(50% - 15px);
top: calc(50% - 15px);
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
and the FadeTransition component is:
<script>
</script>
<template>
<Transition name="fade">
<slot></slot>
</Transition>
</template>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
I have tried swapping the image for a text block, which works correctly, leading me to conclude that the problem I have is that the transition is not being correctly applied to the image.
How can I get the transition to apply correctly to the image?
英文:
I have been unable to apply a fade in transition to an image using Vue JS 3. The transition works fine with text, but the image just loads and renders as it would normally without a transition applied.
I have been trying to create an image loader, which will show a loading spinner until the image is loaded, then fade the loading spinner out and the image in once the image loads. Currently the loading spinner fades out as expected, but the image does not fade in.
Here is what I have in the image element:
<script setup>
import FadeTransition from '../transitions/fade-transition.vue';
import { reactive } from 'vue'
const props = defineProps({
imgUrl: String,
route: String
})
let getURL = function () {
return new URL(props.imgUrl, import.meta.url);
}
let show = reactive({showing: false});
let showImg = function () {
show.showing = true;
}
</script>
<template>
<div class="frame">
<FadeTransition><div v-show="!show.showing" class="loader"></div></FadeTransition>
<RouterLink :to="props.route"><FadeTransition><img v-show="show.showing" class="image" :src="getURL()" @load="showImg()"/></FadeTransition></RouterLink>
</div>
</template>
<style scoped>
.frame {
width: 33.3333%;
aspect-ratio: 1/1;
margin: 0px;
/*inline-block leaves space for descenders (e.g: letter y or g) so space between rows is wrong*/
display: inline-flex;
position: relative;
padding: 6px;
}
.image {
width: calc(100% - 12px);
height: calc(100% - 12px);
position: absolute;
}
.loader {
border: 4px solid var(--grey);
border-top: 4px solid var(--darkGrey);
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 5s linear infinite;
position: absolute;
left: calc(50% - 15px);
top: calc(50% - 15px);
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
</style>
and the FadeTransition component is:
<script>
</script>
<template>
<Transition name="fade">
<slot></slot>
</Transition>
</template>
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s ease;
}
.fade-enter-from,
.fade-leave-to {
opacity: 0;
}
</style>
I have tried swapping the image for a text block, which works correctly, leading me to conclude that the problem I have is that the transition is not being correctly applied to the image.
How can I get the transition to apply correctly to the image?
答案1
得分: 1
如果 imgUrl
是一个属性(prop),我会添加一个监视器(watcher),当URL发生变化时重新设置组件:
watch(
() => props.imgUrl,
() => {
show.showing = false
},
{ immediate: true }
)
否则,在初始加载后,当URL变化时不会触发加载动画和淡出效果。
其余部分看起来都完全正常。
如果我漏掉了什么,请告诉我。
英文:
Hmm, all I can tell you is that it seems to work perfectly in the playground
If imgUrl
is a prop, I would add a watcher that resets the component when the URL changes:
watch(
() => props.imgUrl,
() => {
show.showing = false
},
{immediate: true}
)
Otherwise, the loading animation and the fade will not be triggered when the URL changes after the initial load.
The rest looks perfectly fine.
Please let me know if I am missing something.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论