admin管理员组

文章数量:1221774

such a situation:

1 background layer, 4 pictures that should replace each other in this background layer – in a time interval (4 sec) with a soft transition (1,5 sec), and 4 links/buttons which should trigger the necessary picture background on mouseover. The changed background should stay until the mouse leaves the button.

The problem: if I bring the mouse over a link while a transition (no matter how it's triggered), the called background picture is set straight away and by a hard transition. How to prevent it?

I'm gonna put here shortened code where only the relevant things are:

HTML:

<div class="bg-image" id="bg-image-de-de"></div>
    <a class="experience-now" data-lang="DE" id="sphere1" onmouseover="imageOne();" onmouseleave="backToChangeBG();">Image 01</a>
    <a class="experience-now" data-lang="DE" id="sphere2" onmouseover="imageTwo();" onmouseleave="backToChangeBG();">Image 02</a>
    <a class="experience-now" data-lang="DE" id="sphere3" onmouseover="imageThree();" onmouseleave="backToChangeBG();">Image 03</a>
    <a class="experience-now" data-lang="DE" id="sphere4" onmouseover="imageFour();" onmouseleave="backToChangeBG();">Image 04</a>

CSS:

.bg-image {
    background-image: url(../_img/Picture1.jpg);
    transition-duration: 1500ms !important;
    transition-property: background-image;
    width: 100%;
    height: calc(100% - 50px);
    background-position: top center;
    background-repeat: repeat-y;
    background-size: cover;
    background-blend-mode: normal;
    background-color: #e6e6eb;
    position: fixed;
} 

JS:

var interval = 4; 
var bilderurl = new Array("_assets/_img/Picture1.jpg", "_assets/_img/Picture2.jpg", "_assets/_img/Picture3.jpg", "_assets/_img/Picture4.jpg");
var bilder = new Array();
let element = document.getElementById("bg-image-de-de");
for (i = 0; i < bilderurl.length; i++)
{
     bilder[i] = new Image;
     bilder[i].src = bilderurl[i];
}
i = 0;

function changebg()
{
     i++;
     if (i == bilderurl.length) i = 0; 
     element.style.backgroundImage = "url(" + bilderurl[i] + ")";
}
window.setInterval("changebg()", 1000 * interval);


function imageOne() {
    element.style.backgroundImage = "url(_assets/_img/Picture1.jpg)";
    element = null; 
};

function imageTwo() {
    element.style.backgroundImage = "url(_assets/_img/Picture2.jpg)";
    element = null; 
};

function imageThree() {
    element.style.backgroundImage = "url(_assets/_img/Picture3.jpg)";
    element = null;
};

function imageFour() {
    element.style.backgroundImage = "url(_assets/_img/Picture4.jpg)";
    element = null;
};

function backToChangeBG() {
    element = document.getElementById("bg-image-de-de");
};

Please help me, it really should be possible. Thankx in previous. Yours, Peter

such a situation:

1 background layer, 4 pictures that should replace each other in this background layer – in a time interval (4 sec) with a soft transition (1,5 sec), and 4 links/buttons which should trigger the necessary picture background on mouseover. The changed background should stay until the mouse leaves the button.

The problem: if I bring the mouse over a link while a transition (no matter how it's triggered), the called background picture is set straight away and by a hard transition. How to prevent it?

I'm gonna put here shortened code where only the relevant things are:

HTML:

<div class="bg-image" id="bg-image-de-de"></div>
    <a class="experience-now" data-lang="DE" id="sphere1" onmouseover="imageOne();" onmouseleave="backToChangeBG();">Image 01</a>
    <a class="experience-now" data-lang="DE" id="sphere2" onmouseover="imageTwo();" onmouseleave="backToChangeBG();">Image 02</a>
    <a class="experience-now" data-lang="DE" id="sphere3" onmouseover="imageThree();" onmouseleave="backToChangeBG();">Image 03</a>
    <a class="experience-now" data-lang="DE" id="sphere4" onmouseover="imageFour();" onmouseleave="backToChangeBG();">Image 04</a>

CSS:

.bg-image {
    background-image: url(../_img/Picture1.jpg);
    transition-duration: 1500ms !important;
    transition-property: background-image;
    width: 100%;
    height: calc(100% - 50px);
    background-position: top center;
    background-repeat: repeat-y;
    background-size: cover;
    background-blend-mode: normal;
    background-color: #e6e6eb;
    position: fixed;
} 

JS:

var interval = 4; 
var bilderurl = new Array("_assets/_img/Picture1.jpg", "_assets/_img/Picture2.jpg", "_assets/_img/Picture3.jpg", "_assets/_img/Picture4.jpg");
var bilder = new Array();
let element = document.getElementById("bg-image-de-de");
for (i = 0; i < bilderurl.length; i++)
{
     bilder[i] = new Image;
     bilder[i].src = bilderurl[i];
}
i = 0;

function changebg()
{
     i++;
     if (i == bilderurl.length) i = 0; 
     element.style.backgroundImage = "url(" + bilderurl[i] + ")";
}
window.setInterval("changebg()", 1000 * interval);


function imageOne() {
    element.style.backgroundImage = "url(_assets/_img/Picture1.jpg)";
    element = null; 
};

function imageTwo() {
    element.style.backgroundImage = "url(_assets/_img/Picture2.jpg)";
    element = null; 
};

function imageThree() {
    element.style.backgroundImage = "url(_assets/_img/Picture3.jpg)";
    element = null;
};

function imageFour() {
    element.style.backgroundImage = "url(_assets/_img/Picture4.jpg)";
    element = null;
};

function backToChangeBG() {
    element = document.getElementById("bg-image-de-de");
};

Please help me, it really should be possible. Thankx in previous. Yours, Peter

Share Improve this question edited Feb 7 at 15:59 Peter asked Feb 7 at 15:55 PeterPeter 112 bronze badges
Add a comment  | 

2 Answers 2

Reset to default 0

The transitions aren't perfect so you'll probably need to fine tune it. background-image is janky, it's easier to use an <img>. Details are commented in the example.

// Define global variables
let tick = null;
let idx = 0;
let int = 4000;

// Array of image urls
const pix = ["https://i.ibb.co/bBGX3Sq/static.gif", "https://i.ibb.co/c1PtcM7/matrix1.gif", "https://i.ibb.co/FHRS8Gx/stars.gif", "https://i.ibb.co/wc356r0/atat.gif"];

// Reference <html>
const root = document.documentElement;
// Reference <img>
const img = document.images[0];
// Reference <section>
const sec = document.querySelector("section");
// Reference <nav>
const nav = document.querySelector("nav");
// Array of <a>
const lnx = Array.from(document.links);

// Initial fadeOut and auto image change
setTimeout(fadeOut, 2500);
tick = setInterval(next, int);

/**
 * This function moves the images forward.
 */
function next() {
  fadeIn();
  setTimeout(fadeOut, 2000);
  idx++;
  if (idx >= pix.length) {
    idx = 0;
  }
  setImg(idx);
}

/**
 * This function sets the src of <img>
 */
function setImg() {
  img.src = pix[idx];
}

/**
 * This function fades <section> in.
 */
function fadeIn() {
  sec.classList.remove("fade");
}

/**
 * This function fades <section> out.
 */
function fadeOut() {
  sec.classList.add("fade");
}

/**
 * This function changes transition duration of
 * fading animation from 3.5s to 0.5s.
 */
function blink() {
  root.style.setProperty("--time", "0.5s");
}

/**
 * This function changes transition duration of
 * fading animation from 0.5s to 3.5s.
 */
function unblink() {
  root.style.setProperty("--time", "3.5s");
}

/**
 * "pointerenter" event handler disables the setInterval()
 * function when the user moves the pointer into
 * <nav>.
 * @param {object} e - Event object
 */
nav.onpointerenter = function(e) {
  clearInterval(tick);
  setTimeout(fadeIn, 500);
};

/**
 * "pointerleave" event handler enables setInterval()
 * function when the user moves the pointer out
 * of <nav>.
 * @param {object} e - Event object
 */ 
nav.onpointerleave = function(e) {
  setTimeout(fadeIn, 100);
  tick = setInterval(next, int);
  setTimeout(fadeOut, 100);
  unblink();
};

/**
 * Each <a> is registered to the "pointerenter"
 * event. Event handler hoverLink() is called
 * when the user moves the pointer into an <a>.
 */
lnx.forEach(l => {
  l.onpointerenter = hoverLink;
});

/**
 * "pointerenter" event handler for each <a>.
 * When the user moves the pointer into an <a>
 * The corresponding image appears.
 * @param {object} e - Event object
 */  
function hoverLink(e) {
  blink();
  idx = lnx.indexOf(this);
  setTimeout(fadeOut, 0);
  setTimeout(setImg, 500);
  setTimeout(fadeIn, 750);
}
:root {
  /* This custom property is the transition
   * durtion for the fading animation.
   */
  --time: 3.5s;
  font: 2ch/1.5 "Segoe UI"
}

main {
  display: flex;
  flex-direction: column;
  align-items: center;
  width: 100%;
  margin: 0.5rem auto;
  background: #000;
}

section {
  width: 100%;
  aspect-ratio: 16 / 9;
  background: #000;
  opacity: 1;
  transition: opacity var(--time);
}

nav {
  padding: 5px 10px;
  border: 1.5px grey solid;
}

img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: contain
}

a {
  display: inline-block;
}

a+a {
  margin-left: 0.5rem;
}

/**
 * This class is the trigger for all fading
 * animations.
 */
.fade {
  opacity: 0;
}
<main>
  <section>
    <img src="https://i.ibb.co/bBGX3Sq/static.gif">
  </section>
  <nav>
    <a href="#">Image 01</a>
    <a href="#">Image 02</a>
    <a href="#">Image 03</a>
    <a href="#">Image 04</a>
  </nav>
</main>

The following snippet attempts to capture the essence of your problem. It transitions between two background colors depending on which radio button is pressed.

But the color is not immediately applied in the event handler. Instead, a color variable is updated with the desired color, and this is applied only

  • if there is no transition running
  • or when the transition has ended.

If you switch back and forth between the radio buttons while a transition is running, only the last color will be applied.

let color;

window.addEventListener("transitionstart", function() {
  d.className = 'transition';
});

window.addEventListener("transitionend", function() {
  d.className = '';
  d.style.backgroundColor = color;
});

function setColor(c) {
  color = c;
  if (d.className === '') d.style.backgroundColor = color;
}
div {
  height: 8em;
  border: solid 3px transparent;
  transition: background-color 1500ms;
}

div.transition {
  border-color: black;
}
<div id="d"></div>
<label><input type="radio" name="color" onclick="setColor('red')">Red</label><br>
<label><input type="radio" name="color" onclick="setColor('white')">White</label>

本文标签: javascriptHow to prevent CSS transitions from interrupting each other by any JS triggersStack Overflow