Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(FEC-10079): as a end user I would like to be able to drag to reposition floating player #9

Merged
merged 9 commits into from
Jul 26, 2020
Merged
4 changes: 4 additions & 0 deletions src/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@
.playkit-floating-container {
height: 100%;
width: 100%;
touch-action: none;
}
.playkit-floating-container.playkit-floating-active {
z-index: 9999;
position: fixed;
}
.playkit-floating-container.playkit-floating-active.draggable {
cursor: grab;
}

.playkit-floating-dismissible {
display: none;
Expand Down
78 changes: 75 additions & 3 deletions src/visibility.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import './style.css';
import {DismissibleFloatingButtonComponent} from './components/dismissible/dismissible';
import 'intersection-observer';

const DRAG_THROTTLE_MS: number = 30;
const FLOATING_DRAGGABLE_CLASS: string = 'playkit-floating-draggable';
const FLOATING_ACTIVE_CLASS: string = 'playkit-floating-active';
const FLOATING_CONTAINER_CLASS: string = 'playkit-floating-container';
const FLOATING_POSTER_CLASS: string = 'playkit-floating-poster';
Expand All @@ -14,7 +16,8 @@ const DEFUALT_FLOATING_CONFIG = {
width: '400',
marginX: '20',
marginY: '20',
dismissible: true
dismissible: true,
draggable: true
}
};

Expand All @@ -30,6 +33,8 @@ class Visibility extends BasePlugin {
_playbackStartOccurred: boolean = false;
_dismissed: boolean = false;
_isInPIP: boolean = false;
_currMousePos: {x: number, y: number} = {x: 0, y: 0};
_throttleWait: boolean = false;

/**
* The default configuration of the plugin.
Expand All @@ -50,7 +55,7 @@ class Visibility extends BasePlugin {
get: DismissibleFloatingButtonComponent,
props: {
onClose: () => {
this.handleDismissFloating();
this._handleDismissFloating();
}
}
}
Expand Down Expand Up @@ -107,9 +112,12 @@ class Visibility extends BasePlugin {
Utils.Dom.addClassName(this._floatingContainer, `${FLOATING_ACTIVE_CLASS}-${side}`);
});
}
if (this.config.floating.draggable) {
Utils.Dom.addClassName(this._floatingContainer, FLOATING_DRAGGABLE_CLASS);
}
}

handleDismissFloating() {
_handleDismissFloating() {
this._dismissed = true;
this.player.pause();
this._stopFloating();
Expand All @@ -118,13 +126,27 @@ class Visibility extends BasePlugin {
_stopFloating() {
Utils.Dom.removeClassName(this._floatingContainer, FLOATING_ACTIVE_CLASS);
Utils.Dom.removeAttribute(this._floatingContainer, 'style');
if (this.config.floating.draggable) {
this.eventManager.unlisten(this._floatingContainer, 'mousedown');
this.eventManager.unlisten(this._floatingContainer, 'touchstart');
this._stopDrag();
}
}

_startFloating() {
Utils.Dom.addClassName(this._floatingContainer, FLOATING_ACTIVE_CLASS);
Utils.Dom.setStyle(this._floatingContainer, 'height', this.config.floating.height + 'px');
Utils.Dom.setStyle(this._floatingContainer, 'width', this.config.floating.width + 'px');
Utils.Dom.setStyle(this._floatingContainer, 'margin', `${this.config.floating.marginY}px ${this.config.floating.marginX}px`);
if (this.config.floating.draggable) {
this.eventManager.listen(this._floatingContainer, 'mousedown', e => {
this._startDrag(e, 'mousemove', 'mouseup');
});
this.eventManager.listen(this._floatingContainer, 'touchstart', e => {
this.eventManager.unlisten(this._floatingContainer, 'mousedown');
this._startDrag(e, 'touchmove', 'touchend');
});
}
}

_handleVisibilityChange(entries: Array<window.IntersectionObserverEntry>) {
Expand Down Expand Up @@ -177,6 +199,56 @@ class Visibility extends BasePlugin {
this._observer = null;
this.eventManager.destroy();
}

_startDrag(e: any, moveEventName: string, endEventName: string) {
this.eventManager.listenOnce(document, endEventName, () => {
this._stopDrag();
});

// get the mouse cursor position at startup:
this._currMousePos.x = this._clientX(e);
this._currMousePos.y = this._clientY(e);

this.eventManager.listen(document, moveEventName, () => {
this._moveDrag();
});
}
_clientX(e: any): number {
return e.clientX || (e.changedTouches && e.changedTouches[0] && e.changedTouches[0].clientX);
}
_clientY(e: any): number {
return e.clientY || (e.changedTouches && e.changedTouches[0] && e.changedTouches[0].clientY);
}

_moveDrag(e: any) {
RoyBregman marked this conversation as resolved.
Show resolved Hide resolved
if (this._throttleWait) return;

e = e || window.event;
// calculate the new cursor position:
const deltaMousePosX = this._currMousePos.x - this._clientX(e);
const deltaMousePosY = this._currMousePos.y - this._clientY(e);
this._currMousePos.x = this._clientX(e);
this._currMousePos.y = this._clientY(e);
const floatingContainer = this._floatingContainer; // flow
// set the element's new position
if (floatingContainer) {
const boundClientRect = floatingContainer.getBoundingClientRect();
floatingContainer.style.top = boundClientRect.top - parseInt(floatingContainer.style.marginTop) - deltaMousePosY + 'px';
RoyBregman marked this conversation as resolved.
Show resolved Hide resolved
floatingContainer.style.left = boundClientRect.left - parseInt(floatingContainer.style.marginLeft) - deltaMousePosX + 'px';
}

// handle throttling to avoid performance issues on dragging
this._throttleWait = true;
setTimeout(() => {
this._throttleWait = false;
}, DRAG_THROTTLE_MS);
}

_stopDrag() {
// stop moving when mouse button is released:
this.eventManager.unlisten(document, 'mousemove');
this.eventManager.unlisten(document, 'touchmove');
}
}

export {Visibility};