0

I have two buttons with bodymovin animations that I want to interact with each other so that if one of the buttons has the open state and the other button is clicked, the open button becomes closed and the animation runs again as if it were click again to simulate the closed state.

So for example if I click the #box it receives the open state (and the animation runs to open. Now if I click the #slider the #box should lose the open state & the animation runs back to closed.

The same situation will equally apply for the slider.

var animData1 = {
  container: document.getElementById("box"),
  renderer: "svg",
  loop: false,
  autoplay: false,
  path: "https://cdn.statically.io/gist/moofawsaw/b8abeafe008f8b9ef040199c60a15162/raw/296dde84544ed1b41d5acfa303cca21c3ceee70f/lottie_box.json"
};
var animData2 = {
  container: document.getElementById("slider"),
  renderer: "svg",
  loop: false,
  autoplay: false,
  path: "https://assets6.lottiefiles.com/private_files/lf30_ht7mmN.json"
};
var anim1;
var anim2;

anim1 = bodymovin.loadAnimation(animData1);
anim2 = bodymovin.loadAnimation(animData2);

$("#box").on("click", function() {
  anim1.setSpeed(5);
  //for Box
  if ($("#box").hasClass("active")) {
    anim1.playSegments([100, 0], true);
    $("#box").removeClass("active");
    $(this).find(".state").html("closed");
  } else {
    $(this).find(".state").html("open");
    anim1.playSegments([0, 100], true);
    $("#box").addClass("active");
  }
  //For other button
  if ($("#slider").hasClass("active")) {}
});
$("#slider").on("click", function() {
  anim2.setSpeed(16);
  //for Slider
  if ($("#slider").hasClass("active")) {
    anim2.playSegments([100, 0], true);
    $("#slider").removeClass("active");
    $(this).find(".state").html("closed");
  } else {
    $(this).find(".state").html("open");
    anim2.playSegments([0, 100], true);
    $("#slider").addClass("active");
  }
  //For other button
  if ($("#box").hasClass("active")) {}
});
#box,
#slider {
  display: flex;
  color: white;
  align-items: center;
  cursor: pointer;
  height: 46px;
  max-width: 270px;
  min-width: 270px;
  margin-top: 9px;
  margin-right: 0.5rem;
  margin-bottom: 6px;
  border-style: none;
  border-radius: 6px;
  background-color: #4aabf0;
  font-size: 16px;
}

#slider {
  background-color: #756fe4;
}

#box path,
#slider path {
  fill: white;
  stroke: white;
}

#slider path {
  stroke-width: 0;
}

#box svg {
  min-height: 32px;
  max-height: 32px;
}

#slider svg {
  max-height: 26px;
}

#box svg,
#slider svg {
  transition: 0.2s cubic-bezier(0.45, 0, 0.55, 1);
}

#box.active>svg {
  transform: scale(.3);
  transform-origin: center;
  transition: 0.2s cubic-bezier(0.45, 0, 0.55, 1);
}

.container {
  margin: 0px auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  align-content: center;
}

.state {
  width: 90px;
  margin-left: .9rem
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.6.8/lottie_svg.min.js" integrity="sha256-nrcbQ5LezWWswBYK9nZCrIG7075yl2ChXPCkT/1UCt8=" crossorigin="anonymous"></script>
<div class="container">
  <div id="box">
    <div class="state">closed</div>
  </div>
  <div id="slider">
    <div class="state">closed</div>
  </div>
</div>
Kyle Underhill
  • 89
  • 15
  • 43
  • My take on this: https://jsfiddle.net/khrismuc/sf71xzet/ (but it depends on how many buttons there are going to be in total) –  Jun 08 '20 at 17:57
  • @ChrisG Hi Chris, I think there is something up with the playSegments() part of the code. It doesn't look like the animations are going to half then back again: codepen.io/moofawsaw/pen/wvMaLjZ – Kyle Underhill Jun 10 '20 at 16:07

1 Answers1

1

You can do it like this:

var animData1 = {
  container: document.getElementById("box"),
  renderer: "svg",
  loop: false,
  autoplay: false,
  path: "https://cdn.statically.io/gist/moofawsaw/b8abeafe008f8b9ef040199c60a15162/raw/296dde84544ed1b41d5acfa303cca21c3ceee70f/lottie_box.json"
};
var animData2 = {
  container: document.getElementById("slider"),
  renderer: "svg",
  loop: false,
  autoplay: false,
  path: "https://assets6.lottiefiles.com/private_files/lf30_ht7mmN.json"
};
var anim1;
var anim2;

anim1 = bodymovin.loadAnimation(animData1);
anim2 = bodymovin.loadAnimation(animData2);

$("#box").on("click", function() {
  anim1.setSpeed(5);
  anim2.setSpeed(16);
  //for Box
  if ($("#box").hasClass("active")) {
    anim1.playSegments([100, 0], true);
    $("#box").removeClass("active");
    $(this).find(".state").html("closed");
  } else {
    $(this).find(".state").html("open");
    anim1.playSegments([0, 100], true);
    $("#box").addClass("active");
  }
  //For other button
  if ($("#slider").hasClass("active")) {
    anim2.playSegments([100, 0], true);
    $("#slider").removeClass("active");
    $("#slider").find(".state").html("closed");
  }
});
$("#slider").on("click", function() {
  anim1.setSpeed(5);
  anim2.setSpeed(16);
  //for Slider
  if ($("#slider").hasClass("active")) {
    anim2.playSegments([100, 0], true);
    $("#slider").removeClass("active");
    $(this).find(".state").html("closed");
  } else {
    $(this).find(".state").html("open");
    anim2.playSegments([0, 100], true);
    $("#slider").addClass("active");
  }
  //For other button
  if ($("#box").hasClass("active")) {
    anim1.playSegments([100, 0], true);
    $("#box").removeClass("active");
    $("#box").find(".state").html("closed");
  }
});
#box,
#slider {
  display: flex;
  color: white;
  align-items: center;
  cursor: pointer;
  height: 46px;
  max-width: 270px;
  min-width: 270px;
  margin-top: 9px;
  margin-right: 0.5rem;
  margin-bottom: 6px;
  border-style: none;
  border-radius: 6px;
  background-color: #4aabf0;
  font-size: 16px;
}

#slider {
  background-color: #756fe4;
}

#box path,
#slider path {
  fill: white;
  stroke: white;
}

#slider path {
  stroke-width: 0;
}

#box svg {
  min-height: 32px;
  max-height: 32px;
}

#slider svg {
  max-height: 26px;
}

#box svg,
#slider svg {
  transition: 0.2s cubic-bezier(0.45, 0, 0.55, 1);
}

#box.active>svg {
  transform: scale(.3);
  transform-origin: center;
  transition: 0.2s cubic-bezier(0.45, 0, 0.55, 1);
}

.container {
  margin: 0px auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  align-content: center;
}

.state {
  width: 90px;
  margin-left: .9rem
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.6.8/lottie_svg.min.js" integrity="sha256-nrcbQ5LezWWswBYK9nZCrIG7075yl2ChXPCkT/1UCt8=" crossorigin="anonymous"></script>
<div class="container">
  <div id="box">
    <div class="state">closed</div>
  </div>
  <div id="slider">
    <div class="state">closed</div>
  </div>
</div>

Another way to solve it is just to trigger a click of the active item:

var animData1 = {
  container: document.getElementById("box"),
  renderer: "svg",
  loop: false,
  autoplay: false,
  path: "https://cdn.statically.io/gist/moofawsaw/b8abeafe008f8b9ef040199c60a15162/raw/296dde84544ed1b41d5acfa303cca21c3ceee70f/lottie_box.json"
};
var animData2 = {
  container: document.getElementById("slider"),
  renderer: "svg",
  loop: false,
  autoplay: false,
  path: "https://assets6.lottiefiles.com/private_files/lf30_ht7mmN.json"
};
var anim1;
var anim2;

anim1 = bodymovin.loadAnimation(animData1);
anim2 = bodymovin.loadAnimation(animData2);

$("#box").on("click", function() {
  anim1.setSpeed(5);
  //for Box
  if ($("#box").hasClass("active")) {
    anim1.playSegments([100, 0], true);
    $("#box").removeClass("active");
    $(this).find(".state").html("closed");
  } else {
    $(this).find(".state").html("open");
    anim1.playSegments([0, 100], true);
    $("#box").addClass("active");
  }
  //For other button
  if ($("#slider").hasClass("active")) {
    $("#slider").click();
  }
});
$("#slider").on("click", function() {
  anim2.setSpeed(16);
  //for Slider
  if ($("#slider").hasClass("active")) {
    anim2.playSegments([100, 0], true);
    $("#slider").removeClass("active");
    $(this).find(".state").html("closed");
  } else {
    $(this).find(".state").html("open");
    anim2.playSegments([0, 100], true);
    $("#slider").addClass("active");
  }
  //For other button
  if ($("#box").hasClass("active")) {
   $("#box").click();
  }
});
#box,
#slider {
  display: flex;
  color: white;
  align-items: center;
  cursor: pointer;
  height: 46px;
  max-width: 270px;
  min-width: 270px;
  margin-top: 9px;
  margin-right: 0.5rem;
  margin-bottom: 6px;
  border-style: none;
  border-radius: 6px;
  background-color: #4aabf0;
  font-size: 16px;
}

#slider {
  background-color: #756fe4;
}

#box path,
#slider path {
  fill: white;
  stroke: white;
}

#slider path {
  stroke-width: 0;
}

#box svg {
  min-height: 32px;
  max-height: 32px;
}

#slider svg {
  max-height: 26px;
}

#box svg,
#slider svg {
  transition: 0.2s cubic-bezier(0.45, 0, 0.55, 1);
}

#box.active>svg {
  transform: scale(.3);
  transform-origin: center;
  transition: 0.2s cubic-bezier(0.45, 0, 0.55, 1);
}

.container {
  margin: 0px auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  align-content: center;
}

.state {
  width: 90px;
  margin-left: .9rem
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.6.8/lottie_svg.min.js" integrity="sha256-nrcbQ5LezWWswBYK9nZCrIG7075yl2ChXPCkT/1UCt8=" crossorigin="anonymous"></script>
<div class="container">
  <div id="box">
    <div class="state">closed</div>
  </div>
  <div id="slider">
    <div class="state">closed</div>
  </div>
</div>
matthias_h
  • 11,356
  • 9
  • 22
  • 40
  • @ChrisG Would it be better practice in your opinion to just trigger a click of the active item? – matthias_h Jun 08 '20 at 18:01
  • That's one way to solve it, but I prefer what I did in the [fiddle](https://jsfiddle.net/khrismuc/sf71xzet/) linked in my comment above (i.e. move repeated code inside a function and call it multiple times) –  Jun 08 '20 at 18:04