Карусель Bootstrap делает текст, появляющийся по буквам

Я использую автозагрузку для слайдера, на каждом слайде есть над ним текст.

Я бы хотел, чтобы этот текст над слайдами появлялся буквально по букве.

Я почти решил это.

Но есть 2 вопроса

  • На первом слайде текст вообще не появляется
  • Если пользователь переходит на другую вкладку в браузере, означает, что текущее окно не находится в фокусе, тогда все становится испорченным.

Вот моя скрипка

HTML

<main>
      <div class="container">
        <div class="block-wrap">
          <div id="js-carousel" class="carousel slide" data-ride="carousel">
            <!-- Wrapper for slides -->
            <div class="carousel-inner" role="listbox">
              <div class="item active">
                <img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Chania">
                <div class="caption">

                  <div class="mystring hide">companies with Inbound Marketing</div>
                  <h4>We help <div class="demo-txt"></div> </h4>
                </div>
              </div>

              <div class="item">
                <img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Chania">
                <div class="caption">
                <div class="mystring hide">companies with Inbound Marketing</div>

                  <h4>We help  <div class="demo-txt "></div> </h4>
                </div>
              </div>

              <div class="item">
                <img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Flower">
                <div class="caption">
                <div class="mystring hide">2companies with Inbound Marketing</div>

                  <h4>We help <div class="demo-txt"></div> </h4>
                </div>
              </div>

              <div class="item">
                <img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Flower">
                <div class="caption">
                <div class="mystring hide">3companies with Inbound Marketing</div>

                  <h4>We help <div class="demo-txt"></div> </h4>
                </div>
              </div>
              <div class="overlay-effect"></div>
            </div>
          </div>
        </div> 
      </div>
    </main>

JS

$(document).ready(function() {    
     $('#js-carousel').carousel({
        interval: 5000
    });

     $('#js-carousel').on('slid.bs.carousel', function () {
      var showText = function (target, message, index, interval) { 
        if (index < message.length) { 
          $(target).append(message[index++]); 
          setTimeout(function () { showText(target, message, index, interval); }, interval); 
        } 
      }                 
       var str = $(this).find(".active .mystring").html();
          $('.active .demo-txt').html("");         
          showText(".active .demo-txt", str, 0, 100);          
     });
    });

Ответ 1

Вместо settimeout используйте функцию setInterval. Также используйте clearInterval, чтобы очистить график, когда начнется новый слайд. (Я думаю, что это ваша вторая проблема.)

Вот ваш целевой файл js:

$(document).ready(function() {    
    $('#js-carousel').carousel({
        interval: 5000
    });
    var handler;
    var interval = 5000;
    var index = 0;
    function showText(target, message, index, interval) { 
        if (index < message.length) { 
            $(target).append(message[index]); 
        }
    }

    function iteration() {
        if(handler){
            clearInterval(handler);
        }
        index = 0;
        var str = $(this).find(".active .mystring").html();
        $('.active .demo-txt').html("");
        showText(".active .demo-txt", str, index++, 100);         
        handler = setInterval(function(){
            showText(".active .demo-txt", str, index++, 100);
        }, 100);
     }

     //on each carousel slide change: 
     $('#js-carousel').on('slid.bs.carousel', iteration);
     //start immediately for your first problem:
     iteration.bind($('#js-carousel'))();
});

Ответ 2

Это потому, что ваша функция находится внутри события слайда. При запуске карусель не скользит...

Fiddle: https://jsfiddle.net/Lbasa2jh/5/

JS

$(document).ready(function() {  
    var showText = function (target, message, index, interval) { 
    if (index < message.length) { 
          $(target).append(message[index++]); 
          setTimeout(function () { showText(target, message, index, interval); }, interval); 
        } 
      };

    $('#js-carousel').carousel({
        interval: 5000
    });

       var str0 = $(this).find(".active .mystring").html();
       $('.active .demo-txt').html("");         
       showText(".active .demo-txt", str0, 0, 100);    

     $('#js-carousel').on('slid.bs.carousel', function () {

       var str = $(this).find(".active .mystring").html();
          $('.active .demo-txt').html("");         
          showText(".active .demo-txt", str, 0, 100);          
     });
    });

Ответ 3

Таймер может быть сложным, если вкладка неактивна. Я переместил код и очистил таймаут, чтобы убедиться, что тайм-аут чист при запуске нового слайда.

Я заметил проблему (не всегда), когда переключение с другой вкладки заключается в том, что карусель на самом деле переместится на следующий слайд быстрее, чем на 5 секунд, в результате чего текст будет неполным.

https://jsfiddle.net/vLwm58Ln/

$(document).ready(function() {
  $('#js-carousel').carousel({
    interval: 5000
  });

  var showText = function(target, message, index, interval) {
    if (index < message.length) {      
      	$(target).append(message[index++]);
        timer = setTimeout(function() {
           showText(target, message, index, interval);
        }, interval);
    }
  }, timer;
  
  //First time, this triggers right away instead of waiting for the slide to move
  showText(".active .demo-txt", $('#js-carousel').find(".active .mystring").html(), 0, 100);
  
  $('#js-carousel').on('slid.bs.carousel', function() {
    //clear any messed up timeout from prev slide
    clearTimeout(timer);
    //clear message that may be incomplete from the previous text animation
    $('.prevActive').removeClass('prevActive').html('');
    var str = $(this).find(".active .mystring").html();
    $('.active .demo-txt').addClass('prevActive').html("");
	showText(".active .demo-txt", str, 0, 100);
  });
});
.carousel-inner {
  position: relative;
}

.carousel-inner .overlay-effect {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: rgba(0, 0, 0, 0.6);
}

.carousel-inner .caption {
  color: #ffffff;
  font-weight: bold;
  position: absolute;
  top: 0;
  bottom: 0;
  margin: auto 0;
  height: 100px;
  z-index: 9999;
  left: 5%;
}

.carousel-inner .caption h1,
.carousel-inner .caption h2 {
  font-weight: bold;
  line-height: 1.6;
}

.carousel-inner .caption h1 {
  font-size: 64px;
}

.carousel-inner .caption h2 {
  font-size: 44px;
}

.carousel-inner .demo-txt {
  border-bottom: 4px solid #ec8422;
  padding-bottom: 5px;
}
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.2.js"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
<link rel="stylesheet" type="text/css" href="#" onclick="location.href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css'; return false;">
<main>
  <div class="container">
    <div class="block-wrap">
      <div id="js-carousel" class="carousel slide" data-ride="carousel">
        <!-- Wrapper for slides -->
        <div class="carousel-inner" role="listbox">
          <div class="item active">
            <img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Chania">
            <div class="caption">

              <div class="mystring hide">companies with Inbound Marketing</div>
              <h4>We help <div class="demo-txt"></div> </h4>
            </div>
          </div>

          <div class="item">
            <img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Chania">
            <div class="caption">
              <div class="mystring hide">companies with Inbound Marketing</div>

              <h4>We help  <div class="demo-txt "></div> </h4>
            </div>
          </div>

          <div class="item">
            <img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Flower">
            <div class="caption">
              <div class="mystring hide">2companies with Inbound Marketing</div>

              <h4>We help <div class="demo-txt"></div> </h4>
            </div>
          </div>

          <div class="item">
            <img src="http://cdn.theatlantic.com/assets/media/img/photo/2015/11/images-from-the-2016-sony-world-pho/s01_130921474920553591/main_900.jpg?1448476701" alt="Flower">
            <div class="caption">
              <div class="mystring hide">3companies with Inbound Marketing</div>

              <h4>We help <div class="demo-txt"></div> </h4>
            </div>
          </div>
          <div class="overlay-effect"></div>
        </div>
      </div>
    </div>
  </div>
</main>