Как предотвратить анимированное расширение в несколько раз после нескольких кликов - PullRequest
0 голосов
/ 22 декабря 2019

У меня есть список с каждым элементом списка, который расширяется при нажатии, а затем уменьшается после повторного нажатия с анимацией, которая длится 200 мс. Это работает нормально, но если пользователь щелкает элемент списка несколько раз за короткий промежуток времени, он пытается догнать пользователя таким образом, который заставляет его расширяться и сжиматься несколько раз в течение довольно длительного периода времени,выглядит очень глючно.

Вот мой HTML

<ul id="cons">
    <li></li>
    <li></li>
    <li></li>
    <li></li>
    <li></li>
</ul>

(элементы моего списка оформлены в виде цветных блоков)

И мой JavaScript

  Array.from(document.getElementById('cons').children).forEach((item, index) => {
      function toggleForward(item) {
        return () => {
          $(item).animate({height: '400px'}, 400)
          $(item).off('click').click(toggleBackward(item))
        }
      }
      function toggleBackward(item) {
        return () => {
          $(item).animate({height: '50px'}, 400)
          $(item).off('click').click(toggleForward(item))
        }
      }
      $(item).click(toggleForward(item))
  })

Ответы [ 2 ]

0 голосов
/ 22 декабря 2019

Я исправил это. Хитрость заключалась в том, чтобы спросить, был ли элемент уже анимирован, и анимировать его только по щелчку, если он еще не был в середине анимации. Таким образом, анимации не «складываются» друг с другом, что требует их наверстывания. Итак, я изменил свой код на это:

Array.from(document.getElementById('cons').children).forEach((item, index) => {
    function toggleForward(item) {
      return () => {
        if(!($(item).is(':animated'))) {
          $(item).animate({height: '400px'}, 400)
          $(item).off('click').click(toggleBackward(item))
        }
      }
    }
    function toggleBackward(item) {
      return () => {
        if(!($(item).is(':animated'))) {
          $(item).animate({height: '50px'}, 400)
          $(item).off('click').click(toggleForward(item))
        }
      }
    }
    $(item).click(toggleForward(item))
})
0 голосов
/ 22 декабря 2019

РЕДАКТИРОВАТЬ: извините за это, я неправильно понял ваш вопрос.

Это должно сделать это, хотя:

ОРИГИНАЛЬНЫЙ ОТВЕТ:

$("#cons").children().each((index, item) => {
  let itemToggler = new Toggler(item, 400, '100px', 'no-cursor');
  $(item).on('click', event => itemToggler.toggle())
});

function Toggler(item, duration, maxToggleHeight, noCursorClass) {
  this.item = item;
  this.toggled = false;
  this.noCursorClass = noCursorClass;
  this.maxToggleHeight = maxToggleHeight;
  this.duration = duration;
  this.originalHeight = $(item).height();

  this.toggle = () => {
    $(this.item).addClass(this.noCursorClass);
    $(this.item).animate({
      height: this.toggled ? this.originalHeight : this.maxToggleHeight
    }, {
      duration: this.duration,
      complete: () => {
        $(this.item).removeClass(this.noCursorClass);
        this.toggled = !this.toggled;
      }
    });
  }
}
li {
  cursor: pointer;
}

.no-cursor {
  cursor: not-allowed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Click on an item</p>
<ul id="cons">
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
  <li>Four</li>
  <li>Five</li>
</ul>

ОБНОВЛЕННЫЙ ОТВЕТ : в качестве плагина jQuery:

MakePlugin();

$("#cons").children().each((ndx, itm) => {
  $(itm).clickToggler({
    cursorClass: "cursor-pointer",
    noCursorClass: "cursor-not-allowed",
    maxToggleHeight: '100px',
    duration: 400
  });
});


// The plugin is only wrapped in this MakePlugin() function
// so I could put it below the 'main logic' above.
function MakePlugin() {


  // Main 'clickToggler' plugin:
  (function($) {
    $.fn.clickToggler = function(options) {
      let settings = $.extend({
          toggled: false,
          cursorClass: "",
          noCursorClass: "",
          maxToggleHeight: '10px',
          duration: 100
        }, { 
          originalHeight: $(this).height(),
          ...options 
        }
      );

      $(this).on("click", event => {
        if(!$(this).is(':animated')) {
          $(this).addClass(settings.noCursorClass);
          $(this).animate({
            height: settings.toggled ? settings.originalHeight : settings.maxToggleHeight
          }, {
            duration: settings.duration,
            complete: () => {
              $(this).removeClass(settings.noCursorClass);
              settings.toggled = !settings.toggled;
            }
          });
        }
      });
      
      return settings.cursorClass
        ? $(this).addClass(settings.cursorClass)
        : this;
    };
  })(jQuery);
  
  
}
.cursor-pointer {
  cursor: pointer;
}

.cursor-not-allowed {
  cursor: not-allowed;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Click on an item</p>
<ul id="cons">
  <li>One</li>
  <li>Two</li>
  <li>Three</li>
  <li>Four</li>
  <li>Five</li>
</ul>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...