@operato/mini-map 2.0.0-beta.0 → 2.0.0-beta.10
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/CHANGELOG.md +10 -0
- package/dist/src/ox-mini-map.js +77 -65
- package/dist/src/ox-mini-map.js.map +1 -1
- package/dist/src/ox-zoomable-image.d.ts +54 -0
- package/dist/src/ox-zoomable-image.js +252 -0
- package/dist/src/ox-zoomable-image.js.map +1 -0
- package/dist/stories/ox-mini-map.stories.js +44 -0
- package/dist/stories/ox-mini-map.stories.js.map +1 -0
- package/dist/stories/ox-zoomable-image.stories.d.ts +31 -0
- package/dist/stories/ox-zoomable-image.stories.js +42 -0
- package/dist/stories/ox-zoomable-image.stories.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -2
- package/src/ox-mini-map.ts +88 -69
- package/src/ox-zoomable-image.ts +256 -0
- package/stories/ox-mini-map.stories.ts +54 -0
- package/stories/ox-zoomable-image.stories.ts +58 -0
- package/dist/stories/index.stories.js +0 -16
- package/dist/stories/index.stories.js.map +0 -1
- package/stories/index.stories.ts +0 -26
- /package/dist/stories/{index.stories.d.ts → ox-mini-map.stories.d.ts} +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [2.0.0-beta.10](https://github.com/hatiolab/operato/compare/v2.0.0-beta.9...v2.0.0-beta.10) (2024-06-08)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### :rocket: New Features
|
|
10
|
+
|
|
11
|
+
* mini-map ([a1cdac2](https://github.com/hatiolab/operato/commit/a1cdac283c57129420247c6d61b9488d2a595dc2))
|
|
12
|
+
* ox-zoomable-image in mini-map module ([9f23992](https://github.com/hatiolab/operato/commit/9f2399235b318cd9b90740ae19aa6d481280d61b))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
6
16
|
## [2.0.0-beta.0](https://github.com/hatiolab/operato/compare/v2.0.0-alpha.158...v2.0.0-beta.0) (2024-06-01)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package @operato/mini-map
|
package/dist/src/ox-mini-map.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
2
|
import { html, css, LitElement } from 'lit';
|
|
3
3
|
import { customElement, property } from 'lit/decorators.js';
|
|
4
|
-
let
|
|
4
|
+
let OxMiniMapComponent = class OxMiniMapComponent extends LitElement {
|
|
5
5
|
constructor() {
|
|
6
6
|
super(...arguments);
|
|
7
7
|
this.target = null;
|
|
@@ -10,28 +10,50 @@ let OxminimapComponent = class OxminimapComponent extends LitElement {
|
|
|
10
10
|
this.startY = 0;
|
|
11
11
|
this.initialScrollLeft = 0;
|
|
12
12
|
this.initialScrollTop = 0;
|
|
13
|
+
this.observer = null;
|
|
13
14
|
}
|
|
14
15
|
connectedCallback() {
|
|
15
16
|
super.connectedCallback();
|
|
16
17
|
window.addEventListener('resize', this.handleResize.bind(this));
|
|
18
|
+
this.addEventListener('mousemove', this.handleMouseMove.bind(this));
|
|
19
|
+
this.addEventListener('mouseup', this.handleMouseUp.bind(this));
|
|
20
|
+
if (this.target) {
|
|
21
|
+
this.observeTarget(this.target);
|
|
22
|
+
}
|
|
17
23
|
}
|
|
18
24
|
disconnectedCallback() {
|
|
19
25
|
super.disconnectedCallback();
|
|
20
26
|
window.removeEventListener('resize', this.handleResize.bind(this));
|
|
27
|
+
window.removeEventListener('mousemove', this.handleMouseMove.bind(this));
|
|
28
|
+
window.removeEventListener('mouseup', this.handleMouseUp.bind(this));
|
|
29
|
+
if (this.observer) {
|
|
30
|
+
this.observer.disconnect();
|
|
31
|
+
this.observer = null;
|
|
32
|
+
}
|
|
21
33
|
}
|
|
22
34
|
firstUpdated(changes) {
|
|
23
35
|
super.firstUpdated(changes);
|
|
24
36
|
this.updateTarget();
|
|
25
|
-
this.checkVisibilityX();
|
|
26
37
|
}
|
|
27
38
|
updated(changedProperties) {
|
|
28
39
|
if (changedProperties.has('target')) {
|
|
29
40
|
this.updateTarget();
|
|
41
|
+
if (this.target) {
|
|
42
|
+
this.observeTarget(this.target);
|
|
43
|
+
}
|
|
30
44
|
}
|
|
31
45
|
}
|
|
32
46
|
handleResize() {
|
|
33
47
|
this.updateTarget();
|
|
34
|
-
|
|
48
|
+
}
|
|
49
|
+
observeTarget(target) {
|
|
50
|
+
if (this.observer) {
|
|
51
|
+
this.observer.disconnect();
|
|
52
|
+
}
|
|
53
|
+
this.observer = new MutationObserver(() => {
|
|
54
|
+
this.updateTarget();
|
|
55
|
+
});
|
|
56
|
+
this.observer.observe(target, { attributes: true, attributeFilter: ['style'] });
|
|
35
57
|
}
|
|
36
58
|
updateTarget() {
|
|
37
59
|
var _a, _b;
|
|
@@ -39,108 +61,99 @@ let OxminimapComponent = class OxminimapComponent extends LitElement {
|
|
|
39
61
|
if (!target) {
|
|
40
62
|
return;
|
|
41
63
|
}
|
|
64
|
+
const targetStyle = window.getComputedStyle(target);
|
|
65
|
+
const transform = targetStyle.transform;
|
|
66
|
+
const scaleMatch = /scale\(([^,]+),?([^)]+)?\)/.exec(transform);
|
|
67
|
+
const leftMatch = /translate\(([^,]+)px, ?([^)]+)?px\)/.exec(transform);
|
|
68
|
+
let scale = 1;
|
|
69
|
+
let left = 0;
|
|
70
|
+
let top = 0;
|
|
71
|
+
if (scaleMatch) {
|
|
72
|
+
scale = parseFloat(scaleMatch[1]);
|
|
73
|
+
}
|
|
74
|
+
if (leftMatch) {
|
|
75
|
+
left = parseFloat(leftMatch[1]);
|
|
76
|
+
top = parseFloat(leftMatch[2] || '0');
|
|
77
|
+
}
|
|
42
78
|
const targetRatio = target.scrollHeight / target.scrollWidth;
|
|
43
79
|
const thisRatio = this.offsetHeight / this.offsetWidth;
|
|
44
|
-
const
|
|
45
|
-
const minimapHeight = target.scrollHeight *
|
|
46
|
-
const minimapWidth = target.scrollWidth *
|
|
47
|
-
const viewportHeight = target.
|
|
48
|
-
const viewportWidth = target.
|
|
80
|
+
const scaleMinimap = targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth;
|
|
81
|
+
const minimapHeight = target.scrollHeight * scaleMinimap;
|
|
82
|
+
const minimapWidth = target.scrollWidth * scaleMinimap;
|
|
83
|
+
const viewportHeight = target.clientHeight * scaleMinimap;
|
|
84
|
+
const viewportWidth = target.clientWidth * scaleMinimap;
|
|
49
85
|
const minimap = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('minimap');
|
|
50
86
|
const viewport = (_b = this.shadowRoot) === null || _b === void 0 ? void 0 : _b.getElementById('viewport');
|
|
51
87
|
minimap.style.width = `${minimapWidth}px`;
|
|
52
88
|
minimap.style.height = `${minimapHeight}px`;
|
|
53
89
|
viewport.style.width = `${viewportWidth}px`;
|
|
54
90
|
viewport.style.height = `${viewportHeight}px`;
|
|
55
|
-
|
|
56
|
-
const viewportTop = target.scrollTop * scale;
|
|
57
|
-
viewport.style.width = `${viewportWidth}px`;
|
|
58
|
-
viewport.style.height = `${viewportHeight}px`;
|
|
59
|
-
viewport.style.left = `${viewportLeft}px`;
|
|
60
|
-
viewport.style.top = `${viewportTop}px`;
|
|
61
|
-
}
|
|
62
|
-
checkVisibilityX() {
|
|
63
|
-
var _a;
|
|
64
|
-
const parentElement = this.target || this.parentElement;
|
|
65
|
-
if (!parentElement)
|
|
66
|
-
return;
|
|
67
|
-
const parentRect = parentElement.getBoundingClientRect();
|
|
68
|
-
const minimap = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('minimap');
|
|
69
|
-
if (parentRect.width >= minimap.offsetWidth && parentRect.height >= minimap.offsetHeight) {
|
|
70
|
-
this.style.display = 'block';
|
|
71
|
-
}
|
|
72
|
-
else {
|
|
73
|
-
this.style.display = 'none';
|
|
74
|
-
}
|
|
91
|
+
this.updateViewportPosition(scale, left, top);
|
|
75
92
|
}
|
|
76
|
-
|
|
93
|
+
updateViewportPosition(scale, left, top) {
|
|
77
94
|
var _a;
|
|
78
95
|
const target = this.target || this.parentElement;
|
|
79
96
|
if (!target) {
|
|
80
97
|
return;
|
|
81
98
|
}
|
|
82
|
-
const
|
|
99
|
+
const targetRatio = target.scrollHeight / target.scrollWidth;
|
|
100
|
+
const thisRatio = this.offsetHeight / this.offsetWidth;
|
|
101
|
+
const scaleMinimap = targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth;
|
|
102
|
+
const viewport = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('viewport');
|
|
103
|
+
viewport.style.transform = `scale(${scale}) translate(${left * scaleMinimap}px, ${top * scaleMinimap}px)`;
|
|
104
|
+
}
|
|
105
|
+
handleMouseDown(event) {
|
|
106
|
+
this.isDragging = true;
|
|
83
107
|
this.startX = event.clientX;
|
|
84
108
|
this.startY = event.clientY;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
109
|
+
const target = this.target || this.parentElement;
|
|
110
|
+
if (target) {
|
|
111
|
+
this.initialScrollLeft = target.scrollLeft;
|
|
112
|
+
this.initialScrollTop = target.scrollTop;
|
|
113
|
+
}
|
|
114
|
+
window.addEventListener('mousemove', this.handleMouseMove.bind(this));
|
|
115
|
+
window.addEventListener('mouseup', this.handleMouseUp.bind(this));
|
|
89
116
|
event.preventDefault();
|
|
90
|
-
event.stopPropagation();
|
|
91
117
|
}
|
|
92
118
|
handleMouseMove(event) {
|
|
93
|
-
var _a;
|
|
94
119
|
if (!this.isDragging)
|
|
95
120
|
return;
|
|
96
121
|
const deltaX = event.clientX - this.startX;
|
|
97
122
|
const deltaY = event.clientY - this.startY;
|
|
98
123
|
const target = this.target || this.parentElement;
|
|
99
|
-
if (!target)
|
|
124
|
+
if (!target)
|
|
100
125
|
return;
|
|
101
|
-
}
|
|
102
126
|
const targetRatio = target.scrollHeight / target.scrollWidth;
|
|
103
127
|
const thisRatio = this.offsetHeight / this.offsetWidth;
|
|
104
128
|
const scale = targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth;
|
|
105
|
-
const targetRect = target.getBoundingClientRect();
|
|
106
|
-
const viewportWidth = (targetRect.width * target.clientWidth) / target.scrollWidth;
|
|
107
|
-
const viewportHeight = (targetRect.height * target.clientHeight) / target.scrollHeight;
|
|
108
129
|
const scrollX = deltaX / scale;
|
|
109
130
|
const scrollY = deltaY / scale;
|
|
110
|
-
target.
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
minimapViewport.style.top = `${Math.max(0, Math.min(event.clientY - viewportHeight / 2, target.clientHeight - viewportHeight))}px`;
|
|
114
|
-
this.updateTarget();
|
|
131
|
+
target.scrollLeft = this.initialScrollLeft + scrollX;
|
|
132
|
+
target.scrollTop = this.initialScrollTop + scrollY;
|
|
133
|
+
this.updateViewportPosition(1, target.scrollLeft, target.scrollTop); // Assuming no additional transform during drag
|
|
115
134
|
event.preventDefault();
|
|
116
|
-
event.stopPropagation();
|
|
117
135
|
}
|
|
118
136
|
handleMouseUp(event) {
|
|
119
|
-
var _a;
|
|
120
|
-
const minimapViewport = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.getElementById('minimap');
|
|
121
137
|
this.isDragging = false;
|
|
122
|
-
|
|
138
|
+
window.removeEventListener('mousemove', this.handleMouseMove.bind(this));
|
|
139
|
+
window.removeEventListener('mouseup', this.handleMouseUp.bind(this));
|
|
123
140
|
event.preventDefault();
|
|
124
|
-
event.stopPropagation();
|
|
125
141
|
}
|
|
126
142
|
render() {
|
|
127
143
|
return html `
|
|
128
144
|
<div id="minimap">
|
|
129
|
-
<div
|
|
130
|
-
id="viewport"
|
|
131
|
-
@mousedown=${this.handleMouseDown}
|
|
132
|
-
@mousemove=${this.handleMouseMove}
|
|
133
|
-
@mouseup=${this.handleMouseUp}
|
|
134
|
-
></div>
|
|
145
|
+
<div id="viewport" @mousedown=${this.handleMouseDown}></div>
|
|
135
146
|
</div>
|
|
136
147
|
`;
|
|
137
148
|
}
|
|
138
149
|
};
|
|
139
|
-
|
|
150
|
+
OxMiniMapComponent.styles = css `
|
|
140
151
|
:host {
|
|
141
152
|
display: flex;
|
|
142
153
|
position: relative;
|
|
143
154
|
background-color: gray;
|
|
155
|
+
width: 200px; /* 기본 너비 */
|
|
156
|
+
height: 150px; /* 기본 높이 */
|
|
144
157
|
}
|
|
145
158
|
|
|
146
159
|
#minimap {
|
|
@@ -149,7 +162,8 @@ OxminimapComponent.styles = css `
|
|
|
149
162
|
left: 50%;
|
|
150
163
|
transform: translate(-50%, -50%);
|
|
151
164
|
box-sizing: border-box;
|
|
152
|
-
|
|
165
|
+
width: 100%;
|
|
166
|
+
height: 100%;
|
|
153
167
|
background-color: var(--md-sys-color-surface);
|
|
154
168
|
overflow: hidden;
|
|
155
169
|
}
|
|
@@ -158,16 +172,14 @@ OxminimapComponent.styles = css `
|
|
|
158
172
|
position: absolute;
|
|
159
173
|
border: 1px dashed blue;
|
|
160
174
|
box-sizing: border-box;
|
|
161
|
-
pointer-events: none;
|
|
162
|
-
background-color: var(--md-sys-color-surface);
|
|
163
|
-
pointer-events: auto;
|
|
164
175
|
cursor: move;
|
|
176
|
+
background-color: rgba(255, 255, 255, 0.5);
|
|
165
177
|
}
|
|
166
178
|
`;
|
|
167
179
|
__decorate([
|
|
168
180
|
property({ type: Object })
|
|
169
|
-
],
|
|
170
|
-
|
|
181
|
+
], OxMiniMapComponent.prototype, "target", void 0);
|
|
182
|
+
OxMiniMapComponent = __decorate([
|
|
171
183
|
customElement('ox-mini-map')
|
|
172
|
-
],
|
|
184
|
+
], OxMiniMapComponent);
|
|
173
185
|
//# sourceMappingURL=ox-mini-map.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ox-mini-map.js","sourceRoot":"","sources":["../../src/ox-mini-map.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, LitElement, PropertyValueMap } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n@customElement('ox-mini-map')\nclass OxminimapComponent extends LitElement {\n static styles = css`\n :host {\n display: flex;\n position: relative;\n background-color: gray;\n }\n\n #minimap {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n box-sizing: border-box;\n\n background-color: var(--md-sys-color-surface);\n overflow: hidden;\n }\n\n #viewport {\n position: absolute;\n border: 1px dashed blue;\n box-sizing: border-box;\n pointer-events: none;\n background-color: var(--md-sys-color-surface);\n pointer-events: auto;\n cursor: move;\n }\n `\n\n @property({ type: Object }) target: HTMLElement | null = null\n private isDragging = false\n private startX = 0\n private startY = 0\n private initialScrollLeft = 0\n private initialScrollTop = 0\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('resize', this.handleResize.bind(this))\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n window.removeEventListener('resize', this.handleResize.bind(this))\n }\n\n firstUpdated(changes: PropertyValueMap<any> | Map<PropertyKey, unknown>) {\n super.firstUpdated(changes)\n\n this.updateTarget()\n this.checkVisibilityX()\n }\n\n updated(changedProperties: Map<string, any>) {\n if (changedProperties.has('target')) {\n this.updateTarget()\n }\n }\n\n handleResize() {\n this.updateTarget()\n this.checkVisibilityX()\n }\n\n updateTarget() {\n const target = this.target || this.parentElement\n if (!target) {\n return\n }\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scale =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const minimapHeight = target.scrollHeight * scale\n const minimapWidth = target.scrollWidth * scale\n\n const viewportHeight = target.offsetHeight * scale\n const viewportWidth = target.offsetWidth * scale\n\n const minimap = this.shadowRoot?.getElementById('minimap') as HTMLElement\n const viewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n\n minimap.style.width = `${minimapWidth}px`\n minimap.style.height = `${minimapHeight}px`\n\n viewport.style.width = `${viewportWidth}px`\n viewport.style.height = `${viewportHeight}px`\n\n const viewportLeft = target.scrollLeft * scale\n const viewportTop = target.scrollTop * scale\n\n viewport.style.width = `${viewportWidth}px`\n viewport.style.height = `${viewportHeight}px`\n viewport.style.left = `${viewportLeft}px`\n viewport.style.top = `${viewportTop}px`\n }\n\n checkVisibilityX() {\n const parentElement = this.target || this.parentElement\n if (!parentElement) return\n\n const parentRect = parentElement.getBoundingClientRect()\n const minimap = this.shadowRoot?.getElementById('minimap') as HTMLElement\n if (parentRect.width >= minimap.offsetWidth && parentRect.height >= minimap.offsetHeight) {\n this.style.display = 'block'\n } else {\n this.style.display = 'none'\n }\n }\n\n handleMouseDown(event: MouseEvent) {\n const target = this.target || this.parentElement\n\n if (!target) {\n return\n }\n\n const minimapViewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n this.startX = event.clientX\n this.startY = event.clientY\n this.initialScrollLeft = target.scrollLeft || 0\n this.initialScrollTop = target.scrollTop || 0\n this.isDragging = true\n minimapViewport.classList.add('dragging')\n event.preventDefault()\n event.stopPropagation()\n }\n\n handleMouseMove(event: MouseEvent) {\n if (!this.isDragging) return\n const deltaX = event.clientX - this.startX\n const deltaY = event.clientY - this.startY\n\n const target = this.target || this.parentElement\n\n if (!target) {\n return\n }\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scale =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const targetRect = target.getBoundingClientRect()\n const viewportWidth = (targetRect.width * target.clientWidth) / target.scrollWidth\n const viewportHeight = (targetRect.height * target.clientHeight) / target.scrollHeight\n const scrollX = deltaX / scale\n const scrollY = deltaY / scale\n target.scrollTo(this.initialScrollLeft + scrollX, this.initialScrollTop + scrollY)\n const minimapViewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n minimapViewport.style.left = `${Math.max(\n 0,\n Math.min(event.clientX - viewportWidth / 2, target.clientWidth - viewportWidth)\n )}px`\n minimapViewport.style.top = `${Math.max(\n 0,\n Math.min(event.clientY - viewportHeight / 2, target.clientHeight - viewportHeight)\n )}px`\n\n this.updateTarget()\n event.preventDefault()\n event.stopPropagation()\n }\n\n handleMouseUp(event: MouseEvent) {\n const minimapViewport = this.shadowRoot?.getElementById('minimap') as HTMLElement\n this.isDragging = false\n minimapViewport.classList.remove('dragging')\n event.preventDefault()\n event.stopPropagation()\n }\n\n render() {\n return html`\n <div id=\"minimap\">\n <div\n id=\"viewport\"\n @mousedown=${this.handleMouseDown}\n @mousemove=${this.handleMouseMove}\n @mouseup=${this.handleMouseUp}\n ></div>\n </div>\n `\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ox-mini-map.js","sourceRoot":"","sources":["../../src/ox-mini-map.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, css, LitElement, PropertyValueMap } from 'lit'\nimport { customElement, property } from 'lit/decorators.js'\n\n@customElement('ox-mini-map')\nclass OxMiniMapComponent extends LitElement {\n static styles = css`\n :host {\n display: flex;\n position: relative;\n background-color: gray;\n width: 200px; /* 기본 너비 */\n height: 150px; /* 기본 높이 */\n }\n\n #minimap {\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n box-sizing: border-box;\n width: 100%;\n height: 100%;\n background-color: var(--md-sys-color-surface);\n overflow: hidden;\n }\n\n #viewport {\n position: absolute;\n border: 1px dashed blue;\n box-sizing: border-box;\n cursor: move;\n background-color: rgba(255, 255, 255, 0.5);\n }\n `\n\n @property({ type: Object }) target: HTMLElement | null = null\n private isDragging = false\n private startX = 0\n private startY = 0\n private initialScrollLeft = 0\n private initialScrollTop = 0\n private observer: MutationObserver | null = null\n\n connectedCallback() {\n super.connectedCallback()\n window.addEventListener('resize', this.handleResize.bind(this))\n this.addEventListener('mousemove', this.handleMouseMove.bind(this))\n this.addEventListener('mouseup', this.handleMouseUp.bind(this))\n if (this.target) {\n this.observeTarget(this.target)\n }\n }\n\n disconnectedCallback() {\n super.disconnectedCallback()\n window.removeEventListener('resize', this.handleResize.bind(this))\n window.removeEventListener('mousemove', this.handleMouseMove.bind(this))\n window.removeEventListener('mouseup', this.handleMouseUp.bind(this))\n if (this.observer) {\n this.observer.disconnect()\n this.observer = null\n }\n }\n\n firstUpdated(changes: PropertyValueMap<any> | Map<PropertyKey, unknown>) {\n super.firstUpdated(changes)\n this.updateTarget()\n }\n\n updated(changedProperties: Map<string, any>) {\n if (changedProperties.has('target')) {\n this.updateTarget()\n if (this.target) {\n this.observeTarget(this.target)\n }\n }\n }\n\n handleResize() {\n this.updateTarget()\n }\n\n observeTarget(target: HTMLElement) {\n if (this.observer) {\n this.observer.disconnect()\n }\n this.observer = new MutationObserver(() => {\n this.updateTarget()\n })\n this.observer.observe(target, { attributes: true, attributeFilter: ['style'] })\n }\n\n updateTarget() {\n const target = this.target || this.parentElement\n if (!target) {\n return\n }\n\n const targetStyle = window.getComputedStyle(target)\n const transform = targetStyle.transform\n const scaleMatch = /scale\\(([^,]+),?([^)]+)?\\)/.exec(transform)\n const leftMatch = /translate\\(([^,]+)px, ?([^)]+)?px\\)/.exec(transform)\n\n let scale = 1\n let left = 0\n let top = 0\n\n if (scaleMatch) {\n scale = parseFloat(scaleMatch[1])\n }\n\n if (leftMatch) {\n left = parseFloat(leftMatch[1])\n top = parseFloat(leftMatch[2] || '0')\n }\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scaleMinimap =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const minimapHeight = target.scrollHeight * scaleMinimap\n const minimapWidth = target.scrollWidth * scaleMinimap\n\n const viewportHeight = target.clientHeight * scaleMinimap\n const viewportWidth = target.clientWidth * scaleMinimap\n\n const minimap = this.shadowRoot?.getElementById('minimap') as HTMLElement\n const viewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n\n minimap.style.width = `${minimapWidth}px`\n minimap.style.height = `${minimapHeight}px`\n\n viewport.style.width = `${viewportWidth}px`\n viewport.style.height = `${viewportHeight}px`\n\n this.updateViewportPosition(scale, left, top)\n }\n\n updateViewportPosition(scale: number, left: number, top: number) {\n const target = this.target || this.parentElement\n if (!target) {\n return\n }\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scaleMinimap =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const viewport = this.shadowRoot?.getElementById('viewport') as HTMLElement\n viewport.style.transform = `scale(${scale}) translate(${left * scaleMinimap}px, ${top * scaleMinimap}px)`\n }\n\n handleMouseDown(event: MouseEvent) {\n this.isDragging = true\n this.startX = event.clientX\n this.startY = event.clientY\n\n const target = this.target || this.parentElement\n if (target) {\n this.initialScrollLeft = target.scrollLeft\n this.initialScrollTop = target.scrollTop\n }\n\n window.addEventListener('mousemove', this.handleMouseMove.bind(this))\n window.addEventListener('mouseup', this.handleMouseUp.bind(this))\n\n event.preventDefault()\n }\n\n handleMouseMove(event: MouseEvent) {\n if (!this.isDragging) return\n\n const deltaX = event.clientX - this.startX\n const deltaY = event.clientY - this.startY\n\n const target = this.target || this.parentElement\n if (!target) return\n\n const targetRatio = target.scrollHeight / target.scrollWidth\n const thisRatio = this.offsetHeight / this.offsetWidth\n\n const scale =\n targetRatio > thisRatio ? this.offsetHeight / target.scrollHeight : this.offsetWidth / target.scrollWidth\n\n const scrollX = deltaX / scale\n const scrollY = deltaY / scale\n\n target.scrollLeft = this.initialScrollLeft + scrollX\n target.scrollTop = this.initialScrollTop + scrollY\n\n this.updateViewportPosition(1, target.scrollLeft, target.scrollTop) // Assuming no additional transform during drag\n\n event.preventDefault()\n }\n\n handleMouseUp(event: MouseEvent) {\n this.isDragging = false\n window.removeEventListener('mousemove', this.handleMouseMove.bind(this))\n window.removeEventListener('mouseup', this.handleMouseUp.bind(this))\n event.preventDefault()\n }\n\n render() {\n return html`\n <div id=\"minimap\">\n <div id=\"viewport\" @mousedown=${this.handleMouseDown}></div>\n </div>\n `\n }\n}\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { LitElement, PropertyValues } from 'lit';
|
|
2
|
+
/**
|
|
3
|
+
* Example usage:
|
|
4
|
+
*
|
|
5
|
+
* <html>
|
|
6
|
+
* <head>
|
|
7
|
+
* <script type="module" src="path/to/ox-zoomable-image.js"></script>
|
|
8
|
+
* <style>
|
|
9
|
+
* body {
|
|
10
|
+
* margin: 0;
|
|
11
|
+
* overflow: hidden;
|
|
12
|
+
* display: flex;
|
|
13
|
+
* justify-content: center;
|
|
14
|
+
* align-items: center;
|
|
15
|
+
* height: 100vh;
|
|
16
|
+
* }
|
|
17
|
+
* ox-zoomable-image {
|
|
18
|
+
* width: 80%;
|
|
19
|
+
* height: 80%;
|
|
20
|
+
* }
|
|
21
|
+
* </style>
|
|
22
|
+
* </head>
|
|
23
|
+
* <body>
|
|
24
|
+
* <ox-zoomable-image src="path/to/your/image.jpg"></ox-zoomable-image>
|
|
25
|
+
* </body>
|
|
26
|
+
* </html>
|
|
27
|
+
*/
|
|
28
|
+
export declare class OxZoomableImage extends LitElement {
|
|
29
|
+
static styles: import("lit").CSSResult;
|
|
30
|
+
src?: string;
|
|
31
|
+
private zoom;
|
|
32
|
+
private left;
|
|
33
|
+
private top;
|
|
34
|
+
private minZoom;
|
|
35
|
+
private imageWidth;
|
|
36
|
+
private imageHeight;
|
|
37
|
+
private dragStart?;
|
|
38
|
+
private readonly dragEndHandler;
|
|
39
|
+
private readonly dragMoveHandler;
|
|
40
|
+
private readonly dragStartHandler;
|
|
41
|
+
private readonly wheelEventHandler;
|
|
42
|
+
private readonly resetHandler;
|
|
43
|
+
connectedCallback(): void;
|
|
44
|
+
disconnectedCallback(): void;
|
|
45
|
+
updated(changes: PropertyValues<this>): void;
|
|
46
|
+
private calculateMinZoom;
|
|
47
|
+
private onWheelEvent;
|
|
48
|
+
private onDragStart;
|
|
49
|
+
private onDragMove;
|
|
50
|
+
private onDragEnd;
|
|
51
|
+
private onReset;
|
|
52
|
+
private updateTransform;
|
|
53
|
+
private applyBounds;
|
|
54
|
+
}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
import { __decorate } from "tslib";
|
|
2
|
+
import { css, LitElement } from 'lit';
|
|
3
|
+
import { customElement, property, state } from 'lit/decorators.js';
|
|
4
|
+
// Utility function to get the point from MouseEvent or TouchEvent
|
|
5
|
+
function getPoint(e) {
|
|
6
|
+
if (e instanceof MouseEvent && e.button === 0) {
|
|
7
|
+
return { x: e.clientX, y: e.clientY };
|
|
8
|
+
}
|
|
9
|
+
else if (e instanceof TouchEvent && e.touches.length === 1) {
|
|
10
|
+
const touch = e.touches[0];
|
|
11
|
+
return { x: touch.clientX, y: touch.clientY };
|
|
12
|
+
}
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Example usage:
|
|
17
|
+
*
|
|
18
|
+
* <html>
|
|
19
|
+
* <head>
|
|
20
|
+
* <script type="module" src="path/to/ox-zoomable-image.js"></script>
|
|
21
|
+
* <style>
|
|
22
|
+
* body {
|
|
23
|
+
* margin: 0;
|
|
24
|
+
* overflow: hidden;
|
|
25
|
+
* display: flex;
|
|
26
|
+
* justify-content: center;
|
|
27
|
+
* align-items: center;
|
|
28
|
+
* height: 100vh;
|
|
29
|
+
* }
|
|
30
|
+
* ox-zoomable-image {
|
|
31
|
+
* width: 80%;
|
|
32
|
+
* height: 80%;
|
|
33
|
+
* }
|
|
34
|
+
* </style>
|
|
35
|
+
* </head>
|
|
36
|
+
* <body>
|
|
37
|
+
* <ox-zoomable-image src="path/to/your/image.jpg"></ox-zoomable-image>
|
|
38
|
+
* </body>
|
|
39
|
+
* </html>
|
|
40
|
+
*/
|
|
41
|
+
let OxZoomableImage = class OxZoomableImage extends LitElement {
|
|
42
|
+
constructor() {
|
|
43
|
+
super(...arguments);
|
|
44
|
+
this.zoom = 1; // Current zoom level
|
|
45
|
+
this.left = 0; // Horizontal position
|
|
46
|
+
this.top = 0; // Vertical position
|
|
47
|
+
this.minZoom = 1; // Minimum zoom level
|
|
48
|
+
this.imageWidth = 0;
|
|
49
|
+
this.imageHeight = 0;
|
|
50
|
+
// Event listeners bound to the component
|
|
51
|
+
this.dragEndHandler = this.onDragEnd.bind(this);
|
|
52
|
+
this.dragMoveHandler = this.onDragMove.bind(this);
|
|
53
|
+
this.dragStartHandler = this.onDragStart.bind(this);
|
|
54
|
+
this.wheelEventHandler = this.onWheelEvent.bind(this);
|
|
55
|
+
this.resetHandler = this.onReset.bind(this);
|
|
56
|
+
}
|
|
57
|
+
connectedCallback() {
|
|
58
|
+
super.connectedCallback();
|
|
59
|
+
// Register event listeners for zooming and dragging
|
|
60
|
+
this.addEventListener('wheel', this.wheelEventHandler);
|
|
61
|
+
this.addEventListener('mousedown', this.dragStartHandler);
|
|
62
|
+
this.addEventListener('touchstart', this.dragStartHandler);
|
|
63
|
+
this.addEventListener('dblclick', this.resetHandler);
|
|
64
|
+
document.addEventListener('mouseup', this.dragEndHandler);
|
|
65
|
+
document.addEventListener('touchend', this.dragEndHandler);
|
|
66
|
+
document.addEventListener('touchcancel', this.dragEndHandler);
|
|
67
|
+
document.addEventListener('mousemove', this.dragMoveHandler);
|
|
68
|
+
document.addEventListener('touchmove', this.dragMoveHandler);
|
|
69
|
+
this.calculateMinZoom(); // Calculate the minimum zoom level based on the image and container size
|
|
70
|
+
}
|
|
71
|
+
disconnectedCallback() {
|
|
72
|
+
// Remove event listeners when the component is disconnected
|
|
73
|
+
this.removeEventListener('wheel', this.wheelEventHandler);
|
|
74
|
+
this.removeEventListener('mousedown', this.dragStartHandler);
|
|
75
|
+
this.removeEventListener('touchstart', this.dragStartHandler);
|
|
76
|
+
this.removeEventListener('dblclick', this.resetHandler);
|
|
77
|
+
document.removeEventListener('mouseup', this.dragEndHandler);
|
|
78
|
+
document.removeEventListener('touchend', this.dragEndHandler);
|
|
79
|
+
document.removeEventListener('touchcancel', this.dragEndHandler);
|
|
80
|
+
document.removeEventListener('mousemove', this.dragMoveHandler);
|
|
81
|
+
document.removeEventListener('touchmove', this.dragMoveHandler);
|
|
82
|
+
super.disconnectedCallback();
|
|
83
|
+
}
|
|
84
|
+
updated(changes) {
|
|
85
|
+
// Update the background image and transform style when properties change
|
|
86
|
+
if (changes.has('src') && this.src) {
|
|
87
|
+
this.style.setProperty('--background-image', `url('${this.src}')`);
|
|
88
|
+
this.calculateMinZoom(); // Recalculate the minimum zoom level when the source changes
|
|
89
|
+
}
|
|
90
|
+
this.updateTransform(); // Apply the current zoom and position
|
|
91
|
+
}
|
|
92
|
+
calculateMinZoom() {
|
|
93
|
+
// Calculate the minimum zoom level to ensure the image always fills the container
|
|
94
|
+
const img = new Image();
|
|
95
|
+
img.src = this.src || '';
|
|
96
|
+
img.onload = () => {
|
|
97
|
+
this.imageWidth = img.width;
|
|
98
|
+
this.imageHeight = img.height;
|
|
99
|
+
const aspectRatio = img.width / img.height;
|
|
100
|
+
const hostAspectRatio = this.offsetWidth / this.offsetHeight;
|
|
101
|
+
if (aspectRatio < hostAspectRatio) {
|
|
102
|
+
this.minZoom = this.offsetHeight / img.height;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
this.minZoom = this.offsetWidth / img.width;
|
|
106
|
+
}
|
|
107
|
+
this.zoom = 1; // this.minZoom
|
|
108
|
+
this.left = 0; // Center the image
|
|
109
|
+
this.top = 0; // Center the image
|
|
110
|
+
this.updateTransform();
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
onWheelEvent(e) {
|
|
114
|
+
// Handle zoom in and out based on mouse wheel events
|
|
115
|
+
e.preventDefault();
|
|
116
|
+
const delta = Math.sign(e.deltaY);
|
|
117
|
+
const newZoom = Math.max(1, this.zoom * (1 - delta / 20));
|
|
118
|
+
const zoomFactor = newZoom / this.zoom;
|
|
119
|
+
const rect = this.getBoundingClientRect();
|
|
120
|
+
const offsetX = e.clientX - rect.left - rect.width / 2;
|
|
121
|
+
const offsetY = e.clientY - rect.top - rect.height / 2;
|
|
122
|
+
// Adjust the position to zoom in/out relative to the center of the client rect
|
|
123
|
+
this.left -= offsetX * (zoomFactor - 1);
|
|
124
|
+
this.top -= offsetY * (zoomFactor - 1);
|
|
125
|
+
this.zoom = newZoom;
|
|
126
|
+
this.applyBounds(); // Ensure the image stays within bounds
|
|
127
|
+
this.updateTransform(); // Apply the new zoom and position
|
|
128
|
+
}
|
|
129
|
+
onDragStart(e) {
|
|
130
|
+
// Start dragging the image
|
|
131
|
+
const point = getPoint(e);
|
|
132
|
+
if (point) {
|
|
133
|
+
this.dragStart = point;
|
|
134
|
+
e.stopPropagation();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
onDragMove(e) {
|
|
138
|
+
// Move the image based on drag events
|
|
139
|
+
if (!this.dragStart)
|
|
140
|
+
return;
|
|
141
|
+
const point = getPoint(e);
|
|
142
|
+
if (!point)
|
|
143
|
+
return;
|
|
144
|
+
e.stopPropagation();
|
|
145
|
+
e.preventDefault();
|
|
146
|
+
const { x, y } = point;
|
|
147
|
+
this.left += x - this.dragStart.x;
|
|
148
|
+
this.top += y - this.dragStart.y;
|
|
149
|
+
this.dragStart = point;
|
|
150
|
+
this.applyBounds(); // Ensure the image stays within bounds
|
|
151
|
+
this.updateTransform(); // Apply the new position
|
|
152
|
+
}
|
|
153
|
+
onDragEnd(e) {
|
|
154
|
+
// End the drag operation
|
|
155
|
+
if (this.dragStart) {
|
|
156
|
+
e.stopPropagation();
|
|
157
|
+
e.preventDefault();
|
|
158
|
+
this.dragStart = undefined;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
onReset(e) {
|
|
162
|
+
// Reset zoom and position to initial state
|
|
163
|
+
this.zoom = 1;
|
|
164
|
+
this.left = 0;
|
|
165
|
+
this.top = 0;
|
|
166
|
+
this.updateTransform();
|
|
167
|
+
}
|
|
168
|
+
updateTransform() {
|
|
169
|
+
// Apply the current zoom and position to the image
|
|
170
|
+
this.style.setProperty('--image-transform', `scale(${this.zoom}) translate(${this.left}px, ${this.top}px)`);
|
|
171
|
+
}
|
|
172
|
+
applyBounds() {
|
|
173
|
+
// Ensure the image stays within the bounds of the container
|
|
174
|
+
const hostWidth = this.offsetWidth;
|
|
175
|
+
const hostHeight = this.offsetHeight;
|
|
176
|
+
const aspectRatio = this.imageHeight / this.imageWidth;
|
|
177
|
+
const hostAspectRatio = hostHeight / hostWidth;
|
|
178
|
+
if (aspectRatio < hostAspectRatio) {
|
|
179
|
+
/* image ratio is wider than host */
|
|
180
|
+
var minX = Math.min(0, (-hostWidth * (this.zoom - 1)) / 2 / this.zoom);
|
|
181
|
+
var maxX = -minX;
|
|
182
|
+
var minY = (hostHeight - hostWidth * aspectRatio * this.zoom) / 2 / this.zoom;
|
|
183
|
+
minY = Math.min(minY, -minY);
|
|
184
|
+
var maxY = -minY;
|
|
185
|
+
this.left = Math.max(minX, Math.min(this.left, maxX));
|
|
186
|
+
this.top = Math.max(minY, Math.min(this.top, maxY));
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
var minX = (hostWidth - (hostHeight / aspectRatio) * this.zoom) / 2 / this.zoom;
|
|
190
|
+
minX = Math.min(minX, -minX);
|
|
191
|
+
var maxX = -minX;
|
|
192
|
+
var minY = Math.min(0, (-hostHeight * (this.zoom - 1)) / 2 / this.zoom);
|
|
193
|
+
var maxY = -minY;
|
|
194
|
+
this.left = Math.max(minX, Math.min(this.left, maxX));
|
|
195
|
+
this.top = Math.max(minY, Math.min(this.top, maxY));
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
// Define CSS styles for the component
|
|
200
|
+
OxZoomableImage.styles = css `
|
|
201
|
+
:host {
|
|
202
|
+
display: block;
|
|
203
|
+
position: relative;
|
|
204
|
+
width: 100%;
|
|
205
|
+
height: 100%;
|
|
206
|
+
overflow: hidden;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
:host::before {
|
|
210
|
+
content: '';
|
|
211
|
+
display: block;
|
|
212
|
+
position: absolute;
|
|
213
|
+
top: 0;
|
|
214
|
+
right: 0;
|
|
215
|
+
width: 100%;
|
|
216
|
+
height: 100%;
|
|
217
|
+
background-image: var(
|
|
218
|
+
--background-image,
|
|
219
|
+
linear-gradient(var(--primary-color, lightgray), var(--primary-color, lightgray))
|
|
220
|
+
);
|
|
221
|
+
transform: var(--image-transform, '');
|
|
222
|
+
background-repeat: no-repeat;
|
|
223
|
+
background-position: center;
|
|
224
|
+
background-size: contain;
|
|
225
|
+
}
|
|
226
|
+
`;
|
|
227
|
+
__decorate([
|
|
228
|
+
property({ type: String })
|
|
229
|
+
], OxZoomableImage.prototype, "src", void 0);
|
|
230
|
+
__decorate([
|
|
231
|
+
state()
|
|
232
|
+
], OxZoomableImage.prototype, "zoom", void 0);
|
|
233
|
+
__decorate([
|
|
234
|
+
state()
|
|
235
|
+
], OxZoomableImage.prototype, "left", void 0);
|
|
236
|
+
__decorate([
|
|
237
|
+
state()
|
|
238
|
+
], OxZoomableImage.prototype, "top", void 0);
|
|
239
|
+
__decorate([
|
|
240
|
+
state()
|
|
241
|
+
], OxZoomableImage.prototype, "minZoom", void 0);
|
|
242
|
+
__decorate([
|
|
243
|
+
state()
|
|
244
|
+
], OxZoomableImage.prototype, "imageWidth", void 0);
|
|
245
|
+
__decorate([
|
|
246
|
+
state()
|
|
247
|
+
], OxZoomableImage.prototype, "imageHeight", void 0);
|
|
248
|
+
OxZoomableImage = __decorate([
|
|
249
|
+
customElement('ox-zoomable-image')
|
|
250
|
+
], OxZoomableImage);
|
|
251
|
+
export { OxZoomableImage };
|
|
252
|
+
//# sourceMappingURL=ox-zoomable-image.js.map
|