Fix range selector
This commit is contained in:
parent
63bec056c7
commit
b6a9c02c5c
@ -1,8 +1,8 @@
|
||||
import { ColorHsla, hexaToHsla, hslaToRgba, rgbaToHexa as rgbaToHexa, rgbaToHsla } from "../helpers/color";
|
||||
import attachGrabListeners from "../helpers/dom/attachGrabListeners";
|
||||
import { clamp } from "../helpers/number";
|
||||
import InputField, { InputState } from "./inputField";
|
||||
|
||||
type EventPosition = {x: number, y: number, isTouch?: boolean};
|
||||
export type ColorPickerColor = {
|
||||
hsl: string;
|
||||
rgb: string;
|
||||
@ -133,56 +133,6 @@ export default class ColorPicker {
|
||||
this.attachHueListeners();
|
||||
}
|
||||
|
||||
private attachGrabListeners(element: SVGSVGElement, onStart: (position: EventPosition) => void, onMove: (position: EventPosition) => void, onEnd: (position: EventPosition) => void) {
|
||||
// * Mouse
|
||||
const onMouseMove = (event: MouseEvent) => {
|
||||
onMove({x: event.pageX, y: event.pageY});
|
||||
};
|
||||
|
||||
const onMouseDown = (event: MouseEvent) => {
|
||||
if(event.button !== 0) {
|
||||
element.addEventListener('mousedown', onMouseDown, {once: true});
|
||||
return;
|
||||
}
|
||||
|
||||
this.onGrabStart();
|
||||
onStart({x: event.pageX, y: event.pageY});
|
||||
onMouseMove(event);
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
document.addEventListener('mouseup', () => {
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
element.addEventListener('mousedown', onMouseDown, {once: true});
|
||||
this.onGrabEnd();
|
||||
onEnd && onEnd({x: event.pageX, y: event.pageY});
|
||||
}, {once: true});
|
||||
};
|
||||
|
||||
element.addEventListener('mousedown', onMouseDown, {once: true});
|
||||
|
||||
// * Touch
|
||||
const onTouchMove = (event: TouchEvent) => {
|
||||
event.preventDefault();
|
||||
onMove({x: event.touches[0].clientX, y: event.touches[0].clientY, isTouch: true});
|
||||
};
|
||||
|
||||
const onTouchStart = (event: TouchEvent) => {
|
||||
this.onGrabStart();
|
||||
onStart({x: event.touches[0].clientX, y: event.touches[0].clientY, isTouch: true});
|
||||
onTouchMove(event);
|
||||
|
||||
document.addEventListener('touchmove', onTouchMove, {passive: false});
|
||||
document.addEventListener('touchend', (event) => {
|
||||
document.removeEventListener('touchmove', onTouchMove);
|
||||
element.addEventListener('touchstart', onTouchStart, {passive: true, once: true});
|
||||
this.onGrabEnd();
|
||||
onEnd && onEnd({x: event.touches[0].clientX, y: event.touches[0].clientY, isTouch: true});
|
||||
}, {passive: true, once: true});
|
||||
};
|
||||
|
||||
element.addEventListener('touchstart', onTouchStart, {passive: true, once: true});
|
||||
}
|
||||
|
||||
private onGrabStart = () => {
|
||||
document.documentElement.style.cursor = this.elements.boxDragger.style.cursor = 'grabbing';
|
||||
};
|
||||
@ -192,21 +142,27 @@ export default class ColorPicker {
|
||||
};
|
||||
|
||||
private attachBoxListeners() {
|
||||
this.attachGrabListeners(this.elements.box, () => {
|
||||
attachGrabListeners(this.elements.box as any, () => {
|
||||
this.onGrabStart();
|
||||
this.boxRect = this.elements.box.getBoundingClientRect();
|
||||
//this.boxDraggerRect = this.elements.boxDragger.getBoundingClientRect();
|
||||
}, (pos) => {
|
||||
this.saturationHandler(pos.x, pos.y);
|
||||
}, null);
|
||||
}, () => {
|
||||
this.onGrabEnd();
|
||||
});
|
||||
}
|
||||
|
||||
private attachHueListeners() {
|
||||
this.attachGrabListeners(this.elements.hue, () => {
|
||||
attachGrabListeners(this.elements.hue as any, () => {
|
||||
this.onGrabStart();
|
||||
this.hueRect = this.elements.hue.getBoundingClientRect();
|
||||
//this.hueDraggerRect = this.elements.hueDragger.getBoundingClientRect();
|
||||
}, (pos) => {
|
||||
this.hueHandler(pos.x);
|
||||
}, null);
|
||||
}, () => {
|
||||
this.onGrabEnd();
|
||||
});
|
||||
}
|
||||
|
||||
public setColor(color: ColorHsla | string, updateHexInput = true, updateRgbInput = true) {
|
||||
|
@ -4,10 +4,8 @@
|
||||
* https://github.com/morethanwords/tweb/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import { clamp } from "../helpers/number";
|
||||
|
||||
type SUPEREVENT = MouseEvent | TouchEvent;
|
||||
import attachGrabListeners, { GrabEvent } from "../helpers/dom/attachGrabListeners";
|
||||
|
||||
export default class RangeSelector {
|
||||
public container: HTMLDivElement;
|
||||
@ -15,12 +13,14 @@ export default class RangeSelector {
|
||||
protected seek: HTMLInputElement;
|
||||
|
||||
public mousedown = false;
|
||||
protected rect: DOMRect;
|
||||
protected _removeListeners: () => void;
|
||||
|
||||
private events: Partial<{
|
||||
//onMouseMove: ProgressLine['onMouseMove'],
|
||||
onMouseDown: RangeSelector['onMouseDown'],
|
||||
onMouseUp: RangeSelector['onMouseUp'],
|
||||
onScrub: (scrubTime: number) => void
|
||||
onScrub: (value: number) => void
|
||||
}> = {};
|
||||
|
||||
protected decimals: number;
|
||||
@ -41,10 +41,6 @@ export default class RangeSelector {
|
||||
seek.max = '' + this.max;
|
||||
seek.value = '' + value;
|
||||
|
||||
/* this.seek.addEventListener('change', (e) => {
|
||||
console.log('seek change', e);
|
||||
}); */
|
||||
|
||||
if(value) {
|
||||
this.setProgress(value);
|
||||
}
|
||||
@ -62,33 +58,33 @@ export default class RangeSelector {
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
onMouseMove = (e: SUPEREVENT) => {
|
||||
this.mousedown && this.scrub(e);
|
||||
protected onMouseMove = (event: GrabEvent) => {
|
||||
this.scrub(event);
|
||||
};
|
||||
|
||||
onMouseDown = (e: SUPEREVENT) => {
|
||||
this.scrub(e);
|
||||
protected onMouseDown = (event: GrabEvent) => {
|
||||
this.rect = this.container.getBoundingClientRect();
|
||||
this.mousedown = true;
|
||||
this.events?.onMouseDown && this.events.onMouseDown(e);
|
||||
this.scrub(event);
|
||||
this.events?.onMouseDown && this.events.onMouseDown(event);
|
||||
};
|
||||
|
||||
onMouseUp = (e: SUPEREVENT) => {
|
||||
protected onMouseUp = (event: GrabEvent) => {
|
||||
this.mousedown = false;
|
||||
this.events?.onMouseUp && this.events.onMouseUp(e);
|
||||
this.events?.onMouseUp && this.events.onMouseUp(event);
|
||||
};
|
||||
|
||||
public setListeners() {
|
||||
this.container.addEventListener('mousemove', this.onMouseMove);
|
||||
this.container.addEventListener('mousedown', this.onMouseDown);
|
||||
this.container.addEventListener('mouseup', this.onMouseUp);
|
||||
|
||||
if(isTouchSupported) {
|
||||
this.container.addEventListener('touchmove', this.onMouseMove, {passive: true});
|
||||
this.container.addEventListener('touchstart', this.onMouseDown, {passive: true});
|
||||
this.container.addEventListener('touchend', this.onMouseUp, {passive: true});
|
||||
}
|
||||
this.seek.addEventListener('input', this.onInput);
|
||||
this._removeListeners = attachGrabListeners(this.container, this.onMouseDown, this.onMouseMove, this.onMouseUp);
|
||||
}
|
||||
|
||||
public onInput = () => {
|
||||
const value = +this.seek.value;
|
||||
this.setFilled(value);
|
||||
this.events?.onScrub && this.events.onScrub(value);
|
||||
};
|
||||
|
||||
public setProgress(value: number) {
|
||||
this.setFilled(value);
|
||||
this.seek.value = '' + value;
|
||||
@ -97,50 +93,40 @@ export default class RangeSelector {
|
||||
public setFilled(value: number) {
|
||||
let percents = (value - this.min) / (this.max - this.min);
|
||||
percents = clamp(percents, 0, 1);
|
||||
//console.log('setFilled', percents, value);
|
||||
|
||||
this.filled.style.width = (percents * 100) + '%';
|
||||
//this.filled.style.transform = 'scaleX(' + scaleX + ')';
|
||||
}
|
||||
|
||||
protected scrub(e: SUPEREVENT) {
|
||||
let offsetX: number;
|
||||
const rect = (e.target as HTMLElement).getBoundingClientRect();
|
||||
if(e instanceof MouseEvent) {
|
||||
offsetX = e.pageX - Math.round(rect.left);
|
||||
} else { // touch
|
||||
offsetX = e.targetTouches[0].pageX - Math.round(rect.left);
|
||||
}
|
||||
protected scrub(event: GrabEvent) {
|
||||
const offsetX = clamp(event.x - this.rect.left, 0, this.rect.width);
|
||||
|
||||
let value = this.min + (offsetX / Math.round(rect.width) * (this.max - this.min));
|
||||
let value = this.min + (offsetX / this.rect.width * (this.max - this.min));
|
||||
|
||||
if((value - this.min) < ((this.max - this.min) / 2)) {
|
||||
value -= this.step / 10;
|
||||
}
|
||||
|
||||
//console.log('scrub value:', value, this.decimals, offsetX, rect.width, e);
|
||||
value = +value.toFixed(this.decimals);
|
||||
//const dotIndex = ('' + value).indexOf('.');
|
||||
//value = +('' + value).slice(0, this.decimals ? dotIndex + this.decimals : dotIndex);
|
||||
|
||||
value = clamp(value, this.min, this.max);
|
||||
|
||||
this.setFilled(value);
|
||||
//this.seek.value = '' + value;
|
||||
//this.onInput();
|
||||
|
||||
this.setProgress(value);
|
||||
this.events?.onScrub && this.events.onScrub(value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
public removeListeners() {
|
||||
this.container.removeEventListener('mousemove', this.onMouseMove);
|
||||
this.container.removeEventListener('mousedown', this.onMouseDown);
|
||||
this.container.removeEventListener('mouseup', this.onMouseUp);
|
||||
|
||||
if(isTouchSupported) {
|
||||
this.container.removeEventListener('touchmove', this.onMouseMove);
|
||||
this.container.removeEventListener('touchstart', this.onMouseDown);
|
||||
this.container.removeEventListener('touchend', this.onMouseUp);
|
||||
if(this._removeListeners) {
|
||||
this._removeListeners();
|
||||
this._removeListeners = null;
|
||||
}
|
||||
|
||||
this.seek.removeEventListener('input', this.onInput);
|
||||
|
||||
this.events = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
61
src/helpers/dom/attachGrabListeners.ts
Normal file
61
src/helpers/dom/attachGrabListeners.ts
Normal file
@ -0,0 +1,61 @@
|
||||
export type GrabEvent = {x: number, y: number, isTouch?: boolean};
|
||||
|
||||
export default function attachGrabListeners(element: HTMLElement, onStart: (position: GrabEvent) => void, onMove: (position: GrabEvent) => void, onEnd: (position: GrabEvent) => void) {
|
||||
// * Mouse
|
||||
const onMouseMove = (event: MouseEvent) => {
|
||||
onMove({x: event.pageX, y: event.pageY});
|
||||
};
|
||||
|
||||
const onMouseUp = (event: MouseEvent) => {
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
element.addEventListener('mousedown', onMouseDown, {once: true});
|
||||
onEnd && onEnd({x: event.pageX, y: event.pageY});
|
||||
};
|
||||
|
||||
const onMouseDown = (event: MouseEvent) => {
|
||||
if(event.button !== 0) {
|
||||
element.addEventListener('mousedown', onMouseDown, {once: true});
|
||||
return;
|
||||
}
|
||||
|
||||
onStart({x: event.pageX, y: event.pageY});
|
||||
onMouseMove(event);
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
document.addEventListener('mouseup', onMouseUp, {once: true});
|
||||
};
|
||||
|
||||
element.addEventListener('mousedown', onMouseDown, {once: true});
|
||||
|
||||
// * Touch
|
||||
const onTouchMove = (event: TouchEvent) => {
|
||||
event.preventDefault();
|
||||
onMove({x: event.touches[0].clientX, y: event.touches[0].clientY, isTouch: true});
|
||||
};
|
||||
|
||||
const onTouchEnd = (event: TouchEvent) => {
|
||||
document.removeEventListener('touchmove', onTouchMove);
|
||||
element.addEventListener('touchstart', onTouchStart, {passive: true, once: true});
|
||||
onEnd && onEnd({x: event.touches[0].clientX, y: event.touches[0].clientY, isTouch: true});
|
||||
};
|
||||
|
||||
const onTouchStart = (event: TouchEvent) => {
|
||||
onStart({x: event.touches[0].clientX, y: event.touches[0].clientY, isTouch: true});
|
||||
onTouchMove(event);
|
||||
|
||||
document.addEventListener('touchmove', onTouchMove, {passive: false});
|
||||
document.addEventListener('touchend', onTouchEnd, {passive: true, once: true});
|
||||
};
|
||||
|
||||
element.addEventListener('touchstart', onTouchStart, {passive: true, once: true});
|
||||
|
||||
return () => {
|
||||
element.removeEventListener('mousedown', onMouseDown);
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
|
||||
element.removeEventListener('touchstart', onTouchStart);
|
||||
document.removeEventListener('touchmove', onTouchMove);
|
||||
document.removeEventListener('touchend', onTouchEnd);
|
||||
};
|
||||
}
|
@ -11,8 +11,6 @@ import { isTouchSupported } from "../helpers/touchSupport";
|
||||
import RangeSelector from "../components/rangeSelector";
|
||||
import { onVideoLoad } from "../helpers/files";
|
||||
|
||||
type SUPEREVENT = MouseEvent | TouchEvent;
|
||||
|
||||
export class MediaProgressLine extends RangeSelector {
|
||||
private filledLoad: HTMLDivElement;
|
||||
|
||||
@ -36,7 +34,7 @@ export class MediaProgressLine extends RangeSelector {
|
||||
this.setSeekMax();
|
||||
this.setListeners();
|
||||
this.setHandlers({
|
||||
onMouseDown: (e: SUPEREVENT) => {
|
||||
onMouseDown: () => {
|
||||
//super.onMouseDown(e);
|
||||
|
||||
//Таймер для того, чтобы стопать видео, если зажал мышку и не отпустил клик
|
||||
@ -50,7 +48,7 @@ export class MediaProgressLine extends RangeSelector {
|
||||
}, 150);
|
||||
},
|
||||
|
||||
onMouseUp: (e: SUPEREVENT) => {
|
||||
onMouseUp: () => {
|
||||
//super.onMouseUp(e);
|
||||
|
||||
if(this.stopAndScrubTimeout) {
|
||||
|
@ -7,6 +7,7 @@
|
||||
.ckin {
|
||||
&__player {
|
||||
letter-spacing: 0.02em;
|
||||
user-select: none;
|
||||
|
||||
&.ckin__fullscreen {
|
||||
position: fixed;
|
||||
|
Loading…
x
Reference in New Issue
Block a user