@ngfx/ui
Version:
Angular UI library for gaming and creative applications
260 lines (259 loc) • 11.4 kB
JavaScript
import { Directive, ElementRef, Input, HostListener } from '@angular/core';
import { NgFxController } from './../../services/controller/controller.service';
export class NgFxDraggableDirective {
constructor(_el, _controller) {
this._el = _el;
this._controller = _controller;
this._elem = _el.nativeElement;
}
ngOnInit() {
const nodeList = (((this._elem.getElementsByClassName('ngfx__handle'))));
this._touchItem = null;
this._handle = nodeList[0];
this.control.height = this._elem.clientHeight;
this.control.width = this._elem.clientWidth;
if (this.control.orient === 'is--hor') {
this.control.currentValue = 0;
this.control.position = 'translate(' + 0 + 'px' + ',' + 0 + 'px' + ')';
}
else if (this.control.orient === 'is--vert') {
this.control.currentValue = 0;
this.control.position = 'translate(' + 0 + 'px' + ',' + 0 + 'px' + ')';
}
else if (this.control.orient === 'is--joystick') {
this.control.currentValue = [0, 0];
this.control.x = this.control.y = 76;
this.control.position = 'translate(' + 76 + 'px' + ',' + 76 + 'px' + ')';
}
this._lastPos = { transform: this.control.position };
this.setActualPosition(this.control.position);
}
onMouseLeave(e) {
}
onMouseEnter(e) {
if (this.control.isActive) {
this.control.hasUserInput = true;
}
}
onTouchStart(e) {
this.control.hasUserInput = true;
this.onTouchDown(e);
}
onTouchDown(e) {
e.preventDefault();
this.control.isActive = true;
this.control.hasUserInput = true;
this._rect = this._elem.getBoundingClientRect();
this.control.height = this._elem.clientHeight;
this.control.width = this._elem.clientWidth;
this._elem.addEventListener('touchmove', this.onTouchMove.bind(this));
this._elem.addEventListener('touchend', this.onMouseUp.bind(this));
if (this._touchItem === null) {
this._touchItem = e.touches.length - 1;
}
this.control.x = e.touches[this._touchItem].pageX - this._rect.left - this._handle.clientWidth / 2;
this.control.y = e.touches[this._touchItem].pageY - this._rect.top - this._handle.clientWidth / 2;
this.setPosition(this.control.x, this.control.y);
}
onMouseDown(e) {
e.preventDefault();
this.control.isActive = true;
this.control.hasUserInput = true;
this._rect = this._elem.getBoundingClientRect();
this.control.height = this._elem.clientHeight;
this.control.width = this._elem.clientWidth;
this.control.x = e.offsetX;
this.control.y = e.offsetY;
this._elem.addEventListener('mousemove', this.onMouseMove.bind(this));
this._elem.addEventListener('mouseup', this.onMouseUp.bind(this));
window.addEventListener('mousemove', this.onMouseMove.bind(this));
window.addEventListener('mouseup', this.onMouseUp.bind(this));
this.setPosition(this.control.x, this.control.y);
}
onTouchMove(e) {
e.preventDefault();
this._handle.style.opacity = '0.8';
if (this._touchItem === null) {
this._touchItem = e.touches.length - 1;
}
this.control.x = e.touches[this._touchItem].pageX - this._rect.left - 22;
this.control.y = e.touches[this._touchItem].pageY - this._rect.top - 66;
this.setPosition(this.control.x, this.control.y);
if (this.control.orient === 'is--hor') {
this.control.currentValue = this.scale(this.control.x, 0, this.control.width - 44, (this.control.min), (this.control.max));
}
else if (this.control.orient === 'is--vert') {
this.control.currentValue = this.scale(this.control.y, 0, this.control.height - 44, (this.control.min), (this.control.max));
}
else if (this.control.orient === 'is--joystick') {
this.control.currentValue = [
this.scale(this.control.x, 0, this.control.width - 44, this.control.min[0], this.control.max[0]),
this.scale(this.control.y, 0, this.control.height - 44, this.control.min[1], this.control.max[1])
];
}
this.control.timeStamp = e.timeStamp;
this.onEvent();
}
onMouseMove(e) {
const parent = (((e.target)).parentNode);
if (!this.control.isActive) {
return;
}
if (this.control.isActive && parent === this._elem) {
this._handle.style.opacity = '0.8';
this.control.x = e.offsetX;
this.control.y = e.offsetY;
}
else {
this._handle.style.opacity = '0.8';
this.control.x = (this._elem.getBoundingClientRect().left - e.offsetX) * -1;
this.control.y = (this._elem.getBoundingClientRect().top - e.offsetY) * -1;
}
if (this.control.hasUserInput && this.control.isActive) {
this.setPosition(this.control.x, this.control.y);
if (this.control.orient === 'is--hor') {
this.control.currentValue = this.scale(this.control.x, 0, this.control.width - 44, (this.control.min), (this.control.max));
}
if (this.control.orient === 'is--vert') {
this.control.currentValue = this.scale(this.control.y, 0, this.control.height - 44, (this.control.min), (this.control.max));
}
if (this.control.orient === 'is--joystick') {
this.control.currentValue = [
this.scale(this.control.x, 0, this.control.width - 44, this.control.min[0], this.control.max[0]),
this.scale(this.control.y, 0, this.control.height - 44, this.control.min[1], this.control.max[1])
];
}
this.control.timeStamp = e.timeStamp;
this.onEvent();
}
}
onMouseUp(e) {
this.control.isActive = false;
this.control.hasUserInput = false;
this._handle.style.opacity = '0.3';
if ('ontouchstart' in document.documentElement) {
this._touchItem = null;
}
else {
this._elem.removeEventListener('mousemove', this.onMouseMove.bind(this));
this._elem.removeEventListener('mouseup', this.onMouseUp.bind(this));
}
if (this.control.orient === 'is--joystick' && this.control.snapToCenter === true) {
const center = this.getCenter([0, this.control.width - this._handle.offsetWidth], [0, this.control.height - this._handle.offsetHeight]);
this.control.x = center[0];
this.control.y = center[1];
this.setPosition(center[0], center[1]);
}
}
onTouchEnd(e) {
this.onMouseUp(e);
}
onEvent() {
if (this.control.isActive) {
this._controller.onEvent.emit({
type: 'change',
endFrame: true,
control: this.control
});
}
}
getCenter(xRange, yRange) {
const cX = xRange[1] - (xRange[1] - xRange[0]) / 2;
const cY = yRange[1] - (yRange[1] - yRange[0]) / 2;
return [cX, cY];
}
distance(dot1, dot2) {
const x1 = dot1[0];
const y1 = dot1[1];
const x2 = dot2[0];
const y2 = dot2[1];
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
}
scale(v, min, max, gmin, gmax) {
return ((v - min) / (max - min)) * (gmax - gmin) + gmin;
}
circularBounds(x, y, xRange, yRange) {
const center = this.getCenter(xRange, yRange);
const dist = this.distance([x, y], center);
const radius = xRange[1] - center[0];
if (dist <= radius) {
return [x, y];
}
else {
x = x - center[0];
y = y - center[1];
const radians = Math.atan2(y, x);
return [Math.cos(radians) * radius + center[0], Math.sin(radians) * radius + center[1]];
}
}
clamp(value, range) {
return Math.max(Math.min(value, range[1]), range[0]);
}
setActualPosition(pos) {
const transformRegex = new RegExp(/(\d+(\.\d+)?)/g);
const positions = pos.match(transformRegex);
this._handle.style.transform = 'matrix3d(1,0,0.00,0,0.00,1,0.00,0,0,0,1,0,' + positions[0] + ',' + positions[1] + ',0,1)';
}
setPosition(x, y) {
if (this.control.orient === 'is--joystick') {
this._joystickPos = this.circularBounds(this.control.x, this.control.y, [0, this.control.width - this._handle.offsetWidth], [0, this.control.height - this._handle.offsetHeight]);
this.control.x = this.clamp(this._joystickPos[0], [0, this.control.width - this._handle.offsetWidth]);
this.control.y = this.clamp(this._joystickPos[1], [0, this.control.height - this._handle.offsetHeight]);
this.control.position = 'translate(' + this.control.x + 'px' + ',' + this.control.y + 'px' + ')';
this.setActualPosition(this.control.position);
}
else {
if (x <= 0) {
this.control.x = 0;
}
else if (x > this._elem.clientWidth - this._handle.offsetWidth) {
this.control.x = this._elem.clientWidth - this._handle.offsetWidth;
}
else {
this.control.x = x;
}
if (y <= 0) {
this.control.y = 0;
}
else if (y > this._elem.clientHeight - this._handle.offsetHeight) {
this.control.y = this._elem.clientHeight - this._handle.offsetHeight;
}
else {
this.control.y = y;
}
this.control.position = 'translate(' + this.control.x + 'px' + ',' + this.control.y + 'px' + ')';
this.setActualPosition(this.control.position);
}
}
}
NgFxDraggableDirective.decorators = [
{ type: Directive, args: [{
selector: '[ngfxDraggable]'
},] },
];
NgFxDraggableDirective.ctorParameters = () => [
{ type: ElementRef },
{ type: NgFxController }
];
NgFxDraggableDirective.propDecorators = {
control: [{ type: Input, args: ['control',] }],
onMouseLeave: [{ type: HostListener, args: ['mouseleave', ['$event'],] }],
onMouseEnter: [{ type: HostListener, args: ['mouseenter', ['$event'],] }],
onTouchStart: [{ type: HostListener, args: ['touchstart', ['$event'],] }],
onMouseDown: [{ type: HostListener, args: ['mousedown', ['$event'],] }],
onMouseUp: [{ type: HostListener, args: ['mouseup', ['$event'],] }],
onTouchEnd: [{ type: HostListener, args: ['touchend', ['$event'],] }]
};
if (false) {
NgFxDraggableDirective.prototype._rect;
NgFxDraggableDirective.prototype._joystickPos;
NgFxDraggableDirective.prototype._touchItem;
NgFxDraggableDirective.prototype._elem;
NgFxDraggableDirective.prototype._handle;
NgFxDraggableDirective.prototype._timeout;
NgFxDraggableDirective.prototype._animation;
NgFxDraggableDirective.prototype._lastPos;
NgFxDraggableDirective.prototype.control;
NgFxDraggableDirective.prototype._el;
NgFxDraggableDirective.prototype._controller;
}