Making smooth transition from image placeholder to images when they are loaded - javascript

I am using swiper slider in my project, and I am wondering how can I have some smooth transition from image placeholders that I would replace with real images when they are loaded. So, in my case I have made a slider that looks like this:
<div class="swiper-slide">
<a href="/player/{{ $player->id }}/{{ $player->fullName }}">
<div class="mdc-card player-slider-card">
<img data-src="https://placeimg.com/250/300/any" class="player-images"/>
<div class="card-img-overlay">
<section class="mdc-card__media">
<i class="material-icons player-icon">person_outline</i>
<h3 class="mdc-card__title mdc-card__title--large">{{ $player->first_name }} {{ $player->last_name }}</h3>
</section>
<div class="mdc-card__primary">
<h4 class="mdc-card__subtitle">
{{ $player->nationality }}
#if($player->position != '')
| {{ $player->position }}
#endif
</h4>
</div>
</div>
</div>
</a>
</div>
I have made img tags with data-src attribute that I am later removing and adding the src attribute, when the images are loaded and I am at the same time removing the icon person_outline that I have as an image placeholder. This is the scss file:
app.scss
$white: #fff;
#mixin pulse {
-webkit-animation: pulse .65s infinite alternate;
animation: pulse .65s infinite alternate;
}
#keyframes pulse {
0%{opacity:.5}100%{opacity:1}
}
.slider-section {
position: relative;
.arrow-left, .arrow-right {
position: absolute;
top: 40%;
z-index: 10;
}
.arrow-left {
left: 5px;
}
.arrow-right {
right: 5px;
}
.swiper-slide {
a {
text-decoration: none;
}
}
.player-slider-card {
background: #E1E9EE;
color: $white;
width: 250px;
#include pulse;
h3, h4 {
#include pulse;
color: $white;
}
img {
opacity: 1;
transition: opacity 0.3s;
}
img[data-src] {
opacity: 0;
}
.mdc-card__media {
height: 300px;
}
.player-icon {
margin: auto;
font-size: 78px;
margin-bottom: 50px;
margin-top: 50px;
}
}
}
And this is the js file:
app.js
import Swiper from 'swiper';
const removePlaceholder = (item) => {
setTimeout(() => {
let slides = document.querySelectorAll(`.${item}-slider-card`);
let images = document.querySelectorAll(`.${item}-images`);
let placeholders = document.querySelectorAll(`.${item}-icon`);
slides.forEach(el => {
el.classList.remove(`${item}-slider-card`);
});
images.forEach(el => {
el.setAttribute('src', el.getAttribute('data-src'));
el.removeAttribute('data-src');
})
placeholders.forEach(el => {
el.remove();
})
}, 3000);
}
const sliderOptions = (nextEl, prevEl) => {
return {
direction: 'horizontal',
slidesPerView: 5,
simulateTouch: false,
spaceBetween: 1,
navigation: {
nextEl,
prevEl,
},
on: {
imagesReady:() => {
removePlaceholder('player');
},
},
breakpoints: {
1181: {
slidesPerView: 5
},
1180: {
slidesPerView: 4
},
1020: {
slidesPerView: 3
},
700: {
slidesPerView: 2
}
}
}
}
let videoOptions = sliderOptions('.js-arrow-videos-right', '.js-arrow-videos-left');
let playerOptions = sliderOptions('.js-arrow-players-right', '.js-arrow-players-left');
let swiperVideos = new Swiper('.js-videos-slider', videoOptions);
let swiperPlayers = new Swiper('.js-players-slider', playerOptions);
I have made a jsfiddle here. What I am wondering is how can I make a smooth transition when the images are being loaded. I thought I would maybe solve this with just a simple transition:
img {
opacity: 1;
transition: opacity 0.3s;
}
img[data-src] {
opacity: 0;
}
But, that didn't help, how can I achieve the similar effect to images on for example on themedium site or facebook.

Related

Add animation on remove child element

I'm using animation property CSS to animate the window when the user clicks maximize button. The window is created ONLY when the maximize button was clicked and the animation is working, but the problem is when I click the close button the window is doesn't animate. How can I animate when the close button is click?
JavaScript:
Show project image.
_showProjectImage(e) {
const btn = e.target.closest('.projects__maximize-btn');
if (!btn) return;
const { id } = btn.dataset;
const { image } = this._data.find(image => image.id === +id);
this._projectBox = e.target.closest('.projects__box');
const markup = this._generateProjectImage(image);
this._projectBox.insertAdjacentHTML('afterbegin', markup);
}
Hide project image.
_hideProjectImage(e) {
const btnClose = e.target.closest('.btn__close-window');
if (!btnClose) return;
this._projectBox.removeChild(this._projectBox.firstElementChild);
}
HTML Element:
_generateProjectImage(image) {
return `
<div class="projects__window">
<div class="projects__window-content">
<button class="projects__window-close btn__close-window">
<svg class="projects__window-icon">
<use
xlink:href="${icon}#icon-close"
></use>
</svg>
</button>
<div class="projects__window-box">
<img src="${image}" alt="" class="projects__window-image">
</div>
</div>
</div>
`;
}
CSS:
.projects {
&__window {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.7);
z-index: 1000;
animation: window-animate 300ms linear;
}
}
#keyframes window-animate {
from {
transform: scale(0);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}

React Slick slider, current active slide overlapped by next slide

I'm currently using Slick in order to make a carousel.
I'm having two issues right now, let's start with the first one.
1)
I'm currently using a slider in which i want to show 3 slides: the current image (Spyro), the previous one (Crash) and the next one (Tekken).
As you see, while the current slide correctly overlaps the previous one (Spyro > Crash), the next one overlaps the current slide (Tekken > Spyro).
Of course i want the current slide to be on top of both of them... How can i fix this?
I'm attacching the code below.
App.js
import "./App.css";
import { useEffect, useState } from "react";
import Slider from "react-slick";
import SliderData from "./SliderData";
import { AiOutlineArrowLeft, AiOutlineArrowRight } from "react-icons/ai";
function useWindowSize() {
const [size, setSize] = useState([window.innerHeight, window.innerWidth]);
useEffect(() => {
const handleResize = () => setSize([window.innerHeight, window.innerWidth]);
window.addEventListener("resize", handleResize);
}, [])
return size;
}
const array = SliderData.map((x) => {
return x.image;
})
console.log(array);
function App() {
const NextArrow = ({ onClick }) => {
return (
<div className="arrow next" onClick={onClick}>
<AiOutlineArrowRight />
</div>
);
};
const PrevArrow = ({ onClick }) => {
return (
<div className="arrow prev" onClick={onClick}>
<AiOutlineArrowLeft />
</div>
);
};
const [imageIndex, setImageIndex] = useState(0);
const [height, width] = useWindowSize();
const settings = {
className: "center",
infinite: true,
lazyLoad: true,
speed: 300,
slidesToShow: width > 1000 ? 3: 1,
centerMode: true,
centerPadding: "60px",
nextArrow: <NextArrow />,
prevArrow: <PrevArrow />,
beforeChange: (current, next) => {
console.log(current);
setImageIndex(next);
}
};
return (
<div className="App">
<Slider {...settings}>
{array.map((img, idx) => (
<div className={idx === imageIndex ? "slide activeSlide" : "slide"}>
<img src={img} alt={img} />
</div>
))}
</Slider>
</div>
);
}
export default App;
App.css
#import "~slick-carousel/slick/slick.css";
#import "~slick-carousel/slick/slick-theme.css";
.App {
width: 100%;
margin: 10rem auto;
height: 570px;
}
.slide img {
width: 35rem;
align-items: center;
margin: 0 auto;
z-index: 1;
}
.slide {
transform: scale(0.8);
transition: transform 300ms;
opacity: 0.5;
z-index: -1;
}
.activeSlide {
transform: scale(1.1);
align-items: center;
opacity: 1;
}
.arrow {
background-color: #fff;
position: absolute;
cursor: pointer;
z-index: 10;
}
.arrow svg {
transition: color 300ms;
}
.arrow svg:hover {
color: #68edff;
}
.next {
right: 3%;
top: 50%;
}
.prev {
left: 3%;
top: 50%;
}
SliderData.js
const SliderData = [
{
image:
"https://www.spaziogames.it/wp-content/uploads/2020/06/Crash-4-Pirate_06-29-20.jpg"
},
{
image:
"https://d2skuhm0vrry40.cloudfront.net/2018/articles/2018-07-18-14-24/news-videogiochi-spyro-reignited-trilogy-video-di-gameplay-livello-colossus-1531920251281.jpg/EG11/thumbnail/750x422/format/jpg/quality/60"
},
{
image: "https://i.ytimg.com/vi/OUh82pOFGDU/maxresdefault.jpg"
},
{
image: "https://www.psu.com/wp/wp-content/uploads/2020/07/MetalGearSolidRemake-1024x576.jpg"
}
];
export default SliderData;
2)
As you see, the active slide is not perfectly centered. Since i suck in CSS i did not use the display: flex; command.
What do you suggest? how can i fix this?
Thank you all.
You need to apply a position element to .slide for the z-index to work properly.
Note: z-index only works on positioned elements (position: absolute, position: relative, position: fixed, or position: sticky) and flex items (elements that are direct children of display:flex elements).
You can read more on z-index here
This is my answer for this issue. Basically you should set position and z-index for every item and set higher z-index for current active item
.App .slick-slide {
position: relative;
z-index: 1;
/* your choice, but make sure z-index of active slide is higher than this value */
}
.App .slick-slide.slick-current {
z-index: 10;
}

Javascript Animate Matching CSS Animation

I'm trying to get the Javascript animation to match exactly my css animation. I'm not sure why this is not working? I'm trying to use basic javascript. not jquery. The second div should be matching the animation of the first div
https://jsfiddle.net/JokerMartini/pf2nt4su/
let content = document.getElementById("content");
html = `<div class="base"></div>`;
let doc = new DOMParser().parseFromString(html, 'text/html');
let div = doc.body.firstChild;
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API
// keyframes
var keyframes = [{
backgroundColor: 'green',
opacity: 0
}, {
backgroundColor: 'blue',
opacity: 1
}];
// timing
let timing = {
duration: 2000,
iterations: Infinity
}
div.animate([
keyframes,
timing
]);
//elements += html;
content.append(div)
body {
background: #808080;
}
.base {
width: 180px;
height: 90px;
background: black;
}
.sample {
animation: play 2s steps(10) infinite;
}
#keyframes play {
0% {
background-color: green;
opacity: 0;
}
100% {
background-color: blue;
opacity: 1;
}
}
<div class='base sample'></div>
<div id="content"></div>
edit: Replace below (notice square brackets)
div.animate([
keyframes,
timing
]);
with:
document.getElementById("content").animate(
keyframes,
timing
);
Here working code snippet: (updated with steps in JS)
<style>
body {
background: #808080;
}
.base {
width: 180px;
height: 90px;
background: black;
}
.sample {
animation: play 2s steps(8) infinite;
}
#keyframes play {
0% {
background-color: green;
opacity: 0;
}
100% {
background-color: blue;
opacity: 1;
}
}
</style>
<div class='base sample'></div> <br>
<div id="content" class="base"></div>
<script>
let content = document.getElementById("content");
html = `<div class="base"></div>`;
let doc = new DOMParser().parseFromString(html, 'text/html');
let div = doc.body.firstChild;
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API
// keyframes
var keyframes = [{
backgroundColor: 'green',
opacity: 0
}, {
backgroundColor: 'blue',
opacity: 1
}];
// timing
var timing = {
duration: 2000,
easing: 'steps(8)',
iterations: Infinity
}
document.getElementById("content").animate(
keyframes,
timing
);
</script>
Move the content.append(div) before the animate call. Also, remove the [] from the animate.
I forked your JSFiddle. Here is a working version. https://jsfiddle.net/jrgiant/c5z7x2bu/.
let content = document.getElementById("content");
html = `<div class="base"></div>`;
let doc = new DOMParser().parseFromString(html, 'text/html');
let div = doc.body.firstChild;
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API
// keyframes
var keyframes = [{
backgroundColor: 'green',
opacity: 0
}, {
backgroundColor: 'blue',
opacity: 1
}];
// timing
let timing = {
duration: 2000,
iterations: Infinity
}
content.append(div)
div.animate(
keyframes,
timing
);
//elements += html;
body {
background: #808080;
}
.base {
width: 180px;
height: 90px;
background: black;
}
.sample {
animation: play 2s steps(10) infinite;
}
#keyframes play {
0% {
background-color: green;
opacity: 0;
}
100% {
background-color: blue;
opacity: 1;
}
}
<div class='base sample'></div>
<div id="content"></div>
Your exact problem is that you are applying the animation before appending the div, and passing the keyframes argument as a list of lists instead of a list of objects (as you defined it):
let content = document.getElementById("content");
html = `<div class="base"></div>`;
let doc = new DOMParser().parseFromString(html, 'text/html');
let div = doc.body.firstChild;
content.append(div)
// https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API/Using_the_Web_Animations_API
// keyframes
var keyframes = [{
backgroundColor: 'green',
opacity: 0
}, {
backgroundColor: 'blue',
opacity: 1
}];
// timing
let timing = {
duration: 200,
iterations: Infinity
}
div.animate(
keyframes,
timing
);

Implementing transition effects in React JS when state changes

I have an image on a React page. When the state is updated to a new image I want to perform the following transition effect:
The original image should zoom in and fade out
The new image should also zoom in and fade in
The effect should look similar to passing through a wall to a new scene.
How am I able to do this in React?
As #pgsandstrom mentioned, React Transition Group is the way to go. Unfortunately, it's not very developer friendly (pretty steep learning curve).
Here's a working example: https://codesandbox.io/s/6lmv669kz
✔ Original image zooms in while fading out
✔ New image zooms in while fading in
TransitionExample.js
import random from "lodash/random";
import React, { Component } from "react";
import { CSSTransition, TransitionGroup } from "react-transition-group";
import uuid from "uuid/v1";
const arr = [
{
id: uuid(),
url: `https://loremflickr.com/600/100?lock=${random(0, 999)}`
},
{
id: uuid(),
url: `https://loremflickr.com/600/100?lock=${random(0, 999)}`
},
{
id: uuid(),
url: `https://loremflickr.com/600/100?lock=${random(0, 999)}`
}
];
export default class TransitionExample extends Component {
state = {
index: 0,
selected: arr[0]
};
nextImage = () =>
this.setState(prevState => {
const newIndex = prevState.index < arr.length - 1 ? prevState.index + 1 : 0;
return {
index: newIndex,
selected: arr[newIndex]
};
});
render = () => (
<div className="app">
<div style={{ marginBottom: 30, height: 100 }}>
<TransitionGroup>
<CSSTransition
key={this.state.selected.id}
timeout={1000}
classNames="messageout"
>
<div style={{ marginTop: 20 }}>
<img className="centered-image" src={this.state.selected.url} />
</div>
</CSSTransition>
</TransitionGroup>
</div>
<div style={{ textAlign: "center" }}>
<button
className="uk-button uk-button-primary"
onClick={this.nextImage}
>
Next Image
</button>
</div>
</div>
);
}
styles.css
.app {
margin: 0 auto;
overflow: hidden;
width: 700px;
height: 800px;
}
.centered-image {
display: block;
margin: 0 auto;
}
/* starting ENTER animation */
.messageout-enter {
position: absolute;
top: 0;
left: calc(13% + 5px);
right: calc(13% + 5px);
opacity: 0.01;
transform: translateY(0%) scale(0.01);
}
/* ending ENTER animation */
.messageout-enter-active {
opacity: 1;
transform: translateY(0%) scale(1);
transition: all 1000ms ease-in-out;
}
/* starting EXIT animation */
.messageout-exit {
opacity: 1;
transform: scale(1.01);
}
/* ending EXIT animation */
.messageout-exit-active {
opacity: 0;
transform: scale(4);
transition: all 1000ms ease-in-out;
}
It sounds like you are looking for React Transition Group. It is the "official" way of solving these issues. Specifically I think this is what you should use. It can be a bit tricky to get a hang of, but it is really nice and powerful once you understand it.
This worked for me (link):
index.js:
import React from "react";
import { render } from "react-dom";
import "./styles.scss";
const src1 =
"https://www.nba.com/dam/assets/121028030322-james-harden-traded-102712-home-t1.jpg";
const src2 = "https://www.nba.com/rockets/sites/rockets/files/wcwebsite.jpg";
var state = {
toggle: true
};
class App extends React.Component {
render() {
const cn1 = "imgFrame " + (state.toggle ? "toggleOut" : "toggleIn");
const cn2 = "imgFrame " + (state.toggle ? "toggleIn" : "toggleOut");
return (
<div>
<img className={cn1} src={src1} alt={"img1"} />
<img className={cn2} src={src2} alt={"img2"} />
<button
onClick={() => {
state.toggle = !state.toggle;
this.forceUpdate();
}}
>
click me to toggle
</button>
<h1>Hello</h1>
</div>
);
}
}
render(<App />, document.getElementById("app"));
style.scss:
html,
body {
background-color: papayawhip;
font-family: sans-serif;
h1 {
color: tomato;
}
}
#keyframes fadeout {
0% {
opacity: 1;
transform: scale(1);
}
100% {
opacity: 0;
transform: scale(0.9);
}
}
#keyframes fadein {
0% {
opacity: 0;
transform: scale(1.1);
}
100% {
opacity: 1;
transform: scale(1);
}
}
.toggleOut {
animation: fadeout 500ms;
opacity: 0;
}
.toggleIn {
animation: fadein 500ms;
opacity: 1;
}
.imgFrame {
position: absolute;
top: 10px;
left: 10px;
width: 200px;
height: 200px;
}
button {
position: absolute;
top: 220px;
}
Wrap with a simple <Animate on={value} /> component that triggers an animation when value changes and is not undefined.
function Animate({ children, on }) {
return (on === undefined)
? <div>{children}</div>
: <div className="fade-in" key={on}>{children}</div>
}
import { useEffect, useState } from 'react'
function TestAnimate() {
const [value, setValue] = useState() // undefined
// update value every second
useEffect(() => {
setInterval(() => setValue(new Date().toLocaleString()), 1_000)
}, [])
return (
<Animate on={value}>
Value: {value}
</Animate>
)
}
#keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.fade-in {
animation: fadeIn 500ms ease-in-out;
}

How I can animate this slideshow(by changing its src)?

Okay okay, so before marking this post as repeated. Let me explain to you:
I made a slideshow in javascript(Vue) and it works by changing its src in an object every time I press a button(next)
It works and all but the problem is that it doesn't get animated no matter what I do, I made a transition on them, set timeout function on it...etc and nothing even the smallest worked.
I could have made another idea which works by the position absolute but I don't want to do that because it will take a loot of time and it will be extremely buggy as position absolute ruins it. So any help on this please?
<template>
<main>
<div id="slideshow">
<figure id="pics">
<img id="slidepic" v-bind:src="pictures[count].src">
<figcaption>{{pictures[count].alt}}</figcaption>
</figure>
</div>
<p>{{count+1}}/{{pictures.length}}</p>
<div id="controls">
<div #click="move(-1)">Previous</div>
<div #click="move(1)">Next</div>
</div>
</main>
Javascript:
methods: {
move: function(num) {
let slideimg = document.querySelector("#slidepic");
slideimg.classList.add("fadeOut");
this.count += num;
if (this.count < 0) {
this.count = this.pictures.length - 1;
} else if (this.count >= this.pictures.length) {
this.count = 0;
}
setTimeout(function() {
slideimg.src = this.pictures[1].src;
}, 1000);
}
}
CSS:
#pics {
opacity: 0.5s;
transition: 0.5s;
}
#pics.fadeOut {
opacity: 1;
}
I didn't include the object(that is in data object, something in Vue) because it would be useless in this situation.
First off all it's transition: <property-name> 0.5s linear; and not transition: 0.5s;. See the transition documentation.
There is no animation for changing the src of an image (see list of animatable css properties).
To do something like this, you can stack all your images into one element and then use css animations and the transform property to create a carousel
var next = document.getElementById('next');
var prev = document.getElementById('prev');
var slideshow = document.getElementById('slideshow');
next.onclick = function() {
var lastChild = slideshow.children[slideshow.children.length - 1];
var firstChild = slideshow.children[0];
var activeEle = document.querySelector('.item.active');
var nextEle = document.querySelector('.item.next');
var prevEle = document.querySelector('.item.prev');
activeEle.classList.remove('active');
activeEle.classList.add('prev');
nextEle.classList.add('active');
nextEle.classList.remove('next');
prevEle.classList.remove('prev');
if (nextEle.nextElementSibling) {
nextEle.nextElementSibling.classList.add('next');
} else {
firstChild.classList.add('next');
}
};
prev.onclick = function() {
var lastChild = slideshow.children[slideshow.children.length - 1];
var activeEle = document.querySelector('.item.active');
var nextEle = document.querySelector('.item.next');
var prevEle = document.querySelector('.item.prev');
// Move the .active class to the previous element
activeEle.classList.remove('active');
activeEle.classList.add('next');
prevEle.classList.add('active');
prevEle.classList.remove('prev');
nextEle.classList.remove('next');
if (prevEle.nextElementSibling) {
prevEle.nextElementSibling.classList.add('prev');
} else {
lastChild.classList.add('prev');
}
};
#slideshow {
width: 100px;
height: 100px;
overflow: hidden;
position: relative;
}
.item {
width: 100%;
height: 100%;
color: white;
background-color: blue;
position: absolute;
/*display: none;*/
top: 0;
left: 0;
z-index: -100;
transition: translateX(-100%);
transition: transform .5s ease-in-out;
opacity: 0;
}
.active {
opacity: 1;
display: block;
z-index: 1;
transform: translateX(0);
}
.next {
transform: translateX(200%);
z-index: 1;
}
.prev {
transform: translateX(-100%);
opacity: 1;
z-index: 1;
}
<div id="slideshow">
<div class="item active">1</div>
<div class="item next">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item prev">7</div>
</div>
<button type="button" id="prev">Prev</button><button type="button" id="next">Next</button>
As you mention you want to build a slideshow on Vue JS, and because jQuery on top of Vue is not recommended, I suggest that you try Vueper Slides, available on NPM. Unless it is for a learning purpose.
I have created two solutions.
First of all. You've a typo.
#pics {
opacity: 0.5s; // <--- remove "s"
transition: 0.5s; // <--- and forgot the property-name (all, opacity ...)
}
#pics.fadeOut {
opacity: 1;
}
I commented all lines I've changed.
Solution
<template>
<main>
<div id="slideshow">
<!--
I recommend to you ref inestad of querySelector.
https://vuejs.org/v2/api/#ref
I've used the v-bind shorthand.
-->
<figure id="pics1" ref="pics1">
<img id="slidepic" :src="pictures[count].src">
<figcaption>{{pictures[count].alt}}</figcaption>
</figure>
<!--
VueJS build-in transition element.
You have to add a key attribute to detect that the content has changed.
I recommend to use this instead of your solution.
It's easier to implement, no class add/remove struggle, its a part of vue, you can add hooks etc.
https://vuejs.org/v2/guide/transitions.html
-->
<transition tag="figure" name="fade" ref="pics2">
<figure id="pics2" :key="`figure-${count}`">
<img :src="pictures[count].src">
<figcaption>{{pictures[count].alt}}</figcaption>
</figure>
</transition>
</div>
<p>{{count+1}}/{{pictures.length}}</p>
<div id="controls">
<div #click="move(-1)">Previous</div>
<div #click="move(1)">Next</div>
</div>
</main>
</template>
<script>
export default {
name: 'teams',
data() {
return {
count: 0,
pictures: [
{
src: 'https://picsum.photos/200/300',
alt: 'test'
},
{
src: 'https://picsum.photos/200/400',
alt: 'test2'
}
]
};
},
methods: {
// instead of move: function(num) {} you can also write move() {}
move(num) {
this.count += num;
if (this.count < 0) {
this.count = this.pictures.length - 1;
} else if (this.count >= this.pictures.length) {
this.count = 0;
}
}
},
// Watch "count" changes and add or remove classes
// you can also add this to your "move" method
watch: {
count() {
// access the reference
const element = this.$refs.pics1;
element.classList.add('fadeOut');
element.classList.remove('fadeIn');
setTimeout(() => {
element.classList.remove('fadeOut');
element.classList.add('fadeIn');
}, 500); // same duration as css transition
}
}
};
</script>
<style scoped lang="scss">
#pics1 {
opacity: 1;
transition: opacity 0.5s;
}
#pics1.fadeIn {
opacity: 1;
}
#pics1.fadeOut {
opacity: 0;
}
// All classes for <transition>
// There are all automatically used by vue
.fade-enter-active {
transition: opacity 0.5s;
}
.fade-leave {
display: none;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>

Categories