Browse Source

Fix range selector

master
Eduard Kuzmenko 3 years ago
parent
commit
b6a9c02c5c
  1. 66
      src/components/colorPicker.ts
  2. 82
      src/components/rangeSelector.ts
  3. 61
      src/helpers/dom/attachGrabListeners.ts
  4. 6
      src/lib/mediaPlayer.ts
  5. 1
      src/scss/partials/_ckin.scss

66
src/components/colorPicker.ts

@ -1,8 +1,8 @@ @@ -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 { @@ -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 { @@ -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) {

82
src/components/rangeSelector.ts

@ -4,10 +4,8 @@ @@ -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 { @@ -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 { @@ -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 { @@ -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 { @@ -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

@ -0,0 +1,61 @@ @@ -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);
};
}

6
src/lib/mediaPlayer.ts

@ -11,8 +11,6 @@ import { isTouchSupported } from "../helpers/touchSupport"; @@ -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 { @@ -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 { @@ -50,7 +48,7 @@ export class MediaProgressLine extends RangeSelector {
}, 150);
},
onMouseUp: (e: SUPEREVENT) => {
onMouseUp: () => {
//super.onMouseUp(e);
if(this.stopAndScrubTimeout) {

1
src/scss/partials/_ckin.scss

@ -7,6 +7,7 @@ @@ -7,6 +7,7 @@
.ckin {
&__player {
letter-spacing: 0.02em;
user-select: none;
&.ckin__fullscreen {
position: fixed;

Loading…
Cancel
Save