草庐IT

javascript - 将方向控制与滑动事件同步

coder 2024-05-12 原文

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

$(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>

最佳答案

你在那里有多个问题:

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

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

Node that we can remove one of the variables and use only the attr value, but I will leave that for you :)

这是工作片段:

$(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>

关于javascript - 将方向控制与滑动事件同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44938047/

有关javascript - 将方向控制与滑动事件同步的更多相关文章

  1. Ruby Readline 在向上箭头上使控制台崩溃 - 2

    当我在Rails控制台中按向上或向左箭头时,出现此错误:irb(main):001:0>/Users/me/.rvm/gems/ruby-2.0.0-p247/gems/rb-readline-0.4.2/lib/rbreadline.rb:4269:in`blockin_rl_dispatch_subseq':invalidbytesequenceinUTF-8(ArgumentError)我使用rvm来管理我的ruby​​安装。我正在使用=>ruby-2.0.0-p247[x86_64]我使用bundle来管理我的gem,并且我有rb-readline(0.4.2)(人们推荐的最少

  2. ruby-on-rails - 带 Spring 锁的 Rails 4 控制台 - 2

    我正在使用Ruby2.1.1和Rails4.1.0.rc1。当执行railsc时,它被锁定了。使用Ctrl-C停止,我得到以下错误日志:~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`gets':Interruptfrom~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.2/lib/spring/client/run.rb:47:in`verify_server_version'from~/.rvm/gems/ruby-2.1.1/gems/spring-1.1.

  3. ruby-on-rails - openshift 上的 rails 控制台 - 2

    我将我的Rails应用程序部署到OpenShift,它运行良好,但我无法在生产服务器上运行“Rails控制台”。它给了我这个错误。我该如何解决这个问题?我尝试更新ruby​​gems,但它也给出了权限被拒绝的错误,我也无法做到。railsc错误:Warning:You'reusingRubygems1.8.24withSpring.UpgradetoatleastRubygems2.1.0andrun`gempristine--all`forbetterstartupperformance./opt/rh/ruby193/root/usr/share/rubygems/rubygems

  4. ruby-on-rails - 事件管理员日期过滤器日期格式自定义 - 2

    是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s

  5. 使用canal同步MySQL数据到ES - 2

    文章目录一、概述简介原理模块二、配置Mysql使用版本环境要求1.操作系统2.mysql要求三、配置canal-server离线下载在线下载上传解压修改配置单机配置集群配置分库分表配置1.修改全局配置2.实例配置垂直分库水平分库3.修改group-instance.xml4.启动监听四、配置canal-adapter1修改启动配置2配置映射文件3启动ES数据同步查询所有订阅同步数据同步开关启动4.验证五、配置canal-admin一、概述简介canal是Alibaba旗下的一款开源项目,Java开发。基于数据库增量日志解析,提供增量数据订阅&消费。Git地址:https://github.co

  6. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  7. ruby-on-rails - 事件记录 : Select max of limit - 2

    我正在尝试将以下SQL查询转换为ActiveRecord,它正在融化我的大脑。deletefromtablewhereid有什么想法吗?我想做的是限制表中的行数。所以,我想删除少于最近10个条目的所有内容。编辑:通过结合以下几个答案找到了解决方案。Temperature.where('id这给我留下了最新的10个条目。 最佳答案 从您的SQL来看,您似乎想要从表中删除前10条记录。我相信到目前为止的大多数答案都会如此。这里有两个额外的选择:基于MurifoX的版本:Table.where(:id=>Table.order(:id).

  8. ruby-on-rails - 在 Rails 控制台中使用 asset_path - 2

    在我的Character模型中,我添加了:字符.rbbefore_savedoself.profile_picture_url=asset_path('icon.png')end但是,对于数据库中已存在的所有角色,它们的profile_picture_url为nil。因此,我想进入控制台并遍历所有这些并进行设置。在我试过的控制台中:Character.find_eachdo|c|c.profile_picture_url=asset_path('icon.png')end但这给出了错误:NoMethodError:undefinedmethod`asset_path'formain:O

  9. ruby-on-rails - 带有 Pry 的 Rails 控制台 - 2

    当我进入Rails控制台时,我已将pry设置为加载代替irb。我找不到该页面或不记得如何将其恢复为默认行为,因为它似乎干扰了我的Rubymine调试器。有什么建议吗? 最佳答案 我刚发现问题,pry-railsgem。忘记了它的目的是让“railsconsole”打开pry。 关于ruby-on-rails-带有Pry的Rails控制台,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/question

  10. ruby - 将全局 $stdout 重新分配给控制台 - ruby - 2

    我正在尝试将$stdout设置为临时写入一个文件,然后返回到一个文件。test.rb:old_stdout=$stdout$stdout.reopen("mytestfile.out",'w+')puts"thisgoesinmytestfile"$stdout=old_stdoutputs"thisshouldbeontheconsole"$stdout.reopen("mytestfile1.out",'w+')puts"thisgoesinmytestfile1:"$stdout=old_stdoutputs"thisshouldbebackontheconsole"这是输出。r

随机推荐