2017-11-14 16 views
0

Hammer JS 2.0.8을 사용하여 사용자 정의 회전 목마를 만들 때 유동적으로 작동하는 데 약간의 문제가있었습니다. 여러 번 시도한 후 실제로 도움이되는 코드 조각을 발견했으며 결국 모듈을 완성 할 때 Richard Liu의Hammer JS를 회전 목마로 사용

답변

0

This was the snippet that really helped 등으로 똑같이 공유하기로 결정했습니다.

Hammer 2.0.4로 다시 전환하면 pancancel/panend 콜백이보다 안정적으로 수행됩니다. 거기에서 내 솔루션을 완성 할 수있었습니다. complete demo 또한 JSFiddle에 있습니다.

class Carousel { 
constructor(options) { 
    this.transiting = false; 
    this.activeCard = 1; 
    this.offset = 0; 
    this.delta = 0; 
    this.element = options.carousel; 
    this.slides = this.element.children.length; 
    this.element.style.width = `${this.slides * 100}%`; 
    this.width = options.carousel.clientWidth; 
    this.boundaryLeft = 0; 
    this.boundaryRight = ((this.count - 1)/this.count) * this.width; 
    this.outOfBounds = false; 
    this.panRequiredToMove = options.container.clientWidth * 0.25; 
    this.hammer = new Hammer(options.container); 

    this.init(); 
} 

init() { 
    var self = this; 

    function handleHammer(e) { 
     switch (e.type) { 
      case 'swipeleft': 
      case 'swiperight': 
       self.handleSwipe(e); 
       break; 
      case 'panleft': 
      case 'panright': 
      case 'panend': 
      case 'pancancel': 
       self.handlePan(e); 
       break; 
     } 
    } 

    this.hammer.on('swipeleft swiperight panleft panright panend pancancel', handleHammer); 
    this.element.addEventListener("transitionend", function (event) { 
     this.classList.remove('carousel--in-motion'); 
    }, false); 
} 

handleSwipe(e) { 
    switch (e.direction) { 
     case Hammer.DIRECTION_LEFT: 
      this.next(); 
      break; 
     case Hammer.DIRECTION_RIGHT: 
      this.previous(); 
      break; 
    } 
    this.hammer.stop(true); 
} 

checkBounds() {  
    var beforeFirstCard = this.activeCard === 1 && (this.offset + this.delta) >= this.boundaryLeft; 
    var afterLastCard = this.activeCard === this.slides && Math.abs(this.offset + this.delta) >= this.boundaryRight; 

    if (beforeFirstCard) { 
     this.outOfBounds = { recoilPosition: this.boundaryLeft }; 
    } else if (afterLastCard) { 
     this.outOfBounds = { recoilPosition: this.boundaryRight * -1 }; 
    } else { 
     this.outOfBounds = false; 
    } 
} 

handlePan(e) { 
    switch (e.type) { 
     case 'panleft': 
     case 'panright': 
       this.checkBounds(); 
      if (this.outOfBounds) e.deltaX *= .2; 
      this.transition(e.deltaX); 
      break; 
     case 'panend': 
     case 'pancancel': 
      if (this.outOfBounds) { 
       this.recoil(this.outOfBounds.recoilPosition); 
      } else if (Math.abs(e.deltaX) > this.panRequiredToMove) { 
       e.deltaX > 0 ? this.previous() : this.next(); 
      } else { 
       this.recoil(); 
      } 
      break; 
    } 
} 

next() { 
    if (this.activeCard < this.slides) { 
     let newPosition = this.activeCard/this.slides * this.width * -1; 
     this.goToSlide(newPosition,() => { 
      this.activeCard++; 
     }); 
    } 
} 

previous() { 
    if (this.activeCard > 1) { 
     let activeCard = this.activeCard - (this.slides - 1); 
     let newPosition = activeCard/this.slides * this.width * -1; 
     this.goToSlide(newPosition,() => { 
      this.activeCard--; 
     }); 
    } 
} 

goToSlide(position, callback) { 
    let self = this; 
    let currentPosition = this.offset + this.delta; 
    this.transiting = true; 

// I used AnimatePlus for the other movement between slides 
    animate({ 
     el: this.element, 
     translateX: [`${currentPosition}px`, `${position}px`], 
     duration: 300, 
     easing: "easeInOutQuad", 
     complete() { 
      self.transiting = false; 
      self.offset = position; 
      self.delta = 0; 
      if (callback) callback(); 
     } 
    }); 
} 

transition(deltaX) { 
    this.delta = deltaX; 
    let position = this.offset + this.delta; 
    this.element.style.webkitTransform = `translateX(${position}px)`; 
} 

recoil(position) {  
    this.element.classList.add('carousel--in-motion'); 
    this.element.style.webkitTransform = `translateX(${position || this.offset}px)`; 
} 
}