【问题标题】:Sync directional controls with swipe events将方向控制与滑动事件同步
【发布时间】:2017-07-06 00:37:47
【问题描述】:

我已经构建了两种功能来控制我构建的滑块。一个是带有方向控制的按钮,另一个是触摸/滑动事件。如何同步它们,以便当我按下 prev/next 时,滑动事件也会更新,反之亦然

$(document).ready(function() {


	$('.prev').on('click', function(e) {
	    event.stopPropagation();
	    // store variable relevent to clicked slider
	    var sliderWrapper      = $(this).closest('.slider-wrapper'),
		    slideItems         = sliderWrapper.find('.slide-items'),
	        slider             = sliderWrapper.find('.slider'),
	        currentSlide       = sliderWrapper.attr('data-slide');

	    // Check if data-slide attribute is greater than 0
	    if( currentSlide > 0 ) {
			// Decremement current slide
			currentSlide--;
			// Assign CSS position to clicked slider
			slider.css({'right' : currentSlide*slideItems.outerWidth() });
			// Update data-slide attribute
			sliderWrapper.attr('data-slide', currentSlide);
	    }
	});

	$('.next').on('click', function(e) {
	    event.stopPropagation();
	    // store variable relevent to clicked slider

		var sliderWrapper      = $(this).closest('.slider-wrapper'),
		    slideItems         = sliderWrapper.find('.slide-items'),
		    slider             = sliderWrapper.find('.slider'),
		    totalSlides        = slideItems.length,
		    currentSlide       = sliderWrapper.attr('data-slide');

		// Check if dataslide is less than the total slides
		if( currentSlide < totalSlides - 1 ) {
		    // Increment current slide
		    currentSlide++;
		    // Assign CSS position to clicked slider
		    slider.css({'right' : currentSlide*slideItems.outerWidth() });
		    // Update data-slide attribute
		    sliderWrapper.attr('data-slide', currentSlide);
		}
	})

	$('.slider-wrapper .slider').each(function(){

	    // create a simple instance
	    // by default, it only adds horizontal recognizers
	 
	    var direction;
        var touchSlider = this;
        var activeSlide = 0;
	    var mc = new Hammer.Manager(this),
	        itemLength = $(this).find('.slide-items').length,
	        count = 0,
	        slide = $(this);
	    
		var sliderWrapper      = slide,
		    slideItems         = sliderWrapper.find('.slide-items'),
		    slider             = sliderWrapper.find('.slider'),
		    totalSlides        = slideItems.length,
		    currentSlide       = sliderWrapper.attr('data-slide');
	    
	    // mc.on("panleft panright", function(ev) {
	    //   direction = ev.type;
	    // });
        
        mc.add(new Hammer.Pan({ threshold: 0, pointers: 0 }))
	    mc.on('pan', function(e) {	
            var percentage = 100 / totalSlides * e.deltaX / window.innerWidth;
            var transformPercentage = percentage - 100 / totalSlides * activeSlide;
            touchSlider.style.transform = 'translateX( ' +  transformPercentage + '% )';

			if( e.isFinal ) { // NEW: this only runs on event end
			    if( percentage < 0 )
			        goToSlide( activeSlide + 1 );
			    else if( percentage > 0 )
			        goToSlide( activeSlide - 1 );
			    else
			        goToSlide( activeSlide );
			}


	    });


		var goToSlide = function( number ) {
		  if( number < 0 )
		    activeSlide = 0;
		  else if( number > totalSlides - 1 )
		    activeSlide = totalSlides - 1
		  else
		    activeSlide = number;

		  touchSlider.classList.add('slide-animation');
		  var percentage = -( 100 / totalSlides ) * activeSlide;
		  touchSlider.style.transform = 'translateX( ' + percentage + '% )';
		  timer = setTimeout( function() {
		      touchSlider.classList.remove('slide-animation');
		  }, 400);

		};

	   //  mc.on("panend", function(ev) {
		  //   if(direction === "panleft") {
	   //          console.log('panleft');

				// // Check if dataslide is less than the total slides
				// if( currentSlide < totalSlides - 1 ) {
				//     // Increment current slide
				//     currentSlide++;
				//     // Assign CSS position to clicked slider
				//     slider.css({'right' : currentSlide*slideItems.outerWidth() });
				//     // Update data-slide attribute
				//     sliderWrapper.attr('data-slide', currentSlide);
				// }
		  //   }

		  //   if(direction === "panright") {
	   //          console.log('right');

			 //    // Check if data-slide attribute is greater than 0
			 //    if( currentSlide > 0 ) {
				// 	// Decremement current slide
				// 	currentSlide--;
				// 	// Assign CSS position to clicked slider
				// 	slider.css({'right' : currentSlide*slideItems.outerWidth() });
				// 	// Update data-slide attribute
				// 	sliderWrapper.attr('data-slide', currentSlide);
			 //    }
		  //   }
	   //  });
	});

});




$(window).on('load', function() {
  $('.slider-wrapper').each(function() {
    var slideItems = $(this).find('.slide-items'),
    items = slideItems.length,
    sliderBox = $(this).find('.slider'),
    sliderWrapperWidth = $(this).width();
    
    slideItems.outerWidth( sliderWrapperWidth );
    
    sliderBox.width( slideItems.outerWidth() * items  );
  });

});
/* http://meyerweb.com/eric/tools/css/reset/
 v2.0 | 20110126
 License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline; }

/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
  display: block; }

body {
  line-height: 1; }

ol, ul {
  list-style: none; }

blockquote, q {
  quotes: none; }

blockquote:before, blockquote:after,
q:before, q:after {
  content: '';
  content: none; }

table {
  border-collapse: collapse;
  border-spacing: 0; }

* {
  box-sizing: border-box; }

.container {
  max-width: 1280px;
  margin: 0 auto; }

.container .slider-wrapper {
  margin-bottom: 40px;
  background-color: grey;
  overflow: hidden;
  display: block; }

.container .slider-wrapper .slider {
  position: relative;
  right: 0;
  display: flex;
  flex-wrap: wrap;
  overflow: hidden;
  /*-webkit-transition : transform 0.3s linear;*/ }
  .container .slider-wrapper .slider.slide-animation {
    -webkit-transition: transform 0.3s linear; }

.container .slider-wrapper .slider > div {
  padding: 10px;
  background-color: #e5d0d0;
  height: 200px; }

.container .slider-wrapper .slider > div p {
  color: purple; }

.container .slider-wrapper .buttons {
  display: flex;
  justify-content: space-between;
  background: beige;
  padding: 10px 0; }

.container .slider-wrapper .buttons div {
  background-color: cyan; }

/*# sourceMappingURL=style.css.map */
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.7/hammer.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container">
  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>1</p>
        </div>

        <div class="slide-items">
            <p>2</p>
        </div>

        <div class="slide-items">
            <p>3</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>
  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>1</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>

  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>2</p>
        </div>
        <div class="slide-items">
            <p>3</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>
  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>1</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>
  <div class="slider-wrapper" data-slide="0">
    <div class="slider">
        <div class="slide-items">
            <p>1</p>
        </div>

        <div class="slide-items">
            <p>2</p>
        </div>
    </div>
    <div class="buttons">
        <div class="prev">prev</div>
        <div class="next">next</div>
    </div>
  </div>
</div>

【问题讨论】:

    标签: javascript jquery swipe hammer.js


    【解决方案1】:

    你有多个问题:

    1. 您使用了两种不同的方法来定位幻灯片(您使用的 hammer 插件使用 translateX 定位它,而您尝试使用 css right 定位。
    2. 每种方法都使用不同的来源来确定哪张幻灯片是活动幻灯片(您使用了.slider-wrapperattr,而hammer 使用了activeSlide 变量。

    我修复了两者以使用translateX,将activeSlide 变量移到$('.slider-wrapper .slider').each 函数的范围之外,并确保每次更改都会影响这两个变量。

    我们可以删除其中一个变量并仅使用 attr 值的节点,但我会把它留给你 :)

    这里是工作的 sn-p:

    $(document).ready(function() {
    
        var activeSlide = 0;
    
        $('.prev').on('click', function(e) {
            event.stopPropagation();
            // store variable relevent to clicked slider
            var sliderWrapper = $(this).closest('.slider-wrapper'),
                slideItems = sliderWrapper.find('.slide-items'),
                totalSlides = slideItems.length,
                slider = sliderWrapper.find('.slider'),
                currentSlide = parseInt(sliderWrapper.attr('data-slide'));
    
            // Check if data-slide attribute is greater than 0
            if (currentSlide > 0) {
                // Decremement current slide
                currentSlide--;
                // Assign CSS position to clicked slider
                var transformPercentage = -1 * currentSlide / totalSlides * 100;
                slider.css('transform', 'translateX(' + transformPercentage + '% )');
                // Update data-slide attribute
                sliderWrapper.attr('data-slide', currentSlide);
                activeSlide = currentSlide;
            }
        });
    
        $('.next').on('click', function(e) {
            event.stopPropagation();
            // store variable relevent to clicked slider
    
            var sliderWrapper = $(this).closest('.slider-wrapper'),
                slideItems = sliderWrapper.find('.slide-items'),
                slider = sliderWrapper.find('.slider'),
                totalSlides = slideItems.length,
                currentSlide = parseInt(sliderWrapper.attr('data-slide'));
    
            // Check if dataslide is less than the total slides
            if (currentSlide < totalSlides - 1) {
                // Increment current slide
                currentSlide++;
                // Assign CSS position to clicked slider
                var transformPercentage = -1 * currentSlide / totalSlides * 100;
                slider.css('transform', 'translateX(' + transformPercentage + '% )');
                // Update data-slide attribute
                sliderWrapper.attr('data-slide', currentSlide);
                activeSlide = currentSlide;
            }
        })
    
        $('.slider-wrapper .slider').each(function() {
    
            // create a simple instance
            // by default, it only adds horizontal recognizers
    
            var direction;
            var touchSlider = this;
            var mc = new Hammer.Manager(this),
                itemLength = $(this).find('.slide-items').length,
                count = 0,
                slide = $(this);
    
            var sliderWrapper = slide,
                slideItems = sliderWrapper.find('.slide-items'),
                slider = sliderWrapper.find('.slider'),
                totalSlides = slideItems.length,
                currentSlide = parseInt(sliderWrapper.attr('data-slide'));
    
            // mc.on("panleft panright", function(ev) {
            //   direction = ev.type;
            // });
    
            mc.add(new Hammer.Pan({
                threshold: 0,
                pointers: 0
            }))
            mc.on('pan', function(e) {
                var percentage = 100 / totalSlides * e.deltaX / window.innerWidth;
                var transformPercentage = percentage - 100 / totalSlides * activeSlide;
                touchSlider.style.transform = 'translateX( ' + transformPercentage + '% )';
                var sliderWrapper = $(e.target).closest('.slider-wrapper')
    
    
                if (e.isFinal) { // NEW: this only runs on event end
    
                    var newSlide = activeSlide;
                    if (percentage < 0)
                        newSlide = activeSlide + 1;
                    else if (percentage > 0)
                        newSlide = activeSlide - 1;
                    goToSlide(newSlide, sliderWrapper);
                }
            });
    
    
            var goToSlide = function(number, sliderWrapper) {
                if (number < 0)
                    activeSlide = 0;
                else if (number > totalSlides - 1)
                    activeSlide = totalSlides - 1
                else
                    activeSlide = number;
    
                sliderWrapper.attr('data-slide', activeSlide);
    
                touchSlider.classList.add('slide-animation');
                var percentage = -(100 / totalSlides) * activeSlide;
                touchSlider.style.transform = 'translateX( ' + percentage + '% )';
                timer = setTimeout(function() {
                    touchSlider.classList.remove('slide-animation');
                }, 400);
    
            };
    
        });
    
    });
    
    
    
    
    $(window).on('load', function() {
        $('.slider-wrapper').each(function() {
            var slideItems = $(this).find('.slide-items'),
                items = slideItems.length,
                sliderBox = $(this).find('.slider'),
                sliderWrapperWidth = $(this).width();
    
            slideItems.outerWidth(sliderWrapperWidth);
    
            sliderBox.width(slideItems.outerWidth() * items);
        });
    
    });
    /* http://meyerweb.com/eric/tools/css/reset/
     v2.0 | 20110126
     License: none (public domain)
    */
    html, body, div, span, applet, object, iframe,
    h1, h2, h3, h4, h5, h6, p, blockquote, pre,
    a, abbr, acronym, address, big, cite, code,
    del, dfn, em, img, ins, kbd, q, s, samp,
    small, strike, strong, sub, sup, tt, var,
    b, u, i, center,
    dl, dt, dd, ol, ul, li,
    fieldset, form, label, legend,
    table, caption, tbody, tfoot, thead, tr, th, td,
    article, aside, canvas, details, embed,
    figure, figcaption, footer, header, hgroup,
    menu, nav, output, ruby, section, summary,
    time, mark, audio, video {
      margin: 0;
      padding: 0;
      border: 0;
      font-size: 100%;
      font: inherit;
      vertical-align: baseline; }
    
    /* HTML5 display-role reset for older browsers */
    article, aside, details, figcaption, figure,
    footer, header, hgroup, menu, nav, section {
      display: block; }
    
    body {
      line-height: 1; }
    
    ol, ul {
      list-style: none; }
    
    blockquote, q {
      quotes: none; }
    
    blockquote:before, blockquote:after,
    q:before, q:after {
      content: '';
      content: none; }
    
    table {
      border-collapse: collapse;
      border-spacing: 0; }
    
    * {
      box-sizing: border-box; }
    
    .container {
      max-width: 1280px;
      margin: 0 auto; }
    
    .container .slider-wrapper {
      margin-bottom: 40px;
      background-color: grey;
      overflow: hidden;
      display: block; }
    
    .container .slider-wrapper .slider {
      position: relative;
      right: 0;
      display: flex;
      flex-wrap: wrap;
      overflow: hidden;
      /*-webkit-transition : transform 0.3s linear;*/ }
      .container .slider-wrapper .slider.slide-animation {
        -webkit-transition: transform 0.3s linear; }
    
    .container .slider-wrapper .slider > div {
      padding: 10px;
      background-color: #e5d0d0;
      height: 200px; }
    
    .container .slider-wrapper .slider > div p {
      color: purple; }
    
    .container .slider-wrapper .buttons {
      display: flex;
      justify-content: space-between;
      background: beige;
      padding: 10px 0; }
    
    .container .slider-wrapper .buttons div {
      background-color: cyan; }
    
    /*# sourceMappingURL=style.css.map */
    <script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.7/hammer.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="container">
        <div class="slider-wrapper" data-slide="0">
            <div class="slider">
                <div class="slide-items">
                    <p>1</p>
                </div>
    
                <div class="slide-items">
                    <p>2</p>
                </div>
    
                <div class="slide-items">
                    <p>3</p>
                </div>
            </div>
            <div class="buttons">
                <div class="prev">prev</div>
                <div class="next">next</div>
            </div>
        </div>
        <div class="slider-wrapper" data-slide="0">
            <div class="slider">
                <div class="slide-items">
                    <p>1</p>
                </div>
            </div>
            <div class="buttons">
                <div class="prev">prev</div>
                <div class="next">next</div>
            </div>
        </div>
    
        <div class="slider-wrapper" data-slide="0">
            <div class="slider">
                <div class="slide-items">
                    <p>2</p>
                </div>
                <div class="slide-items">
                    <p>3</p>
                </div>
            </div>
            <div class="buttons">
                <div class="prev">prev</div>
                <div class="next">next</div>
            </div>
        </div>
        <div class="slider-wrapper" data-slide="0">
            <div class="slider">
                <div class="slide-items">
                    <p>1</p>
                </div>
            </div>
            <div class="buttons">
                <div class="prev">prev</div>
                <div class="next">next</div>
            </div>
        </div>
        <div class="slider-wrapper" data-slide="0">
            <div class="slider">
                <div class="slide-items">
                    <p>1</p>
                </div>
    
                <div class="slide-items">
                    <p>2</p>
                </div>
            </div>
            <div class="buttons">
                <div class="prev">prev</div>
                <div class="next">next</div>
            </div>
        </div>
    </div>

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-05
      • 1970-01-01
      • 2021-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多