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
text/typescript
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 };
export class UniSliderRangeComponent extends UniSliderBaseComponent implements OnChanges {
public thumbs: { [key: string]: SliderModel } = {
from: { sliding: false, percent: 0 },
to: { sliding: false, percent: 0 }
}
pushable = true;
showTicks = false;
componentClass = true;
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();
}
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();
}
onStartSlide(event) {
const thumb = this.selectThumbByPercent(this.getPercentByX(event.center.x));
this.sliding = thumb;
this.thumbs[thumb].sliding = true;
}
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;
}
}
}
}