UNPKG

unicorn-components

Version:

<a target="_blank" href="https://getunicorn.io"><img src="https://bitbucket-assetroot.s3.amazonaws.com/c/photos/2017/Jul/07/2615006260-5-nitsnetsstudios-ondemand-UNI_avatar.png" align="left"></a>

116 lines (99 loc) 4.1 kB
import { Component, ElementRef, HostBinding, HostListener, Input, OnChanges } from '@angular/core'; import { UniSliderBaseComponent } from '../../base/slider-base/slider-base.component'; type SliderModel = { sliding: boolean, percent: number }; @Component({ selector: 'uni-slider-range', templateUrl: 'slider-range.component.html', styleUrls: ['slider-range.component.scss'] }) export class UniSliderRangeComponent extends UniSliderBaseComponent implements OnChanges { public thumbs: { [key: string]: SliderModel } = { from: { sliding: false, percent: 0 }, to: { sliding: false, percent: 0 } } @Input() pushable = true; @Input() showTicks = false; @HostBinding('class.uni-slider-range') componentClass = true; @HostListener('pan', ['$event']) onSlide(event) { const percent = this.getPercentByX(event.center.x); let thumb = this.sliding || this.selectThumbByPercent(percent); this.thumbs[thumb].percent = percent; this.fixPercents(); this.updateModelByPercent(); event.preventDefault(); } @HostListener('tap', ['$event']) @HostListener('press', ['$event']) onClick(event) { const percent = this.getPercentByX(event.center.x); const thumb = this.selectThumbByPercent(percent); this.thumbs[thumb].percent = percent; this.fixPercents(); this.updateModelByPercent(); event.preventDefault(); } @HostListener('panstart', ['$event']) onStartSlide(event) { const thumb = this.selectThumbByPercent(this.getPercentByX(event.center.x)); this.sliding = thumb; this.thumbs[thumb].sliding = true; } @HostListener('panend', ['$event']) onEndSlide(event) { if (this.sliding && this.thumbs[this.sliding]) { this.thumbs[this.sliding].sliding = false; } this.sliding = null; } get thumbFromStyle() { return { transform: `translateX(${this.thumbs.from.percent * this.elementRef.nativeElement.clientWidth}px)` }; } get thumbToStyle() { return { transform: `translateX(${this.thumbs.to.percent * this.elementRef.nativeElement.clientWidth}px)` }; } get trackStyle() { const sliderWidth = this.elementRef.nativeElement.clientWidth; return { left: `${this.thumbs.from.percent * sliderWidth}px`, width: `${(this.thumbs.to.percent - this.thumbs.from.percent) * sliderWidth}px` }; } private sliding: 'from' | 'to' = null; constructor(elementRef: ElementRef) { super(elementRef); } private selectThumbByPercent(percent: number): 'from' | 'to' { const fromDiff = percent - this.thumbs.from.percent; const fromDiffAbs = Math.abs(fromDiff); const toDiff = percent - this.thumbs.to.percent; const toDiffAbs = Math.abs(toDiff); if (fromDiffAbs < toDiffAbs) { return 'from'; } if (fromDiffAbs > toDiffAbs) { return 'to'; } if (toDiff > 0) { return 'to'; } return 'from'; } updatePercentByModel() { // TODO: Allow thumbs refresh when external model changes happen } updateModelByPercent() { if (this.thumbs.from.percent > this.thumbs.to.percent) { if (this.sliding === 'from') { this.thumbs.to.percent = this.thumbs.from.percent; } else { this.thumbs.from.percent = this.thumbs.to.percent; } } this.onNgModelChange({ from: Math.max(this.thumbs.from.percent, 0) * this.range, to: Math.min(this.thumbs.to.percent, 1) * this.range }); } private fixPercents() { if (this.thumbs.from.percent > this.thumbs.to.percent) { if (this.sliding === 'from') { this.thumbs.to.percent = this.pushable ? this.thumbs.from.percent : this.thumbs.from.percent + 1; } else { this.thumbs.from.percent = this.pushable ? this.thumbs.to.percent : this.thumbs.to.percent + 1; } } } }