Skip to content

Commit 00474a9

Browse files
author
Xie, Ziyu
committed
Provide [rzAspectRatio]
1 parent f504737 commit 00474a9

File tree

10 files changed

+149
-27
lines changed

10 files changed

+149
-27
lines changed

README.md

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ angular2-draggable has angular (ver >= 4.x) directives that make the DOM element
2121
+ `ngResizable`
2222

2323
# Latest Update
24+
+ 2018.06.27: 2.0.0-beta.2
25+
+ ngResizable: Provide `[rzAspectRatio]`, whether the element should be constrained to a specific aspect ratio.
26+
2427
+ 2018.06.26: 2.0.0-beta.1
2528
+ ngResizable: Provide `(rzStart)`, `(rzResizing)`, `(rzStop)` event emitters
2629
+ ngResizable: Provide `resetSize()`, `getStatus()` methods
@@ -137,22 +140,23 @@ Well you can use both directives concurrently if you wish:
137140

138141
| Input | Type | Default | Description |
139142
| ----- | ---- | ------- | ----------- |
140-
| `ngDraggable` | boolean | `true` | You can toggle the draggable capability by setting `true` or `false` |
141-
| `handle` | HTMLElement | null | Use template variable to refer to the handle element. Then only the handle element is draggable |
142-
| `zIndex` | string | null | Use it to set z-index property when element is not moving |
143-
| `zIndexMoving` | string | null | Use it to set z-index property when element is moving |
144-
| `bounds` | HTMLElemnt | null | Use it to set the boundary |
145-
| `inBounds` | boolean | `false` | Use it make element stay in the bounds |
146-
| `outOfBounds` | `{ top: boolean; bottom: boolean; right: boolean; left: boolean }` | `false` | Set it to allow element get out of bounds from the direction. Refer to [demo](https://xieziyu.github.io/angular2-draggable/#/usage/boundary) |
147-
| `position` | `{ x: number, y: number }` | `{ x:0, y:0 }` | Use it to set position offset |
148-
| `gridSize` | number | 1 | Use it for snapping to grid. Refer to [demo](https://xieziyu.github.io/angular2-draggable/#/advance/snap-grid) |
143+
| ngDraggable | boolean | `true` | You can toggle the draggable capability by setting `true` or `false` |
144+
| handle | HTMLElement | null | Use template variable to refer to the handle element. Then only the handle element is draggable |
145+
| zIndex | string | null | Use it to set z-index property when element is not moving |
146+
| zIndexMoving | string | null | Use it to set z-index property when element is moving |
147+
| bounds | HTMLElemnt | null | Use it to set the boundary |
148+
| inBounds | boolean | `false` | Use it make element stay in the bounds |
149+
| outOfBounds | `{ top: boolean; bottom: boolean; right: boolean; left: boolean }` | `false` | Set it to allow element get out of bounds from the direction. Refer to [demo](https://xieziyu.github.io/angular2-draggable/#/usage/boundary) |
150+
| position | `{ x: number, y: number }` | `{ x:0, y:0 }` | Use it to set position offset |
151+
| gridSize | number | 1 | Use it for snapping to grid. Refer to [demo](https://xieziyu.github.io/angular2-draggable/#/advance/snap-grid) |
149152

150153
+ `ngResizable` directive support following input porperties:
151154

152155
| Input | Type | Default | Description |
153156
| ----- | ---- | ------- | ----------- |
154-
| `ngResizable` | boolean | `true` | You can toggle the resizable capability by setting `true` or `false` |
155-
| `rzHandles` | string | `"e,s,se"` | Which handles can be used for resizing. Optional types in `"n,e,s,w,se,sw,ne,nw"` or `"all"` |
157+
| ngResizable | boolean | `true` | You can toggle the resizable capability by setting `true` or `false` |
158+
| rzHandles | string | `"e,s,se"` | Which handles can be used for resizing. Optional types in `"n,e,s,w,se,sw,ne,nw"` or `"all"` |
159+
| rzAspectRatio | boolean\|number | false | `boolean`: Whether the element should be constrained to a specific aspect ratio. `number`: Force the element to maintain a specific aspect ratio during resizing (width/height) |
156160

157161
## CSS:
158162
+ When `ngDraggable` is enabled on some element, `ng-draggable` class is automatically assigned to it. You can use it to customize the pointer style. For example:
@@ -170,11 +174,11 @@ Well you can use both directives concurrently if you wish:
170174
171175
| Output | $event | Description |
172176
| ------ | ------ | ----------- |
173-
| `started` | `nativeElement` of host | emitted when start dragging |
174-
| `stopped` | `nativeElement` of host | emitted when stop dragging |
175-
| `edge` | { top: boolean, right: boolean, bottom: boolean, left: boolean } | emitted after `[bounds]` is set |
176-
| `movingOffset` | { x: number, y: number } | emit position offset when moving |
177-
| `endOffset` | { x: number, y: number } | emit position offset when stop moving |
177+
| started | `nativeElement` of host | emitted when start dragging |
178+
| stopped | `nativeElement` of host | emitted when stop dragging |
179+
| edge | { top: boolean, right: boolean, bottom: boolean, left: boolean } | emitted after `[bounds]` is set |
180+
| movingOffset | { x: number, y: number } | emit position offset when moving |
181+
| endOffset | { x: number, y: number } | emit position offset when stop moving |
178182
179183
Simple example:
180184
```html
@@ -191,9 +195,9 @@ Well you can use both directives concurrently if you wish:
191195
192196
| Output | $event | description |
193197
| ------ | ------ | ----------- |
194-
| `rzStart` | `IResizeEvent` | emitted when start resizing |
195-
| `rzResizing` | `IResizeEvent` | emitted when stop resizing |
196-
| `rzStop` | `IResizeEvent` | emitted when resizing |
198+
| rzStart | `IResizeEvent` | emitted when start resizing |
199+
| rzResizing | `IResizeEvent` | emitted when stop resizing |
200+
| rzStop | `IResizeEvent` | emitted when resizing |
197201
198202
```typescript
199203
export interface IResizeEvent {

projects/angular2-draggable/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "angular2-draggable",
3-
"version": "2.0.0-beta.1",
3+
"version": "2.0.0-beta.2",
44
"peerDependencies": {
55
"@angular/common": "^6.0.0-rc.0 || ^6.0.0",
66
"@angular/core": "^6.0.0-rc.0 || ^6.0.0"

projects/angular2-draggable/src/lib/angular-resizable.directive.ts

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ export class AngularResizableDirective implements OnInit, OnChanges, OnDestroy,
2020
private _handles: { [key: string]: ResizeHandle } = {};
2121
private _handleType: string[] = [];
2222
private _handleResizing: ResizeHandle = null;
23+
24+
private _aspectRatio = 0;
2325
private _origMousePos: Position = null;
2426

2527
/** Original Size and Position */
@@ -51,6 +53,14 @@ export class AngularResizableDirective implements OnInit, OnChanges, OnDestroy,
5153
* */
5254
@Input() rzHandles: ResizeHandleType = 'e,s,se';
5355

56+
/**
57+
* Whether the element should be constrained to a specific aspect ratio.
58+
* Multiple types supported:
59+
* boolean: When set to true, the element will maintain its original aspect ratio.
60+
* number: Force the element to maintain a specific aspect ratio during resizing.
61+
*/
62+
@Input() rzAspectRatio: boolean|number = false;
63+
5464
/** emitted when start resizing */
5565
@Output() rzStart = new EventEmitter<IResizeEvent>();
5666

@@ -66,6 +76,10 @@ export class AngularResizableDirective implements OnInit, OnChanges, OnDestroy,
6676
if (changes['rzHandles'] && !changes['rzHandles'].isFirstChange()) {
6777
this.updateResizable();
6878
}
79+
80+
if (changes['rzAspectRatio'] && !changes['rzAspectRatio'].isFirstChange()) {
81+
this.updateAspectRatio();
82+
}
6983
}
7084

7185
ngOnInit() {
@@ -82,6 +96,7 @@ export class AngularResizableDirective implements OnInit, OnChanges, OnDestroy,
8296
this._initPos = Position.getCurrent(elm);
8397
this._currSize = Size.copy(this._initSize);
8498
this._currPos = Position.copy(this._initPos);
99+
this.updateAspectRatio();
85100
}
86101

87102
/** A method to reset size */
@@ -123,6 +138,20 @@ export class AngularResizableDirective implements OnInit, OnChanges, OnDestroy,
123138
}
124139
}
125140

141+
/** Use it to update aspect */
142+
private updateAspectRatio() {
143+
if (typeof this.rzAspectRatio === 'boolean') {
144+
if (this.rzAspectRatio && this._currSize.height) {
145+
this._aspectRatio = (this._currSize.width / this._currSize.height);
146+
} else {
147+
this._aspectRatio = 0;
148+
}
149+
} else {
150+
let r = Number(this.rzAspectRatio);
151+
this._aspectRatio = isNaN(r) ? 0 : r;
152+
}
153+
}
154+
126155
/** Use it to create handle divs */
127156
private createHandles() {
128157
if (!this.rzHandles) {
@@ -259,18 +288,30 @@ export class AngularResizableDirective implements OnInit, OnChanges, OnDestroy,
259288
// n, ne, nw
260289
this._currSize.height = this._origSize.height - p.y;
261290
this._currPos.y = this._origPos.y + p.y;
291+
292+
// aspect ratio
293+
this.adjustByRatio('h');
262294
} else if (this._handleResizing.type.match(/s/)) {
263295
// s, se, sw
264296
this._currSize.height = this._origSize.height + p.y;
297+
298+
// aspect ratio
299+
this.adjustByRatio('h');
265300
}
266301

267302
if (this._handleResizing.type.match(/e/)) {
268303
// e, ne, se
269304
this._currSize.width = this._origSize.width + p.x;
305+
306+
// aspect ratio
307+
this.adjustByRatio('w');
270308
} else if (this._handleResizing.type.match(/w/)) {
271309
// w, nw, sw
272310
this._currSize.width = this._origSize.width - p.x;
273311
this._currPos.x = this._origPos.x + p.x;
312+
313+
// aspect ratio
314+
this.adjustByRatio('w');
274315
}
275316

276317
this.doResize();
@@ -283,4 +324,14 @@ export class AngularResizableDirective implements OnInit, OnChanges, OnDestroy,
283324
this.renderer.setStyle(container, 'left', this._currPos.x + 'px');
284325
this.renderer.setStyle(container, 'top', this._currPos.y + 'px');
285326
}
327+
328+
private adjustByRatio(d: string) {
329+
if (this._aspectRatio) {
330+
if (d === 'w') {
331+
this._currSize.height = this._currSize.width / this._aspectRatio;
332+
} else {
333+
this._currSize.width = this._aspectRatio * this._currSize.height;
334+
}
335+
}
336+
}
286337
}

src/app/_nav.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,17 @@ export const navigation = [
5959
{
6060
name: 'Default',
6161
url: '/resizable/default',
62-
icon: 'fa fa-arrows-v',
63-
badge: {
64-
variant: 'success',
65-
text: 'new'
66-
}
62+
icon: 'fa fa-arrows-v'
6763
},
6864
{
6965
name: 'Events',
7066
url: '/resizable/events',
71-
icon: 'fa fa-comment',
67+
icon: 'fa fa-comment'
68+
},
69+
{
70+
name: 'Aspect Ratio',
71+
url: '/resizable/aspect-ratio',
72+
icon: 'fa fa-square-o',
7273
badge: {
7374
variant: 'success',
7475
text: 'new'

src/app/views/resizable-demo/resizable-demo-routing.module.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { NgModule } from '@angular/core';
22
import { Routes, RouterModule } from '@angular/router';
33
import { ResizeDefaultDemoComponent } from './resize-default-demo/resize-default-demo.component';
44
import { ResizeEventDemoComponent } from './resize-event-demo/resize-event-demo.component';
5+
import { ResizeAspectRatioDemoComponent } from './resize-aspect-ratio-demo/resize-aspect-ratio-demo.component';
56

67

78
const routes: Routes = [
@@ -19,6 +20,13 @@ const routes: Routes = [
1920
title: 'Events'
2021
}
2122
},
23+
{
24+
path: 'aspect-ratio',
25+
component: ResizeAspectRatioDemoComponent,
26+
data: {
27+
title: 'Aspect Ratio'
28+
}
29+
},
2230
];
2331

2432
@NgModule({

src/app/views/resizable-demo/resizable-demo.module.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { SharedModule } from '../shared/shared.module';
55
import { ResizableDemoRoutingModule } from './resizable-demo-routing.module';
66
import { ResizeDefaultDemoComponent } from './resize-default-demo/resize-default-demo.component';
77
import { ResizeEventDemoComponent } from './resize-event-demo/resize-event-demo.component';
8+
import { ResizeAspectRatioDemoComponent } from './resize-aspect-ratio-demo/resize-aspect-ratio-demo.component';
89

910
@NgModule({
1011
imports: [
@@ -14,7 +15,8 @@ import { ResizeEventDemoComponent } from './resize-event-demo/resize-event-demo.
1415
],
1516
declarations: [
1617
ResizeDefaultDemoComponent,
17-
ResizeEventDemoComponent
18+
ResizeEventDemoComponent,
19+
ResizeAspectRatioDemoComponent
1820
]
1921
})
2022
export class ResizableDemoModule { }
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<div class="row">
2+
<div class="col" style="min-height: 200px;">
3+
<div ngResizable class="resizable-widget" [rzAspectRatio]="aspectRatio">
4+
<h4 class="widget-header">Resizable</h4>
5+
</div>
6+
</div>
7+
</div>
8+
9+
<!-- Controls -->
10+
<div class="row mt-4">
11+
<div class="col">
12+
<div>
13+
<button class="btn btn-outline-primary" (click)="aspectRatio = !aspectRatio">Toggle Aspect Ratio</button>
14+
</div>
15+
</div>
16+
</div>
17+
18+
<!-- Documents -->
19+
<div class="row mt-4">
20+
<div class="col">
21+
<tabset>
22+
<tab heading="html">
23+
<markdown [data]="demo_html | language: 'html'"></markdown>
24+
</tab>
25+
<tab heading="component">
26+
<markdown [data]="demo_ts | language: 'typescript'"></markdown>
27+
</tab>
28+
</tabset>
29+
</div>
30+
</div>

src/app/views/resizable-demo/resize-aspect-ratio-demo/resize-aspect-ratio-demo.component.scss

Whitespace-only changes.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { Component, OnInit } from '@angular/core';
2+
3+
declare const require: any;
4+
5+
@Component({
6+
selector: 'app-resize-aspect-ratio-demo',
7+
templateUrl: './resize-aspect-ratio-demo.component.html',
8+
styleUrls: ['./resize-aspect-ratio-demo.component.scss']
9+
})
10+
export class ResizeAspectRatioDemoComponent implements OnInit {
11+
demo_html = require('!!html-loader!./resize-aspect-ratio-demo.component.html');
12+
demo_ts = require('!!raw-loader!./resize-aspect-ratio-demo.component.ts');
13+
14+
aspectRatio = true;
15+
16+
constructor() { }
17+
18+
ngOnInit() {
19+
}
20+
21+
}

src/assets/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 2.0.0-beta.2 (2018-06-27)
2+
3+
#### New
4+
+ ngResizable: Provide `[rzAspectRatio]`, whether the element should be constrained to a specific aspect ratio.
5+
16
## 2.0.0-beta.1 (2018-06-26)
27

38
#### New

0 commit comments

Comments
 (0)