有没有办法确保所有元素在再次操作之前都已重置到原始位置?

时间:2019-04-25 15:51:38

标签: javascript html css dom

首先,我知道这是一个大问题。我正在寻找更多的想法和指导,而不是一个完整的解决方案。我正在建立一个屏幕上有十张卡片的网站。每张卡与前一张卡稍有重叠。当鼠标放在卡上时,其他卡应移开,突出显示的卡应展开。有没有一种方法可以使光标移出当前卡之后且开始任何其他操作之前,所有卡都返回其原始位置?我已经将所有代码都包含在当前的.html文件中。

我尝试在HTML文档上使用onMouseOver和onMouseOut来根据调用的函数来回移动元素。

我尝试将GSAP与时间轴类混淆,但我不知道如何制作可以播放,停止,倒转等的动画。

我目前已设置它来添加和删除具有超时的事件侦听器,以限制函数的调用速度。

var cards = document.getElementsByClassName('card');
var currentCard;
var currentIndex;
var leftSpread = 150;
var rightSpread = 200;
var initialOffset = 100;

(function initialLoad() {
  for (var i = 0; i < cards.length; i++) {
    cards[i].style.zIndex = i;

    cards[i].addEventListener("mouseenter", this);

    if (i > 0) {
      cards[i].style.left = cards[i - 1].offsetLeft + initialOffset + 'px';
    }
  }
})();

function handleEvent(evt) {
  switch (evt.type) {
    case "mouseenter":
      this.cardMouseOver(evt);
      break;
    case "mouseout":
      this.cardMouseOut(evt);
      break;
    default:
      return;
  }
}

function cardMouseOver(event) {
  currentIndex = event.target.style.zIndex;
  event.target.style.zIndex = 10;

  for (var i = 0; i < cards.length; i++) {
    if (event.target == cards[i]) {
      currentCard = i;
    } else {
      cards[i].removeEventListener("mouseenter", this);
    }
  }

  setTimeout(function() {
    cards[currentCard].addEventListener("mouseout", this);
  }, 50);

  for (var i = 0; i < cards.length; i++) {
    if (i < currentCard) {
      cards[i].style.left = cards[i].offsetLeft - leftSpread + 'px';
    } else if (i > currentCard) {
      cards[i].style.left = cards[i].offsetLeft + rightSpread + 'px';
    }
  }

  cards[currentCard].removeEventListener("mouseenter", this);
}

function cardMouseOut(event) {
  cards[currentCard].style.zIndex = currentIndex;

  setTimeout(function() {
    for (var i = 0; i < cards.length; i++) {
      cards[i].addEventListener("mouseenter", this);
    }
  }, 100);

  for (var i = 0; i < cards.length; i++) {
    if (i === currentCard) {
      cards[i].removeEventListener("mouseout", this);
    }
  }

  for (var i = 0; i < cards.length; i++) {
    if (i < currentCard) {
      cards[i].style.left = cards[i].offsetLeft + leftSpread + 'px';
    } else if (i > currentCard) {
      cards[i].style.left = cards[i].offsetLeft - rightSpread + 'px';
    }
  }
}
body {
  background-color: #242424;
  padding: 0;
  margin: 0;
}

.cards-container {
  background: #fff;
  margin: 20px auto;
  position: absolute;
  left: 21%;
  top: 375px;
}

.card {
  position: absolute;
  background: rgb(255, 255, 255);
  border: 1px solid black;
  height: 250px;
  transition: 0.2s;
  width: 200px;
  box-shadow: -1px 0px 1px 1px rgba(0, 0, 0, 0.747);
}

.card:hover {
  transition: all 0.2s ease;
  width: 250px;
  height: 350px;
  top: -75px;
}
<body>
  <header>
    <div class="cards-container">
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
      <div class="card"></div>
    </div>
  </header>
</body>

<script type="text/javascript" src="http://code.jquery.com/jquery-3.4.0.min.js"></script>

我希望一切都根据当前突出显示的卡片(平滑过渡)来定位,并在突出显示任何内容时重置为原始位置。

2 个答案:

答案 0 :(得分:0)

您可以通过以下两种方式完成此操作

  1. 您可能拥有一个布尔标志,该布尔标志会在元素移入/移出位置时切换。当元素返回其起始位置时,可以从那里重新进行切换。
let DOMHasChanged = false

function handleEvent(evt) {
  DOMHasChanged = true
  switch (evt.type) {
    case "mouseenter":
      this.cardMouseOver(evt);
      break;
    case "mouseout":
      this.cardMouseOut(evt);
      break;
    default:
      return;
  }
}

// Some function to set DOMHasChanged back to false on element reset
  1. 您可以通过类(.inUse,.active,.hovered等)处理动画和CSS更改,然后运行循环以检查是否有任何元素具有“活动”类
const pageChanged = () => {
  if(Array.from(document.querySelectorAll(".inUse")).length > 0) {
    return false
  } else {
    return true
  }
}

编辑:此外,关于动画,当您知道如何制作时,它们相当简单!我建议在@keyframes上查看W3Schools的文章

https://www.w3schools.com/cssref/css3_pr_animation-keyframes.asp

您还可以将动画方向设置为前进,后退等。功能非常强大!

答案 1 :(得分:0)

通过继续挖掘,我找到了答案。这比我想象的要简单得多。由于在鼠标悬停在卡片上时希望获得平滑的动画效果,因此我使用了CSS过渡和变换属性。

通过创建以下CSS类:

.card {
    position: absolute;
    background: rgb(255, 255, 255);
    height: 275px;
    width: 200px;
    box-shadow: -1px 0px 3px 1px rgba(0, 0, 0, 0.747);
    transition: all .4s ease;
}

.card.left {
    transform: translateX(-175px);
}

.card.right {
    transform: translateX(175px);
}

我能够添加和删除“ mouseenter”和“ mouseover”事件侦听器,以获得我想要的效果。

function handleEvent(evt) {
    switch(evt.type) {
        case "mouseenter":
            this.cardMouseOver(evt);
            break;
        case "mouseout":
            this.cardMouseOut(evt);
            break;
        default:
            return;
    }
}

function cardMouseOver(event) {
    for (var i = 0; i < cards.length; i++) {
        if (event.target == cards[i]) {
            currentCard = i;
        }
    }

    for (var i = 0; i < cards.length; i++) {
        if (i < currentCard) {
            if (!cards[i].classList.contains('left')) {
                cards[i].classList.add('left');
            }
        } else if (i > currentCard) {
            if (!cards[i].classList.contains('right')) {
                cards[i].classList.add('right');
            }
        }
    }
}

function cardMouseOut(event) {
    for (var i = 0; i < cards.length; i++) {
        if (i < currentCard) {
            if (cards[i].classList.contains('right')) {
                cards[i].classList.remove('right');
            } else if (cards[i].classList.contains('left')) {
                cards[i].classList.remove('left');
            }
        } else if (i > currentCard) {
            if (cards[i].classList.contains('left')) {
                cards[i].classList.remove('left');
            } else if (cards[i].classList.contains('right')) {
                cards[i].classList.remove('right');
            }
        } else {
            if (cards[i].classList.contains('left')) {
                cards[i].classList.remove('left');
            } else if (cards[i].classList.contains('right')) {
                cards[i].classList.remove('right');
            }
        }
    }
}

卡片是“卡片”元素的数组。