Breath guide

Animated and controllable breath guide component.

by irama

HTML

<div class="breath-guide">
  <div class="play"></div>
  <div class="in">IN</div>
  <div class="out">OUT</div>
  
  <div class="breath-bubble" id="breath-bubble-1"></div>
  <div class="breath-bubble-full"></div>
  
  <div class="breath-guide-controls">
    <input type="range" min="1" max="6" step="1" value="3">
    <p class="breath-guide-duration">3 seconds</p>
  </div>
</div>

CSS

.breath-guide {
  text-align: center;
  position: relative;
  font-family: sans-serif;
}

.breath-bubble,
.breath-bubble-full {
  border-radius: 50%;
  margin: auto;
  position: absolute;
  opacity: 0.4;
  width: 50px;
  height: 50px;
  top: 100px;
  left: 100px;
  border-radius: 50%;
  margin: auto;
  background: blue;
}
.breath-bubble {
  z-index: 98;
}
.breath-bubble-full {
  opacity: .2;
  width: 200px;
  height: 200px;
  top: 25px;
  left: 25px;
}

.breath-guide .in,
.breath-guide .out,
.breath-guide .play {
  color: #fff;
  margin: auto;
  position: absolute;
  top: 125px;
  left: 125px;
  z-index: 99;
  opacity: 0;
  margin-top: -7px;
}
.breath-guide .in {
  margin-left: -9px;
}
.breath-guide .out {
  margin-left: -16px;
}
.breath-guide .play {
  margin-left: -8px;
  margin-top: -12px;
  opacity: 1;
  width: 0;
  height: 0;
  border-style: solid;
  border-width: 12px 0 12px 20px;
  border-color: transparent transparent transparent #fff;
  cursor: pointer;
  z-index: 100;
}

.breath-guide-controls {
  position: absolute;
  top: 250px;
  left: 60px;
}
.breath-guide input {
  width: 130px
}

JavaScript

breatheIn = function($guide) {
		var bubble = $guide.find('.breath-bubble');
    $(bubble).animate({
        width: 200,
        height: 200,
        top: 25,
        left: 25,
        opacity: 1
    }, {
        duration: $guide.find('input').val()*1000,
        easing: "linear",
        complete: function(){ breatheOut($guide); }
    });
    $guide.find('.in').animate({
        opacity: 1
    }, {
        duration: 500
    });
    $guide.find('.out').animate({
        opacity: 0
    }, {
        duration: 500
    });
}
breatheOut = function($guide) {
		var bubble = $guide.find('.breath-bubble');
    $(bubble).animate({
        width: 50,
        height: 50,
        top: 100,
        left: 100,
        opacity: 0.4
    }, {
        duration: $guide.find('input').val()*1000,
        easing: "linear",
        complete: function(){ breatheIn($guide); }
    });
    $guide.find('.in').animate({
        opacity: 0
    }, {
        duration: 500
    });
    $guide.find('.out').animate({
        opacity: 1
    }, {
        duration: 500
    });
}


$('.breath-guide').find('input').change(function(){
	$(this).siblings('.breath-guide-duration').text($(this).val()+' seconds');
});
$('.breath-guide').find('.play').click(function(){
	$(this).hide();
  breatheIn($(this).parents('.breath-guide'));
});