@operato/image-marker 8.0.0-alpha.37 → 8.0.0-alpha.39

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.
@@ -32,6 +32,10 @@ export class BaseImageMarker extends LitElement {
32
32
  height: 100%;
33
33
  touch-action: none;
34
34
  }
35
+
36
+ .link:hover {
37
+ cursor: pointer;
38
+ }
35
39
  `
36
40
  ]
37
41
 
@@ -50,6 +54,7 @@ export class BaseImageMarker extends LitElement {
50
54
  protected initialViewBox: string | null = null
51
55
 
52
56
  @query('svg') protected svg!: SVGSVGElement
57
+ @query('image') protected image!: SVGImageElement
53
58
 
54
59
  private gestureHelper: GestureHelper | null = null
55
60
 
@@ -69,6 +74,7 @@ export class BaseImageMarker extends LitElement {
69
74
 
70
75
  protected updated(changes: PropertyValues): void {
71
76
  if (changes.has('imageUrl') || changes.has('imageProvider')) {
77
+ this.zoomLevel = 1
72
78
  this.initialViewBox = null
73
79
  this.updateImage()
74
80
  }
@@ -79,19 +85,26 @@ export class BaseImageMarker extends LitElement {
79
85
  }
80
86
 
81
87
  protected onImageLoad(event: Event) {
88
+ const element = event.target as SVGImageElement
82
89
  const img = new Image()
83
90
 
84
91
  img.onload = () => {
85
- const [vbX, vbY, vbWidth, vbHeight] = this.viewBox.split(' ').map(Number)
92
+ const width = img.naturalWidth
93
+ const height = img.naturalHeight
86
94
 
87
95
  if (!this.initialViewBox) {
88
- const width = img.naturalWidth
89
- const height = img.naturalHeight
90
-
91
96
  this.initialViewBox = `0 0 ${width} ${height}`
92
97
  this.viewBox = this.initialViewBox
98
+
99
+ element.setAttribute('width', width.toString())
100
+ element.setAttribute('height', height.toString())
101
+ element.setAttribute('preserveAspectRatio', 'xMidYMid meet')
93
102
  } else {
94
- this.viewBox = `${vbX} ${vbY} ${vbWidth} ${vbHeight}`
103
+ const [initialX, initialY, initialWidth, initialHeight] = this.initialViewBox.split(' ').map(Number)
104
+ const scale = initialWidth / width
105
+
106
+ element.setAttribute('width', (width * scale).toString())
107
+ element.setAttribute('height', (height * scale).toString())
95
108
  }
96
109
  }
97
110
 
@@ -103,6 +116,10 @@ export class BaseImageMarker extends LitElement {
103
116
  throw new Error('ImageProvider is not set')
104
117
  }
105
118
 
119
+ if (!this.imageUrl) {
120
+ return
121
+ }
122
+
106
123
  const options = {
107
124
  id: this.imageUrl, // 이미지 ID는 imageUrl 속성을 사용
108
125
  scale: this.zoomLevel, // scale은 zoomLevel 속성을 사용
@@ -177,13 +194,28 @@ export class BaseImageMarker extends LitElement {
177
194
  }
178
195
  }
179
196
 
180
- protected reset() {
197
+ public reset() {
198
+ if (!this.initialViewBox) {
199
+ this.zoomLevel = 1
200
+ return
201
+ }
202
+
181
203
  this.viewBox = this.initialViewBox!
182
204
  this.zoomLevel = 1
183
205
 
184
206
  this.debouncedUpdateImage()
185
207
  }
186
208
 
209
+ protected handleLinkClick(shape: Shape) {
210
+ this.dispatchEvent(
211
+ new CustomEvent('link-clicked', {
212
+ detail: { id: shape.id, link: shape.link },
213
+ bubbles: true,
214
+ composed: true
215
+ })
216
+ )
217
+ }
218
+
187
219
  protected renderShape(shape: Shape) {
188
220
  const commonAttrs = {
189
221
  stroke: 'red',
@@ -208,6 +240,12 @@ export class BaseImageMarker extends LitElement {
208
240
  </marker>
209
241
  </defs>
210
242
  <line x1="${shape.x1}" y1="${shape.y1}" x2="${shape.x2}" y2="${shape.y2}" stroke="${commonAttrs.stroke}" stroke-width="${commonAttrs['stroke-width']}" marker-end="url(#arrowhead-${shape.id})"></line>`
243
+ case 'link':
244
+ return svg`
245
+ <rect class="link" x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}"
246
+ stroke="${commonAttrs.stroke}" stroke-width="0"
247
+ fill="${commonAttrs.stroke}" fill-opacity="0.3" @click="${() => this.handleLinkClick(shape)}">
248
+ </rect>`
211
249
  default:
212
250
  return nothing
213
251
  }
package/src/index.ts CHANGED
@@ -0,0 +1,6 @@
1
+ export * from './types.js'
2
+ export * from './base-image-marker.js'
3
+
4
+ export * from './ox-image-marker.js'
5
+ export * from './ox-image-marker-view.js'
6
+ export * from './ox-image-marker-mode.js'
@@ -432,6 +432,13 @@ export class OxImageMarker extends BaseImageMarker {
432
432
  ${shape.selected ? this.renderResizeHandles(shape) : ''}
433
433
  `
434
434
 
435
+ case 'link':
436
+ return svg`
437
+ <rect class="link" x="${shape.x}" y="${shape.y}" width="${shape.width}" height="${shape.height}"
438
+ stroke="${commonAttrs.stroke}" stroke-width="0"
439
+ fill="${commonAttrs.stroke}" fill-opacity="0.3" @click="${() => this.handleLinkClick(shape)}">
440
+ </rect>
441
+ `
435
442
  default:
436
443
  return nothing
437
444
  }
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- export type ShapeType = 'text' | 'rectangle' | 'circle' | 'triangle' | 'line' | 'arrow'
1
+ export type ShapeType = 'text' | 'rectangle' | 'circle' | 'triangle' | 'line' | 'arrow' | 'link'
2
2
  export type ImageMarkerMode = 'edit' | 'view' | 'shape'
3
3
  export interface Shape {
4
4
  id: string
@@ -17,6 +17,8 @@ export interface Shape {
17
17
  y2?: number
18
18
  selected?: boolean
19
19
  text?: string
20
+ link?: string
21
+ opacity?: number
20
22
  }
21
23
 
22
24
  export interface ImageOptions {
@@ -94,7 +94,7 @@ const Template: Story<ArgTypes> = ({ imageUrl, shapes = [] }: ArgTypes) => html`
94
94
 
95
95
  imageMarker.setImageProvider(new TestImageProvider(1080, 720))
96
96
  document.body.querySelector('[button1]').addEventListener('click', e => {
97
- imageMarker.setImageProvider(new TestImageProvider(1600, 1200))
97
+ imageMarker.setImageProvider(new TestImageProvider(1600, 400))
98
98
  })
99
99
  document.body.querySelector('[button2]').addEventListener('click', e => {
100
100
  imageMarker.setImageProvider(new TestImageProvider(800, 600))
@@ -103,7 +103,7 @@ const Template: Story<ArgTypes> = ({ imageUrl, shapes = [] }: ArgTypes) => html`
103
103
 
104
104
  <ox-image-marker .imageUrl=${imageUrl} .shapes=${shapes}></ox-image-marker>
105
105
  <div buttons>
106
- <button button1>1200 x 800</button>
106
+ <button button1>1600 x 400</button>
107
107
  <button button2>800 x 600</button>
108
108
  </div>
109
109
  `
@@ -27,8 +27,10 @@ export class TestImageProvider implements ImageProvider {
27
27
  throw new Error('Failed to get canvas context')
28
28
  }
29
29
 
30
- const width = this.width
31
- const height = this.height
30
+ const { scale } = options
31
+
32
+ const width = this.width * scale
33
+ const height = this.height * scale
32
34
  canvas.width = width
33
35
  canvas.height = height
34
36