@h4md1/visual-image-tool 0.1.5 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # VisualImageTool
1
+ # <img src="demo/android-chrome-192x192.png" alt="Visual Image Tool logo" width="48" height="48" style="vertical-align:middle; margin-right: 0.5em; border-radius: 8px;"> Visual Image Tool
2
2
 
3
- Un outil léger en JavaScript vanilla pour définir des points focaux et zones de recadrage sur des images.
3
+ A lightweight vanilla JavaScript tool to define focus points and crop zones on images.
4
4
 
5
- ## Fonctionnalités
5
+ ## Features
6
6
 
7
- - **Point focal** : Définissez un point d'intérêt sur l'image avec un marqueur visuel
8
- - **Zone de recadrage** : Définissez une zone de recadrage avec poignées de redimensionnement
9
- - **Sans dépendances** : Fonctionne sans bibliothèques externes
10
- - **API simple** : Interface claire et facile à utiliser
11
- - **Personnalisable** : Options de configuration flexibles
12
- - **Responsive** : S'adapte aux redimensionnements d'écran
7
+ - **Focus point**: Set a point of interest on the image with a visual marker
8
+ - **Crop zone**: Define a crop zone with resize handles
9
+ - **No dependencies**: Works without external libraries
10
+ - **Simple API**: Clear and easy-to-use interface
11
+ - **Customizable**: Flexible configuration options
12
+ - **Responsive**: Adapts to screen resizing
13
13
 
14
14
  ## Installation
15
15
 
@@ -17,64 +17,68 @@ Un outil léger en JavaScript vanilla pour définir des points focaux et zones d
17
17
  npm install @h4md1/visual-image-tool
18
18
  ```
19
19
 
20
- ## Guide de démarrage rapide
20
+ ## Quick Start Guide
21
21
 
22
- ### 1. Importation
22
+ ### 1. Import
23
23
 
24
24
  ```javascript
25
- // Importation ES modules (recommandé)
25
+ // ES modules import (recommended)
26
26
  import VisualImageTool from '@h4md1/visual-image-tool';
27
27
 
28
- // OU importation CommonJS
28
+ // OR CommonJS import
29
29
  const VisualImageTool = require('@h4md1/visual-image-tool');
30
30
 
31
- // OU utilisation directe via balise script (UMD)
31
+ // OR direct usage via script tag (UMD)
32
32
  // <script src="node_modules/image-tool/dist/image-tool.umd.js"></script>
33
33
  ```
34
34
 
35
- ### 2. Initialisation
35
+ ### 2. Initialization
36
36
 
37
37
  ```javascript
38
- // Créer une instance avec une image
38
+ // Create an instance with an image
39
39
  const imageTool = new VisualImageTool.VisualImageTool({
40
40
  imageElement: document.getElementById('myImage'),
41
+ debug: true, // Enable debug logs for overlay positioning (optional)
41
42
  onChange: (data) => {
42
- console.log('Point focal:', data.focusPoint);
43
- console.log('Zone de recadrage:', data.cropZone);
43
+ console.log('Focus point:', data.focusPoint);
44
+ console.log('Crop zone:', data.cropZone);
44
45
  }
45
46
  });
46
47
  ```
47
48
 
48
- ### 3. Utilisation des fonctionnalités
49
+ ### 3. Using the Features
49
50
 
50
51
  ```javascript
51
- // Activer le point focal
52
+ // Enable the focus point
52
53
  imageTool.toggleFocusPoint(true);
53
54
 
54
- // Activer la zone de recadrage
55
+ // Enable the crop zone
55
56
  imageTool.toggleCropZone(true);
56
57
 
57
- // Définir manuellement un point focal
58
+ // Manually set a focus point
58
59
  imageTool.setFocusPoint(x, y);
59
60
 
60
- // Définir manuellement une zone de recadrage
61
+ // Manually set a crop zone
61
62
  imageTool.setCropZone(x, y, width, height);
62
63
 
63
- // Obtenir les valeurs actuelles
64
+ // Get current values
64
65
  const focusPoint = imageTool.getFocusPoint();
65
66
  const cropZone = imageTool.getCropZone();
66
67
  ```
67
68
 
68
- ## Options de configuration
69
+ ## Configuration Options
69
70
 
70
71
  ```javascript
71
72
  const imageTool = new VisualImageTool.VisualImageTool({
72
- // Élément image (obligatoire) - peut être un sélecteur CSS ou un élément DOM
73
+ // Image element (required) - can be a CSS selector or a DOM element
73
74
  imageElement: '#myImage',
74
-
75
- // Configuration du point focal (optionnel)
75
+
76
+ // Enable debug logs for overlay positioning (optional)
77
+ debug: true, // Set to true to see overlay positioning logs in the console
78
+
79
+ // Focus point configuration (optional)
76
80
  focusPoint: {
77
- enabled: true, // Activer/désactiver la fonctionnalité
81
+ enabled: true, // Enable/disable the feature
78
82
  style: {
79
83
  width: '30px',
80
84
  height: '30px',
@@ -83,10 +87,10 @@ const imageTool = new VisualImageTool.VisualImageTool({
83
87
  backgroundColor: 'rgba(255, 0, 0, 0.5)'
84
88
  }
85
89
  },
86
-
87
- // Configuration de la zone de recadrage (optionnel)
90
+
91
+ // Crop zone configuration (optional)
88
92
  cropZone: {
89
- enabled: true, // Activer/désactiver la fonctionnalité
93
+ enabled: true, // Enable/disable the feature
90
94
  style: {
91
95
  border: '1px dashed #fff',
92
96
  backgroundColor: 'rgba(0, 0, 0, 0.4)'
@@ -99,71 +103,71 @@ const imageTool = new VisualImageTool.VisualImageTool({
99
103
  boxShadow: '0 0 3px rgba(0,0,0,0.5)'
100
104
  }
101
105
  },
102
-
103
- // Callback appelé lors des changements (optionnel)
106
+
107
+ // Callback called on changes (optional)
104
108
  onChange: function(data) {
105
- // data contient focusPoint, cropZone, focusActive, cropActive
109
+ // data contains focusPoint, cropZone, focusActive, cropActive
106
110
  }
107
111
  });
108
112
  ```
109
113
 
110
- ## API complète
114
+ ## Full API
111
115
 
112
- ### Méthodes
116
+ ### Methods
113
117
 
114
118
  #### `toggleFocusPoint(active)`
115
- Active ou désactive le point focal.
116
- - `active` (boolean, optionnel): Si défini, force l'état à cette valeur. Si omis, inverse l'état actuel.
117
- - Retourne: L'instance VisualImageTool pour le chaînage.
119
+ Enables or disables the focus point.
120
+ - `active` (boolean, optional): If set, forces the state to this value. If omitted, toggles the current state.
121
+ - Returns: The VisualImageTool instance for chaining.
118
122
 
119
123
  #### `toggleCropZone(active)`
120
- Active ou désactive la zone de recadrage.
121
- - `active` (boolean, optionnel): Si défini, force l'état à cette valeur. Si omis, inverse l'état actuel.
122
- - Retourne: L'instance VisualImageTool pour le chaînage.
124
+ Enables or disables the crop zone.
125
+ - `active` (boolean, optional): If set, forces the state to this value. If omitted, toggles the current state.
126
+ - Returns: The VisualImageTool instance for chaining.
123
127
 
124
128
  #### `setFocusPoint(x, y)`
125
- Définit la position du point focal.
126
- - `x` (number): Coordonnée X en pixels originaux.
127
- - `y` (number): Coordonnée Y en pixels originaux.
128
- - Retourne: L'instance VisualImageTool pour le chaînage.
129
+ Sets the position of the focus point.
130
+ - `x` (number): X coordinate in original pixels.
131
+ - `y` (number): Y coordinate in original pixels.
132
+ - Returns: The VisualImageTool instance for chaining.
129
133
 
130
134
  #### `setCropZone(x, y, width, height)`
131
- Définit la position et les dimensions de la zone de recadrage.
132
- - `x` (number): Coordonnée X en pixels originaux.
133
- - `y` (number): Coordonnée Y en pixels originaux.
134
- - `width` (number): Largeur en pixels originaux.
135
- - `height` (number): Hauteur en pixels originaux.
136
- - Retourne: L'instance VisualImageTool pour le chaînage.
135
+ Sets the position and dimensions of the crop zone.
136
+ - `x` (number): X coordinate in original pixels.
137
+ - `y` (number): Y coordinate in original pixels.
138
+ - `width` (number): Width in original pixels.
139
+ - `height` (number): Height in original pixels.
140
+ - Returns: The VisualImageTool instance for chaining.
137
141
 
138
142
  #### `getFocusPoint()`
139
- Obtient la position actuelle du point focal.
140
- - Retourne: Un objet `{x, y}` avec les coordonnées en pixels originaux.
143
+ Gets the current position of the focus point.
144
+ - Returns: An object `{x, y}` with coordinates in original pixels.
141
145
 
142
146
  #### `getCropZone()`
143
- Obtient la position et les dimensions actuelles de la zone de recadrage.
144
- - Retourne: Un objet `{x, y, width, height}` avec les valeurs en pixels originaux.
147
+ Gets the current position and dimensions of the crop zone.
148
+ - Returns: An object `{x, y, width, height}` with values in original pixels.
145
149
 
146
150
  #### `getImageDimensions()`
147
- Obtient les dimensions originales de l'image.
148
- - Retourne: Un objet `{width, height}` avec les dimensions en pixels originaux.
151
+ Gets the original dimensions of the image.
152
+ - Returns: An object `{width, height}` with dimensions in original pixels.
149
153
 
150
154
  #### `destroy()`
151
- Détruit l'instance et nettoie les ressources.
155
+ Destroys the instance and cleans up resources.
152
156
 
153
- ### Événements
157
+ ### Events
154
158
 
155
- L'outil utilise le callback `onChange` pour notifier des changements. Ce callback reçoit un objet avec les propriétés suivantes:
159
+ The tool uses the `onChange` callback to notify about changes. This callback receives an object with the following properties:
156
160
 
157
161
  ```javascript
158
162
  {
159
- focusPoint: {x, y}, // Position du point focal
160
- cropZone: {x, y, width, height}, // Position et dimensions de la zone de recadrage
161
- focusActive: true|false, // État d'activation du point focal
162
- cropActive: true|false // État d'activation de la zone de recadrage
163
+ focusPoint: {x, y}, // Position of the focus point
164
+ cropZone: {x, y, width, height}, // Position and dimensions of the crop zone
165
+ focusActive: true|false, // Activation state of the focus point
166
+ cropActive: true|false // Activation state of the crop zone
163
167
  }
164
168
  ```
165
169
 
166
- ## Exemples d'intégration avec des frameworks
170
+ ## Integration Examples with Frameworks
167
171
 
168
172
  ### React
169
173
 
@@ -180,16 +184,16 @@ function ImageEditor() {
180
184
  toolRef.current = new VisualImageTool({
181
185
  imageElement: imageRef.current,
182
186
  onChange: (data) => {
183
- console.log('Données mises à jour:', data);
187
+ console.log('Updated data:', data);
184
188
  }
185
189
  });
186
190
 
187
- // Activer les fonctionnalités
191
+ // Enable features
188
192
  toolRef.current.toggleFocusPoint(true);
189
193
  toolRef.current.toggleCropZone(true);
190
194
  }
191
195
 
192
- // Nettoyage
196
+ // Cleanup
193
197
  return () => {
194
198
  if (toolRef.current) {
195
199
  toolRef.current.destroy();
@@ -200,7 +204,7 @@ function ImageEditor() {
200
204
 
201
205
  return (
202
206
  <div>
203
- <img ref={imageRef} src="path/to/image.jpg" alt="Éditable" />
207
+ <img ref={imageRef} src="path/to/image.jpg" alt="Editable" />
204
208
  </div>
205
209
  );
206
210
  }
@@ -211,7 +215,7 @@ function ImageEditor() {
211
215
  ```vue
212
216
  <template>
213
217
  <div>
214
- <img ref="editableImage" src="path/to/image.jpg" alt="Éditable" />
218
+ <img ref="editableImage" src="path/to/image.jpg" alt="Editable" />
215
219
  </div>
216
220
  </template>
217
221
 
@@ -228,11 +232,11 @@ export default {
228
232
  this.imageTool = new VisualImageTool({
229
233
  imageElement: this.$refs.editableImage,
230
234
  onChange: (data) => {
231
- console.log('Données mises à jour:', data);
235
+ console.log('Updated data:', data);
232
236
  }
233
237
  });
234
238
 
235
- // Activer les fonctionnalités
239
+ // Enable features
236
240
  this.imageTool.toggleFocusPoint(true);
237
241
  this.imageTool.toggleCropZone(true);
238
242
  },
@@ -246,22 +250,27 @@ export default {
246
250
  </script>
247
251
  ```
248
252
 
249
- ## Démos
253
+ ## Demos
250
254
 
251
- Consultez le dossier `demos/` pour des exemples complets :
255
+ The `demo/` folder contains the following examples:
252
256
 
253
- - `basic-usage.html` : Exemple d'utilisation basique
254
- - `custom-config.html` : Exemple avec configuration personnalisée
255
- - `react-integration.jsx` : Exemple d'intégration avec React
256
- - `vue-integration.js` : Exemple d'intégration avec Vue.js
257
+ - `basic-usage.html`: Basic usage example
258
+ - `custom-config.html`: Custom configuration demo with live controls
259
+ - `demo-esm.html`: ESM (ECMAScript Module) integration demo
260
+ - `demo-umd.html`: UMD (Universal Module Definition) integration demo
261
+ - `index2.html`: Alternate or experimental demo page
262
+ - `preact-importmap-demo.html`: Preact integration using importmap
263
+ - `react-integration.jsx`: React integration example
264
+ - `vue-importmap-demo.html`: Vue integration using importmap
265
+ - `vue-integration.js`: Vue integration script
257
266
 
258
- ## Compatibilité navigateur
267
+ ## Browser Compatibility
259
268
 
260
- - Chrome (dernières versions)
261
- - Firefox (dernières versions)
262
- - Safari (dernières versions)
263
- - Edge (dernières versions)
269
+ - Chrome (latest versions)
270
+ - Firefox (latest versions)
271
+ - Safari (latest versions)
272
+ - Edge (latest versions)
264
273
 
265
- ## Licence
274
+ ## License
266
275
 
267
276
  MIT
@@ -59,7 +59,8 @@ class VisualImageTool {
59
59
  },
60
60
  ...options.cropZone
61
61
  },
62
- onChange: options.onChange || (() => {})
62
+ onChange: options.onChange || (() => {}),
63
+ debug: options.debug || false
63
64
  };
64
65
 
65
66
  // État interne
@@ -536,10 +537,31 @@ class VisualImageTool {
536
537
  }
537
538
 
538
539
  const scaled = this._toScaledCoords(clampedX, clampedY);
539
-
540
+
541
+ // LOGGING: Validate padding offset
542
+ if (this.options.debug) {
543
+ const container = this.imageElement.parentNode;
544
+ const computedStyle = window.getComputedStyle(container);
545
+ const paddingLeft = parseFloat(computedStyle.paddingLeft);
546
+ const paddingTop = parseFloat(computedStyle.paddingTop);
547
+ console.log('[FocusMarker] scaled:', scaled, 'paddingLeft:', paddingLeft, 'paddingTop:', paddingTop, 'containerRect:', container.getBoundingClientRect());
548
+ }
549
+
540
550
  // Ajuster pour centrer le marqueur
541
- this.state.focusMarker.style.left = (scaled.x - this.state.focusMarker.offsetWidth / 2) + 'px';
542
- this.state.focusMarker.style.top = (scaled.y - this.state.focusMarker.offsetHeight / 2) + 'px';
551
+ // Adjust for container padding (use unique variable names)
552
+ let focusPaddingLeft = 0, focusPaddingTop = 0;
553
+ {
554
+ const container = this.imageElement.parentNode;
555
+ const computedStyle = window.getComputedStyle(container);
556
+ focusPaddingLeft = parseFloat(computedStyle.paddingLeft);
557
+ focusPaddingTop = parseFloat(computedStyle.paddingTop);
558
+ }
559
+
560
+ this.state.focusMarker.style.left = (scaled.x + focusPaddingLeft - this.state.focusMarker.offsetWidth / 2) + 'px';
561
+ this.state.focusMarker.style.top = (scaled.y + focusPaddingTop - this.state.focusMarker.offsetHeight / 2) + 'px';
562
+ if (this.options.debug) {
563
+ console.log('[FocusMarker] style.left:', this.state.focusMarker.style.left, 'style.top:', this.state.focusMarker.style.top);
564
+ }
543
565
  }
544
566
 
545
567
  /**
@@ -566,12 +588,33 @@ class VisualImageTool {
566
588
  const scaled = this._toScaledCoords(clampedX, clampedY);
567
589
  const scaledWidth = clampedWidth * this.state.scaleX;
568
590
  const scaledHeight = clampedHeight * this.state.scaleY;
569
-
591
+
592
+ // LOGGING: Validate padding offset
593
+ if (this.options.debug) {
594
+ const container = this.imageElement.parentNode;
595
+ const computedStyle = window.getComputedStyle(container);
596
+ const paddingLeft = parseFloat(computedStyle.paddingLeft);
597
+ const paddingTop = parseFloat(computedStyle.paddingTop);
598
+ console.log('[CropOverlay] scaled:', scaled, 'paddingLeft:', paddingLeft, 'paddingTop:', paddingTop, 'containerRect:', container.getBoundingClientRect());
599
+ }
600
+
570
601
  // Mettre à jour l'overlay
571
- this.state.cropOverlay.style.left = scaled.x + 'px';
572
- this.state.cropOverlay.style.top = scaled.y + 'px';
602
+ // Adjust for container padding (use unique variable names)
603
+ let cropPaddingLeft = 0, cropPaddingTop = 0;
604
+ {
605
+ const container = this.imageElement.parentNode;
606
+ const computedStyle = window.getComputedStyle(container);
607
+ cropPaddingLeft = parseFloat(computedStyle.paddingLeft);
608
+ cropPaddingTop = parseFloat(computedStyle.paddingTop);
609
+ }
610
+
611
+ this.state.cropOverlay.style.left = (scaled.x + cropPaddingLeft) + 'px';
612
+ this.state.cropOverlay.style.top = (scaled.y + cropPaddingTop) + 'px';
573
613
  this.state.cropOverlay.style.width = scaledWidth + 'px';
574
614
  this.state.cropOverlay.style.height = scaledHeight + 'px';
615
+ if (this.options.debug) {
616
+ console.log('[CropOverlay] style.left:', this.state.cropOverlay.style.left, 'style.top:', this.state.cropOverlay.style.top);
617
+ }
575
618
  }
576
619
 
577
620
  /**