feat: Add smart min/max behavior to custom controls
Improve custom controls example with intelligent button behavior: - Minus buttons disabled when at minimum (initial state) - Plus buttons reset to minimum when at maximum - Prevents going below min values - Provides intuitive UX with disabled states Implementation: - Added computed signals: isZoomAtMin, isBrightnessAtMin, isBrightnessAtMax - Created handler methods: handleZoomIn/Out, handleBrightnessIn/Out - Handlers check limits and reset when appropriate - Template binds [disabled] to computed signals Benefits: - Users can't accidentally go below minimum - Easy reset from maximum with single click - Clear visual feedback via disabled buttons - Clean pattern for custom toolbar integration
This commit is contained in:
parent
757197fe26
commit
3991058265
3 changed files with 115 additions and 21 deletions
64
README.md
64
README.md
|
|
@ -241,10 +241,10 @@ export class BrightnessControlsComponent {
|
||||||
|
|
||||||
### Custom Controls with Plus/Minus Buttons
|
### Custom Controls with Plus/Minus Buttons
|
||||||
|
|
||||||
Build your own custom UI by disabling default controls and using the public methods:
|
Build your own custom UI by disabling default controls and using the public methods with smart min/max behavior:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { Component, viewChild, signal } from '@angular/core';
|
import { Component, viewChild, signal, computed } from '@angular/core';
|
||||||
import { PinchZoomComponent } from '@brianpooe/ngx-pinch-zoom';
|
import { PinchZoomComponent } from '@brianpooe/ngx-pinch-zoom';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
|
|
@ -265,10 +265,10 @@ import { PinchZoomComponent } from '@brianpooe/ngx-pinch-zoom';
|
||||||
</pinch-zoom>
|
</pinch-zoom>
|
||||||
|
|
||||||
<div class="custom-controls">
|
<div class="custom-controls">
|
||||||
<button (click)="zoomOut()">Zoom -</button>
|
<button [disabled]="isZoomAtMin()" (click)="handleZoomOut()">Zoom -</button>
|
||||||
<button (click)="zoomIn()">Zoom +</button>
|
<button (click)="handleZoomIn()">Zoom +</button>
|
||||||
<button (click)="brightnessOut()">Brightness -</button>
|
<button [disabled]="isBrightnessAtMin()" (click)="handleBrightnessOut()">Brightness -</button>
|
||||||
<button (click)="brightnessIn()">Brightness +</button>
|
<button (click)="handleBrightnessIn()">Brightness +</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Zoom: {{ zoomLevel() }} | Brightness: {{ brightnessLevel() }}</p>
|
<p>Zoom: {{ zoomLevel() }} | Brightness: {{ brightnessLevel() }}</p>
|
||||||
|
|
@ -280,20 +280,51 @@ export class CustomControlsComponent {
|
||||||
zoomLevel = signal(1);
|
zoomLevel = signal(1);
|
||||||
brightnessLevel = signal(1.0);
|
brightnessLevel = signal(1.0);
|
||||||
|
|
||||||
zoomIn() {
|
// Min/max constants
|
||||||
this.pinchZoom()?.zoomIn(0.5);
|
private readonly MIN_ZOOM = 1;
|
||||||
|
private readonly MIN_BRIGHTNESS = 1.0;
|
||||||
|
private readonly MAX_BRIGHTNESS = 2.0;
|
||||||
|
|
||||||
|
// Computed signals for button states
|
||||||
|
isZoomAtMin = computed(() => this.zoomLevel() <= this.MIN_ZOOM);
|
||||||
|
isBrightnessAtMin = computed(() => this.brightnessLevel() <= this.MIN_BRIGHTNESS);
|
||||||
|
|
||||||
|
// Smart handlers with min/max and reset behavior
|
||||||
|
handleZoomIn() {
|
||||||
|
const pinch = this.pinchZoom();
|
||||||
|
if (!pinch) return;
|
||||||
|
|
||||||
|
const maxScale = pinch.maxScale();
|
||||||
|
if (this.zoomLevel() >= maxScale) {
|
||||||
|
// At max, reset to min
|
||||||
|
pinch.destroy();
|
||||||
|
} else {
|
||||||
|
pinch.zoomIn(0.5);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
zoomOut() {
|
handleZoomOut() {
|
||||||
this.pinchZoom()?.zoomOut(0.5);
|
const pinch = this.pinchZoom();
|
||||||
|
if (!pinch || this.isZoomAtMin()) return;
|
||||||
|
pinch.zoomOut(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
brightnessIn() {
|
handleBrightnessIn() {
|
||||||
this.pinchZoom()?.brightnessIn();
|
const pinch = this.pinchZoom();
|
||||||
|
if (!pinch) return;
|
||||||
|
|
||||||
|
if (this.brightnessLevel() >= this.MAX_BRIGHTNESS) {
|
||||||
|
// At max, reset to normal
|
||||||
|
pinch.resetBrightness();
|
||||||
|
} else {
|
||||||
|
pinch.brightnessIn();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
brightnessOut() {
|
handleBrightnessOut() {
|
||||||
this.pinchZoom()?.brightnessOut();
|
const pinch = this.pinchZoom();
|
||||||
|
if (!pinch || this.isBrightnessAtMin()) return;
|
||||||
|
pinch.brightnessOut();
|
||||||
}
|
}
|
||||||
|
|
||||||
onZoomChange(scale: number) {
|
onZoomChange(scale: number) {
|
||||||
|
|
@ -306,6 +337,11 @@ export class CustomControlsComponent {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**Smart Control Behavior:**
|
||||||
|
- **Minus buttons**: Disabled when at minimum value (initial state), prevent going below min
|
||||||
|
- **Plus buttons**: When at maximum value, clicking resets to minimum instead of being disabled
|
||||||
|
- This pattern provides intuitive UX - users can't accidentally go below min, and can easily reset from max
|
||||||
|
|
||||||
## Configuration Options
|
## Configuration Options
|
||||||
|
|
||||||
| Input | Type | Default | Description |
|
| Input | Type | Default | Description |
|
||||||
|
|
|
||||||
|
|
@ -371,8 +371,9 @@
|
||||||
<div class="demo">
|
<div class="demo">
|
||||||
<h2>Custom Zoom & Brightness Controls</h2>
|
<h2>Custom Zoom & Brightness Controls</h2>
|
||||||
<p>
|
<p>
|
||||||
Build your own custom control UI using the component's public methods. This example demonstrates plus/minus buttons for both zoom
|
Build your own custom control UI using the component's public methods. This example demonstrates plus/minus buttons with smart
|
||||||
and brightness, with default controls disabled. Perfect for integrating controls into your own toolbar or UI layout.
|
behavior: minus buttons are disabled when at minimum (initial state), plus buttons reset to minimum when at maximum. Perfect for
|
||||||
|
integrating controls into your own toolbar or UI layout.
|
||||||
</p>
|
</p>
|
||||||
<p>Zoom State: {{ zoomstate() }} | Brightness State: {{ brightnessstate().toFixed(2) }}</p>
|
<p>Zoom State: {{ zoomstate() }} | Brightness State: {{ brightnessstate().toFixed(2) }}</p>
|
||||||
<pinch-zoom
|
<pinch-zoom
|
||||||
|
|
@ -389,10 +390,12 @@
|
||||||
/>
|
/>
|
||||||
</pinch-zoom>
|
</pinch-zoom>
|
||||||
<div class="actions">
|
<div class="actions">
|
||||||
<button class="btn btn-small btn-blue btn-rounded" (click)="customPinch.zoomOut(0.5)">Zoom -</button>
|
<button class="btn btn-small btn-blue btn-rounded" [disabled]="isZoomAtMin()" (click)="handleZoomOut()">Zoom -</button>
|
||||||
<button class="btn btn-small btn-blue btn-rounded" (click)="customPinch.zoomIn(0.5)">Zoom +</button>
|
<button class="btn btn-small btn-blue btn-rounded" (click)="handleZoomIn()">Zoom +</button>
|
||||||
<button class="btn btn-small btn-green btn-rounded" (click)="customPinch.brightnessOut()">Brightness -</button>
|
<button class="btn btn-small btn-green btn-rounded" [disabled]="isBrightnessAtMin()" (click)="handleBrightnessOut()">
|
||||||
<button class="btn btn-small btn-green btn-rounded" (click)="customPinch.brightnessIn()">Brightness +</button>
|
Brightness -
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-small btn-green btn-rounded" (click)="handleBrightnessIn()">Brightness +</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { Component, signal } from '@angular/core';
|
import { Component, signal, computed, viewChild } from '@angular/core';
|
||||||
import { PinchZoomComponent } from '@brianpooe/ngx-pinch-zoom';
|
import { PinchZoomComponent } from '@brianpooe/ngx-pinch-zoom';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -19,6 +19,19 @@ export class AppComponent {
|
||||||
zoomstate = signal(1);
|
zoomstate = signal(1);
|
||||||
brightnessstate = signal(1.0);
|
brightnessstate = signal(1.0);
|
||||||
|
|
||||||
|
// Reference to custom controls pinch-zoom instance
|
||||||
|
customPinch = viewChild<PinchZoomComponent>('customPinch');
|
||||||
|
|
||||||
|
// Custom controls configuration
|
||||||
|
private readonly MIN_ZOOM = 1;
|
||||||
|
private readonly MIN_BRIGHTNESS = 1.0;
|
||||||
|
private readonly MAX_BRIGHTNESS = 2.0;
|
||||||
|
|
||||||
|
// Computed signals for button states
|
||||||
|
isZoomAtMin = computed(() => this.zoomstate() <= this.MIN_ZOOM);
|
||||||
|
isBrightnessAtMin = computed(() => this.brightnessstate() <= this.MIN_BRIGHTNESS);
|
||||||
|
isBrightnessAtMax = computed(() => this.brightnessstate() >= this.MAX_BRIGHTNESS);
|
||||||
|
|
||||||
onZoomChanged(zoom: number): void {
|
onZoomChanged(zoom: number): void {
|
||||||
this.zoomstate.set(zoom);
|
this.zoomstate.set(zoom);
|
||||||
}
|
}
|
||||||
|
|
@ -26,4 +39,46 @@ export class AppComponent {
|
||||||
onBrightnessChanged(brightness: number): void {
|
onBrightnessChanged(brightness: number): void {
|
||||||
this.brightnessstate.set(brightness);
|
this.brightnessstate.set(brightness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Custom control handlers with min/max and reset behavior
|
||||||
|
handleZoomIn(): void {
|
||||||
|
const pinch = this.customPinch();
|
||||||
|
if (!pinch) return;
|
||||||
|
|
||||||
|
const maxScale = pinch.maxScale();
|
||||||
|
const currentScale = this.zoomstate();
|
||||||
|
|
||||||
|
if (currentScale >= maxScale) {
|
||||||
|
// At max, reset to min
|
||||||
|
pinch.destroy();
|
||||||
|
} else {
|
||||||
|
pinch.zoomIn(0.5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleZoomOut(): void {
|
||||||
|
const pinch = this.customPinch();
|
||||||
|
if (!pinch || this.isZoomAtMin()) return;
|
||||||
|
|
||||||
|
pinch.zoomOut(0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBrightnessIn(): void {
|
||||||
|
const pinch = this.customPinch();
|
||||||
|
if (!pinch) return;
|
||||||
|
|
||||||
|
if (this.isBrightnessAtMax()) {
|
||||||
|
// At max, reset to normal (1.0)
|
||||||
|
pinch.resetBrightness();
|
||||||
|
} else {
|
||||||
|
pinch.brightnessIn();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleBrightnessOut(): void {
|
||||||
|
const pinch = this.customPinch();
|
||||||
|
if (!pinch || this.isBrightnessAtMin()) return;
|
||||||
|
|
||||||
|
pinch.brightnessOut();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue