弹跳球动画手风琴

bouncing balls animation Accordion

我正在尝试制作 this CodePen

中显示的动画

皇冠上我有5个球。在另一边,手风琴中有 5 个球。每当我打开手风琴中的特定部分时,连接到后者的球就会移动到表冠中的相同位置。感谢您的帮助

$(document).ready(function() {
  $('.acc__title').click(function(j) {
    let elem = $(this).find("i");
    let dot = '#' + $(this).data("dot");

    elem = $(elem[0]);
    dot = $(dot);

    let thisClass = $(this);
    let dropDown = $(this).closest('.acc__card').find('.acc__panel');
    $(this).closest('.acc').find('.acc__panel').not(dropDown).slideUp();

    if ($(this).hasClass('active')) {
      let dist_top = dot.offset().top - elem.offset().top;
      let dist_left = dot.offset().left - elem.offset().left;
      elem.animate({
        "left": dist_left + "px",
        "top": dist_top + "px"
      }, 500, "linear");
      $(this).removeClass('active');

    } else {
      $(this).closest('.acc').find('.acc__title.active').removeClass('active');

      $('.acc__title i').animate({
        "left": "0"
      }, 500, "linear");
      let dist_top = dot.offset().top - elem.offset().top;
      let dist_left = dot.offset().left - elem.offset().left;
      elem.animate({
        "left": dist_left + "px",
        "top": dist_top + "px"
      }, 500, "linear");
      $(this).addClass('active');
    }

    dropDown.stop(false, true).slideToggle();
    j.preventDefault();
  });
});

function animCollapse(element) {
  let elem = $(element).find("i");
  let dot = '#' + $(element).data("dot");

  elem = $(elem[0]);
  dot = $(dot);
  //console.log(dot);

  let dist_top = dot.offset().top - elem.offset().top;
  let dist_left = dot.offset().left - elem.offset().left;
  // console.log("Y : " + dist_top, " X : " + dist_left);
  gsap.to(elem, {
    x: dist_left,
    y: dist_top,
    opacity: 1,
    duration: 1
  })
}
#values-and-missions {
  position: relative;
  background-color: #DEE4EA;
  background-image: url(../images/bg-dots.png);
  background-repeat: no-repeat;
  background-position: 100% 50%;
  background-size: 50%;
  padding: 40px 0;
}

#values-and-missions .crown {
  position: absolute;
  z-index: 1;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
}

#values-and-missions #accordion .card {
  border: none;
  border-top: 1px solid #D0D9E2;
  border-radius: 0;
  box-shadow: none;
  margin-bottom: 0;
  background-color: rgba(255, 255, 255, 0.1);
}

#values-and-missions #accordion .card:last-child {
  border-bottom: 1px solid #D0D9E2;
}

#values-and-missions #accordion .card-header {
  padding: 0;
  border: none;
  border-radius: 0;
  background-color: #e4e9ee;
}

#values-and-missions #accordion .card-title a {
  display: block;
  padding: 23px 15px;
  /* padding-left: 30px; */
  font-size: 18px;
  font-weight: 400;
  color: #0F89CF;
  /* box-shadow: 0 0 10px rgba(0,0,0,.05); */
  position: relative;
  transition: all 0.5s ease 0s;
}

#values-and-missions #accordion .card-title a.collapsed {
  box-shadow: none;
  background: #dee4ea;
}

#values-and-missions #accordion .card-title a i {
  font-size: 9.71px;
  vertical-align: middle;
  padding-right: 10px;
}

#values-and-missions #accordion .card-title a:after,
#values-and-missions #accordion .card-title a.collapsed:after {
  content: "\f078";
  font-family: "Font Awesome 5 Free";
  width: 25px;
  height: 25px;
  line-height: 28px;
  font-size: 15px;
  font-weight: 900;
  color: #0F89CF;
  text-align: center;
  position: absolute;
  top: 0;
  bottom: 0;
  margin: auto;
  right: 15px;
  transform: rotate(180deg);
  transition: all 0.3s ease 0s;
}

#values-and-missions #accordion .card-title a.collapsed:after {
  color: #0F89CF;
  transform: rotate(0);
}

#values-and-missions #accordion .card-body {
  padding: 0px 15px;
  border: none;
  font-size: 15px;
  color: #615f5f;
  line-height: 27px;
}

#values-and-missions #accordion .collapse.show {
  background-color: rgba(255, 255, 255, 0.1);
}

svg:not(:root) {
  overflow: visible;
}


/* Accordion
================================================== */

.acc {
  margin: 0 auto;
  max-width: 800px;
}

.acc__card {
  margin: 0;
  position: relative;
  border-bottom: 1px solid;
}

.acc__title {
  background: #fff;
  color: #212121;
  cursor: pointer;
  display: block;
  padding: 1em 1.5em;
  position: relative;
  text-align: left;
}

.acc__title span {
  position: relative;
}

.acc__title span i {
  font-size: 9.71px;
  vertical-align: middle;
  padding-right: 10px;
  position: absolute;
  left: 0;
}

.acc__title::after {
  width: 8px;
  height: 8px;
  border-right: 1px solid #4a6e78;
  border-bottom: 1px solid #4a6e78;
  position: absolute;
  right: 10px;
  content: " ";
  top: 17px;
  -webkit-transform: rotate(-45deg);
  transform: rotate(-45deg);
  transition: all 0.2s ease-in-out;
}

.acc__title.active::after {
  -webkit-transform: rotate(45deg);
  transform: rotate(45deg);
  transition: all 0.2s ease-in-out;
}

.acc__panel {
  background: #fff;
  color: #212121;
  display: none;
  margin: 0;
  padding: 2em;
  text-align: left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section id="values-and-missions" class="section">
  <!-- <img src="images/damandis.svg" class="crown" alt=""> -->
  <div class="crown">
    <svg xmlns="http://www.w3.org/2000/svg" width="52.701" height="98.174" viewBox="0 0 52.701 98.174">
        <g id="damandis" transform="translate(369.132 -50.394) rotate(90)">
          <path id="crown"
            d="M111.133,357.154a116.647,116.647,0,0,1-8.392-19,116.684,116.684,0,0,1-8.392,19c-5.944,10.257-16.143,16.143-33.51-3.788l11.947,22.262H132.7l11.946-22.262C127.276,373.3,117.077,367.411,111.133,357.154Z"
            transform="translate(-3.123 -6.495)" fill="#0f89cf" />
          <circle id="dot_05" data-name="dot 05" cx="4.855" cy="4.855" r="4.855" transform="translate(138.858 335.942)"
            fill="#0f89cf" />
          <circle id="dot_04" data-name="dot 04" cx="4.855" cy="4.855" r="4.855" transform="translate(115.432 335.942)"
            fill="#0f89cf" />
          <circle id="dot_03" data-name="dot 03" cx="4.855" cy="4.855" r="4.855"
            transform="translate(92.751 323.297) rotate(-45)" fill="#0f89cf" />
          <circle id="dot_02" data-name="dot 02" cx="4.855" cy="4.855" r="4.855" transform="translate(73.82 335.942)"
            fill="#0f89cf" />
          <circle id="dot_01" data-name="dot 01" cx="4.855" cy="4.855" r="4.855" transform="translate(50.394 335.941)"
            fill="#0f89cf" />
        </g>
      </svg>
  </div>
  <div class="container">
    <div class="row">
      <div class="col">
        <div class="acc">
          <div class="acc__card">
            <div class="acc__title" data-dot="dot_01"><span><i class="fas fa-circle"></i> Accordion Title #1</span></div>
            <div class="acc__panel">
              I am the content found under accordion #1. You can't see me while "active" is not present.
            </div>
          </div>
          <div class="acc__card">
            <div class="acc__title" data-dot="dot_02"><span><i class="fas fa-circle"></i> Accordion Title #2</span></div>
            <div class="acc__panel">
              I am the content found under accordion #2. You can't see me while "active" is not present.
            </div>
          </div>
          <div class="acc__card">
            <div class="acc__title" data-dot="dot_03"><span><i class="fas fa-circle"></i> Accordion Title #3</span></div>
            <div class="acc__panel">
              I am the content found under accordion #3. You can't see me while "active" is not present.
            </div>
          </div>
          <div class="acc__card">
            <div class="acc__title" data-dot="dot_04"><span><i class="fas fa-circle"></i> Accordion Title #4</span></div>
            <div class="acc__panel">
              I am the content found under accordion #4. You can't see me while "active" is not present.
            </div>
          </div>
          <div class="acc__card">
            <div class="acc__title" data-dot="dot_05"><span><i class="fas fa-circle"></i> Accordion Title #5</span></div>
            <div class="acc__panel">
              I am the content found under accordion #5. You can't see me while "active" is not present.
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</section>

不要使用 jQuery 的 .animate()。它的性能不佳,并且没有 GSAP 的动画功能那么多的功能。与 .slideUp 相同 - 您可以将其替换为 GSAP 补间。如果您打算使用 GSAP 的动画功能,那么加载 GSAP 就没有意义了。

您需要做的步骤是:

  1. 将表冠的位置设置在其最终位置(即在部分打开之后)。
  2. 获取该点与其在皇冠上对应点的 x 和 y 距离。
  3. 原始位置到您正在设置动画的皇冠和圆点的最终位置设置动画。
  4. 当它关闭时,将点动画化回 0,0(您不必进行任何计算)。

最好使用 GSAP 的 xy 属性,因为它们使用不会导致回流的转换。

我让你在 this demo 开始了。我没有执行第 2 步和第 3 步,我会把它留给你弄清楚。提示:利用 GS​​AP 的 .set().from() 方法。