Skip to content

Commit

Permalink
feat: improve transforms, add resize events
Browse files Browse the repository at this point in the history
  • Loading branch information
Matt Lewis committed Jun 6, 2016
1 parent 0a1e9d4 commit 0959a12
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 61 deletions.
20 changes: 13 additions & 7 deletions demo/demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,28 @@ import {Resizable} from './../angular2-resizable';
styles: [`
.rectangle {
position: relative;
top: 100px;
top: 200px;
display: flex;
align-items: center;
justify-content: center;
width: 300px;
height: 150px;
background-color: #FD4140;
border: solid 1px #121621;
margin: auto;
display: flex;
align-items: center;
justify-content: center;
color: #121621;
margin: auto;
}
`],
template: `
<div class="text-center">
<div class="rectangle" mwl-resizeable>Resize me!</div>
<div class="rectangle" mwl-resizeable (onResizeEnd)="log($event)">Resize me!</div>
</div>
`
})
export class DemoApp {}
export class DemoApp {

log(value: any): void {
console.log(value);
}

}
140 changes: 86 additions & 54 deletions src/resizable.directive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,13 @@ import {
HostListener,
Renderer,
ElementRef,
OnInit
OnInit,
Output,
EventEmitter
} from '@angular/core';
import {Subject} from 'rxjs';
import {Observable} from 'rxjs/Observable';

const isNumberCloseTo: Function = (value1: number, value2: number, precision: number = 3): boolean => {
const diff: number = Math.abs(value1 - value2);
return diff < precision;
};

interface Edges {
top?: boolean;
bottom?: boolean;
Expand All @@ -29,11 +26,49 @@ interface BoundingRectangle {
width?: number;
}

const isNumberCloseTo: Function = (value1: number, value2: number, precision: number = 3): boolean => {
const diff: number = Math.abs(value1 - value2);
return diff < precision;
};

const getNewBoundingRectangle: Function =
(startingRect: BoundingRectangle, edges: Edges, mouseX: number, mouseY: number): BoundingRectangle => {

const newBoundingRect: BoundingRectangle = {
top: startingRect.top,
bottom: startingRect.bottom,
left: startingRect.left,
right: startingRect.right
};

if (edges.top) {
newBoundingRect.top += mouseY;
}
if (edges.bottom) {
newBoundingRect.bottom += mouseY;
}
if (edges.left) {
newBoundingRect.left += mouseX;
}
if (edges.right) {
newBoundingRect.right += mouseX;
}
newBoundingRect.height = newBoundingRect.bottom - newBoundingRect.top;
newBoundingRect.width = newBoundingRect.right - newBoundingRect.left;

return newBoundingRect;

};

@Directive({
selector: '[mwl-resizeable]'
})
export class Resizable implements OnInit {

@Output() onResizeStart: EventEmitter<Object> = new EventEmitter();
@Output() onResize: EventEmitter<Object> = new EventEmitter();
@Output() onResizeEnd: EventEmitter<Object> = new EventEmitter();

private mouseup: Subject<any> = new Subject();
private mousedown: Subject<any> = new Subject();
private mousemove: Subject<any> = new Subject();
Expand Down Expand Up @@ -69,75 +104,72 @@ export class Resizable implements OnInit {
mousedrag.subscribe(({mouseX, mouseY}) => {
if (currentResize) {

const newBoundingRect: BoundingRectangle = {
top: currentResize.startingRect.top,
bottom: currentResize.startingRect.bottom,
left: currentResize.startingRect.left,
right: currentResize.startingRect.right
};

if (currentResize.edges.top) {
newBoundingRect.top += mouseY;
}
if (currentResize.edges.bottom) {
newBoundingRect.bottom += mouseY;
}
if (currentResize.edges.left) {
newBoundingRect.left += mouseX;
}
if (currentResize.edges.right) {
newBoundingRect.right += mouseX;
}
newBoundingRect.height = newBoundingRect.bottom - newBoundingRect.top;
newBoundingRect.width = newBoundingRect.right - newBoundingRect.left;
const newBoundingRect: BoundingRectangle = getNewBoundingRectangle(currentResize.startingRect, currentResize.edges, mouseX, mouseY);

let translateY: number = (newBoundingRect.top - currentResize.startingRect.top);
let translateX: number = (newBoundingRect.left - currentResize.startingRect.left);

if (currentResize.previousTranslate) {
translateX += +currentResize.previousTranslate.translateX;
translateY += +currentResize.previousTranslate.translateY;
}

if (currentResize.edges.right) {
translateX += (mouseX / 2);
} else if (currentResize.edges.left) {
translateX -= (mouseX / 2);
}

if (newBoundingRect.height > 0 && newBoundingRect.width > 0) {
this.renderer.setElementStyle(this.elm.nativeElement, 'height', newBoundingRect.height + 'px');
this.renderer.setElementStyle(this.elm.nativeElement, 'width', newBoundingRect.width + 'px');
this.renderer.setElementStyle(this.elm.nativeElement, 'height', `${newBoundingRect.height}px`);
this.renderer.setElementStyle(this.elm.nativeElement, 'width', `${newBoundingRect.width}px`);
this.renderer.setElementStyle(this.elm.nativeElement, 'transform', `translate(${translateX}px, ${translateY}px)`);
}

this.onResize.emit({
edges: currentResize.edges,
rectangle: newBoundingRect
});

}
});

this.mousedown.subscribe(({mouseX, mouseY}) => {
const resizeEdges: Edges = this.getResizeEdges({mouseX, mouseY});
if (Object.keys(resizeEdges).length > 0) {
let previousTranslate: any;
const transform: string = this.elm.nativeElement.style.transform;
if (transform) {
const [, translateX, translateY]: any = transform.match(/translate\((.+)px, (.+)px\)/);
previousTranslate = {
translateX,
translateY
};
}
const startingRect: BoundingRectangle = this.elm.nativeElement.getBoundingClientRect();
currentResize = {
startCoords: {
mouseX,
mouseY
},
edges: resizeEdges,
startingRect: this.elm.nativeElement.getBoundingClientRect(),
previousTranslate
startingRect,
originalStyles: {
position: this.elm.nativeElement.style.position,
left: this.elm.nativeElement.style.left,
top: this.elm.nativeElement.style.top,
transform: this.elm.nativeElement.style.transform,
width: `${startingRect.width}px`,
height: `${startingRect.height}px`
}
};
console.log('resize started', currentResize);
this.renderer.setElementStyle(this.elm.nativeElement, 'position', 'fixed');
this.renderer.setElementStyle(this.elm.nativeElement, 'left', `${currentResize.startingRect.left}px`);
this.renderer.setElementStyle(this.elm.nativeElement, 'top', `${currentResize.startingRect.top}px`);
this.onResizeStart.emit({
edges: resizeEdges,
rectangle: startingRect
});
}
});

this.mouseup.subscribe(() => {
this.mouseup.subscribe(({mouseX, mouseY}) => {
if (currentResize) {
console.log('resize ended');
this.onResizeEnd.emit({
edges: currentResize.edges,
rectangle: getNewBoundingRectangle(
currentResize.startingRect,
currentResize.edges,
mouseX - currentResize.startCoords.mouseX,
mouseY - currentResize.startCoords.mouseY
)
});
for (let key in currentResize.originalStyles) {
const value: string = currentResize.originalStyles[key];
if (typeof value !== 'undefined') {
this.renderer.setElementStyle(this.elm.nativeElement, key, currentResize.originalStyles[key]);
}
}
currentResize = null;
}
});
Expand Down

0 comments on commit 0959a12

Please sign in to comment.