docs: Add comprehensive click-to-zoom documentation
Add real-world implementation example of click-to-zoom feature to maintainer documentation: **IMPLEMENTATION_GUIDE.md:** - Complete step-by-step implementation guide showing how click-to-zoom was added - Explains each component (input signals, IvyPinch method, template, CSS) - Includes code snippets from actual implementation - Shows real-world usage for anomaly detection use case - Provides testing checklist **docs/README.md:** - Added click-to-zoom to "Where do I find...?" quick reference table - Added to "How do I...?" task guide - Helps maintainers quickly locate click-to-zoom documentation This serves as a template for future feature additions and helps maintainers understand how to add similar interactive features to the library.
This commit is contained in:
parent
1b7ed5adff
commit
dcc0f95818
2 changed files with 179 additions and 0 deletions
|
|
@ -473,6 +473,183 @@ ngOnDestroy(): void {
|
||||||
6. Compare snapshots
|
6. Compare snapshots
|
||||||
7. Verify no PinchZoomComponent instances retained
|
7. Verify no PinchZoomComponent instances retained
|
||||||
|
|
||||||
|
### Feature: Click-to-Zoom (Real-World Example)
|
||||||
|
|
||||||
|
This is a complete, real implementation added to the library for anomaly detection and defect inspection use cases.
|
||||||
|
|
||||||
|
**Goal**: Allow users to click any point on the image to zoom to that exact location, perfect for quickly examining suspicious areas in images.
|
||||||
|
|
||||||
|
#### Step 1: Add Input Signals
|
||||||
|
|
||||||
|
**File: `pinch-zoom.component.ts`**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export class PinchZoomComponent implements OnInit, OnDestroy {
|
||||||
|
// ... existing inputs
|
||||||
|
|
||||||
|
// Click-to-zoom inputs
|
||||||
|
enableClickToZoom = input<boolean>(false);
|
||||||
|
clickToZoomScale = input<number>(2.5);
|
||||||
|
|
||||||
|
// ... rest of class
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why this works**:
|
||||||
|
|
||||||
|
- `enableClickToZoom` - Feature flag to avoid interfering with existing functionality
|
||||||
|
- `clickToZoomScale` - Configurable zoom level (default 2.5x is good for defect inspection)
|
||||||
|
|
||||||
|
#### Step 2: Add zoomToPoint Method to IvyPinch
|
||||||
|
|
||||||
|
**File: `ivypinch.ts`**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export class IvyPinch {
|
||||||
|
// Add after zoomOut() method
|
||||||
|
|
||||||
|
public zoomToPoint(clientX: number, clientY: number, targetScale: number): void {
|
||||||
|
// Update element position
|
||||||
|
this.getElementPosition();
|
||||||
|
|
||||||
|
// Calculate the click point relative to the element
|
||||||
|
const xRelativeToElement = clientX - this.elementPosition.left;
|
||||||
|
const yRelativeToElement = clientY - this.elementPosition.top;
|
||||||
|
|
||||||
|
// Clamp target scale to limits
|
||||||
|
let newScale = targetScale;
|
||||||
|
if (newScale > this.maxScale) {
|
||||||
|
newScale = this.maxScale;
|
||||||
|
}
|
||||||
|
if (newScale < (this.properties.minScale || 0)) {
|
||||||
|
newScale = this.properties.minScale || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If already at target scale or zoomed in, reset zoom
|
||||||
|
if (this.scale >= targetScale || this.scale > 1) {
|
||||||
|
this.resetScale();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the new position to keep the clicked point centered
|
||||||
|
this.scale = newScale;
|
||||||
|
this.zoomChanged(this.scale);
|
||||||
|
|
||||||
|
// Calculate the zoom offset to keep clicked point under cursor
|
||||||
|
const scaleRatio = newScale / this.initialScale;
|
||||||
|
this.moveX = this.initialMoveX - xRelativeToElement * (scaleRatio - 1);
|
||||||
|
this.moveY = this.initialMoveY - yRelativeToElement * (scaleRatio - 1);
|
||||||
|
|
||||||
|
this.centeringImage();
|
||||||
|
this.updateInitialValues();
|
||||||
|
this.transformElement(this.properties.transitionDuration || 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key points**:
|
||||||
|
|
||||||
|
- Uses `getElementPosition()` to get fresh position (element may have moved)
|
||||||
|
- Calculates click position relative to element bounds
|
||||||
|
- Applies zoom offset to keep clicked point under cursor
|
||||||
|
- Respects min/max scale limits
|
||||||
|
- Smooth animation using existing transition duration
|
||||||
|
|
||||||
|
#### Step 3: Add Component Wrapper Method
|
||||||
|
|
||||||
|
**File: `pinch-zoom.component.ts`**
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export class PinchZoomComponent implements OnInit, OnDestroy {
|
||||||
|
// ... existing methods
|
||||||
|
|
||||||
|
zoomToPoint(event: MouseEvent): void {
|
||||||
|
if (!this.enableClickToZoom() || this.isDisabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent default to avoid conflicts
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
// Get click coordinates
|
||||||
|
const clientX = event.clientX;
|
||||||
|
const clientY = event.clientY;
|
||||||
|
|
||||||
|
// Call IvyPinch method with target scale
|
||||||
|
this.pinchZoom?.zoomToPoint(clientX, clientY, this.clickToZoomScale());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Why this works**:
|
||||||
|
|
||||||
|
- Checks feature flag and disabled state
|
||||||
|
- Prevents event propagation to avoid conflicts with other gestures
|
||||||
|
- Delegates to IvyPinch for actual zoom logic
|
||||||
|
|
||||||
|
#### Step 4: Add Click Handler to Template
|
||||||
|
|
||||||
|
**File: `pinch-zoom.component.html`**
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div
|
||||||
|
class="pinch-zoom-content"
|
||||||
|
[class.pz-dragging]="isDragging()"
|
||||||
|
[class.pz-click-to-zoom]="enableClickToZoom()"
|
||||||
|
(click)="enableClickToZoom() ? zoomToPoint($event) : null"
|
||||||
|
>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Key points**:
|
||||||
|
|
||||||
|
- Conditional click handler (only active when enabled)
|
||||||
|
- CSS class for visual feedback (cursor changes)
|
||||||
|
- Works alongside existing touch/pan gestures
|
||||||
|
|
||||||
|
#### Step 5: Add CSS Cursor Feedback
|
||||||
|
|
||||||
|
**File: `pinch-zoom.component.sass`**
|
||||||
|
|
||||||
|
```sass
|
||||||
|
.pz-click-to-zoom
|
||||||
|
cursor: zoom-in
|
||||||
|
|
||||||
|
.pz-click-to-zoom.pz-dragging
|
||||||
|
cursor: all-scroll // Dragging takes priority
|
||||||
|
```
|
||||||
|
|
||||||
|
**UX improvement**: User knows they can click to zoom when cursor changes
|
||||||
|
|
||||||
|
#### Result
|
||||||
|
|
||||||
|
Users can now:
|
||||||
|
|
||||||
|
1. Enable click-to-zoom with `[enableClickToZoom]="true"`
|
||||||
|
2. Click any suspicious area on the image
|
||||||
|
3. Image zooms to 2.5x with clicked point centered
|
||||||
|
4. Click again to zoom out
|
||||||
|
5. Works perfectly with brightness control for defect inspection
|
||||||
|
|
||||||
|
**Real-world usage**:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<pinch-zoom [enableClickToZoom]="true" [clickToZoomScale]="2.5" [enableBrightnessControl]="true">
|
||||||
|
<img src="product-defect-scan.jpg" />
|
||||||
|
</pinch-zoom>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Testing checklist**:
|
||||||
|
|
||||||
|
- ✅ Click to zoom in to point
|
||||||
|
- ✅ Click again to zoom out
|
||||||
|
- ✅ Respects max zoom limit
|
||||||
|
- ✅ Works with pan gesture
|
||||||
|
- ✅ Cursor shows zoom-in icon
|
||||||
|
- ✅ Disabled when `disabled=true`
|
||||||
|
|
||||||
## Common Customizations
|
## Common Customizations
|
||||||
|
|
||||||
### Custom: Programmatic Zoom to Specific Point
|
### Custom: Programmatic Zoom to Specific Point
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@ docs/
|
||||||
| Why isn't pan working? | QUICK_REFERENCE.md → "Debugging Checklist" |
|
| Why isn't pan working? | QUICK_REFERENCE.md → "Debugging Checklist" |
|
||||||
| What is `transformElement()`? | ARCHITECTURE.md → "Transform Mathematics" |
|
| What is `transformElement()`? | ARCHITECTURE.md → "Transform Mathematics" |
|
||||||
| How to add rotation? | IMPLEMENTATION_GUIDE.md → "Feature: Add Rotation Support" |
|
| How to add rotation? | IMPLEMENTATION_GUIDE.md → "Feature: Add Rotation Support" |
|
||||||
|
| How click-to-zoom works? | IMPLEMENTATION_GUIDE.md → "Feature: Click-to-Zoom" |
|
||||||
| Performance best practices? | QUICK_REFERENCE.md → "Performance Tips" |
|
| Performance best practices? | QUICK_REFERENCE.md → "Performance Tips" |
|
||||||
| Event flow diagram? | ARCHITECTURE.md → "Event System" |
|
| Event flow diagram? | ARCHITECTURE.md → "Event System" |
|
||||||
|
|
||||||
|
|
@ -77,6 +78,7 @@ docs/
|
||||||
| Task | Document |
|
| Task | Document |
|
||||||
| ------------------------ | ----------------------------------------------------------------------- |
|
| ------------------------ | ----------------------------------------------------------------------- |
|
||||||
| Fix image jumping | IMPLEMENTATION_GUIDE.md → "Bug: Image Jumps on First Touch" |
|
| Fix image jumping | IMPLEMENTATION_GUIDE.md → "Bug: Image Jumps on First Touch" |
|
||||||
|
| Add click-to-zoom | IMPLEMENTATION_GUIDE.md → "Feature: Click-to-Zoom" |
|
||||||
| Add custom zoom behavior | IMPLEMENTATION_GUIDE.md → "Custom: Programmatic Zoom to Specific Point" |
|
| Add custom zoom behavior | IMPLEMENTATION_GUIDE.md → "Custom: Programmatic Zoom to Specific Point" |
|
||||||
| Debug transforms | IMPLEMENTATION_GUIDE.md → "Technique 1: Visual Transform Debugging" |
|
| Debug transforms | IMPLEMENTATION_GUIDE.md → "Technique 1: Visual Transform Debugging" |
|
||||||
| Improve performance | IMPLEMENTATION_GUIDE.md → "Performance Optimization" |
|
| Improve performance | IMPLEMENTATION_GUIDE.md → "Performance Optimization" |
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue