-
Notifications
You must be signed in to change notification settings - Fork 0
/
component.htpl
199 lines (166 loc) · 7.07 KB
/
component.htpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
<template id="zoomable-img">
<style>
/*--- Common ----------------------------------------------------------------*/
:host {
/* Defaults for the custom props.
(NOTE: CSS is too stupid to allow optional init of the same prop. :-/ ) */
--z-thumb-w: var(--thumb-w, 100px);
--z-zoomv-w: var(--zoomv-w, 500px);
--z-zoomv-border-w: var(--zoomv-border-w, 1px);
--z-zoomv-border-s: var(--zoomv-border-s, solid);
--z-zoomv-border-c: var(--zoomv-border-c, grey);
--z-zoomv-border-r: var(--zoomv-border-r, 1px);
--z-magicon-c: var(--magicon-c, black);
--z-magicon-bg: var(--magicon-bg, lightgrey);
--z-magicon-op: var(--magicon-op, 0.3);
--z-magicon-h: var(--magicon-h, 12px);
border: 1px solid grey; /* Clients can override/disable; I find it better to have it by default. */
position: relative;
display: inline-block; /*! This kills (viewport-)width-percent sizing, unfortunately. */
vertical-align: top;
}
#zoomview, img { margin: 0; padding: 0; }
img {
display: block; /* Get rid of the descender gap below the images... */
}
#zoomview {
background-position: 50% 50%;
width: 100px; width: var(--z-thumb-w);
overflow: hidden;
cursor: zoom-in;
}
/* thumbnail */
#thumb {
width: 100px; width: var(--z-thumb-w);
cursor: zoom-in;
}
/* full-size img */
#zoomview img {
width: 100%; /* Without this, the image will grow to a full-height, but horiz. cropped narrow rectangle! */
}
/* Hide the full-size image, while zooming/panning, allowing to show the backgnd. img. */
/* This img. also a) guides the aspect-ratio when sizing the FIGURE,
and b) resets to thumbnail view, when not zooming. */
#zoomview:hover img { visibility: hidden; }
#magicon {
user-select: none;
font-size: var(--z-magicon-h);
position: absolute;
bottom: 0; right: 0;
padding: 1px 2px;
border: 1px dotted var(--z-magicon-c);
color: var(--z-magicon-c); background: var(--z-magicon-bg);
opacity: var(--z-magicon-op);
}
/* Alternative way to show the mag. symbol, but restricted to plain text: */
/*#magicon::before { inline; content: "🔍"; } */
:host(:hover) #magicon { visibility: hidden; }
/*--- Basic in-place zoom ---------------------------------------------------*/
/* In this mode, there's no separate thumbnail, so the full-size image is shown
when no zooming, to reset the panning position & zoom level. */
:host(.basic) {
/* remove unwanted default border from the zoom view */
--z-zoomv-border-w: var(--zoomv-border-w, 0px);
}
:host(.basic) #thumb { display: none; }
:host(.basic) #zoomview:hover {
width: 500px; width: var(--z-zoomv-w);
transition: width 0.1s;
border: var(--z-zoomv-border-w) var(--z-zoomv-border-s) var(--z-zoomv-border-c);
border-radius: var(--z-zoomv-border-r); /* Does nothing, for some reason, perhaps only inside another border... */
}
/*--- In-place zoom ---------------------------------------------------------*/
/* In this mode, there's a separate thumbnail to support proper sizing, because
the zoomed view is not part of the content flow (-> `pos.: abs.`). */
:host(.inplace) #zoomview {
position: absolute; /* cover the thumbnail, wo. affecting the layout */
top: 0; left: 0;
width: 100px; width: var(--z-thumb-w);
}
:host(.inplace) #zoomview:hover {
width: 500px; width: var(--z-zoomv-w);
transition: width 0.1s;
border: var(--z-zoomv-border-w) var(--z-zoomv-border-s) var(--z-zoomv-border-c);
border-radius: var(--z-zoomv-border-r);
z-index: 10; /* some subsequent elements did cover this otherwise */
}
/*--- Popup zoom ------------------------------------------------------------*/
/* The magnified view is as separate image, only shown, when hovering the thumb. */
/* In this mode, the full-size image must be explicitly hidden, as the default
"hide on hover" does not apply here (because it's a different element). */
:host(.popup) #zoomview img { visibility: hidden; }
:host(.popup) #zoomview { display: none; }
:host(.popup) > img:hover ~ #zoomview {
display: inline; /* turn displaying back on; `inline` for preserving the vert. pos. */
position: absolute; /* remove from flow, leave original pos. */
top: 0; left: 100px; left: var(--z-thumb-w);
margin-left: 1ex; margin-top: -1ex;
width: 500px; width: var(--z-zoomv-w);
-transition: width 0.1s; /* does nothing in Chrome */
z-index: 10; /* some subsequent elements did cover this otherwise */
border: var(--z-zoomv-border-w) var(--z-zoomv-border-s) var(--z-zoomv-border-c);
border-radius: var(--z-zoomv-border-r);
}
</style>
<img id='thumb' src='placeholder.jpg' onmousemove=''>
<figure id='zoomview' style='background-image: url(placeholder.jpg)' onmousemove=''>
<img id='large' src='placeholder.jpg'>
</figure>
<div id='magicon'>🔍</div>
</template>
<!-- See the separate .js, loaded from test.html "manually" (until HTML import becomes a thing again). :-/
<script onload="?">//---------------------------------------------------------------------
customElements.define('z-img', class extends HTMLElement {
constructor() {
super();
// Attributes are generally not available in the ctor!
//console.log("zimg ctor, this.classList=" + this.classList);
this.tpl = document.getElementById('zoomable-img').content;
this.shdom = this.attachShadow({mode: 'open'});
this.shdom.appendChild(this.tpl.cloneNode(true));
//console.log("zimg ctor: " + this.shdom)
}
connectedCallback() {
//console.log("zimg connect: this.classList=" + this.classList
// + ", src=" + this.getAttribute('src'));
// Make sure a known mode is set (falling back to a default):
const cl = this.classList;
if (! (cl.contains('basic') || cl.contains('inplace') || cl.contains('popup')) )
cl.add('popup');
const src = this.getAttribute('src');
const thumb = this.shdom.getElementById('thumb');
const large = this.shdom.getElementById('large');
const zoomv = this.shdom.getElementById('zoomview');
// Set the 'src' img URL where needed:
thumb.setAttribute('src', src);
large.setAttribute('src', src);
zoomv.style = 'background-image: url(' + src + ')';
// Setup the event handlers:
if (cl.contains('popup')) {
thumb.onmousemove = this.popup_zoom.bind(this);
} else {
zoomv.onmousemove = this.zoom.bind(this);
}
}
zoom(e) { this.zoompanner(e, e.currentTarget, e.currentTarget); }
popup_zoom(e) { this.zoompanner(e, e.currentTarget, e.currentTarget.nextElementSibling); }
zoompanner(e, zoompad, zoomview) {
const img = zoomview.getElementsByTagName('img')[0];
if (img.naturalHeight < img.height || img.naturalWidth < img.width) {
zoomview.style.backgroundSize = 'cover';
return;
}
let offsetX = e.offsetX !== null ? e.offsetX : e.touches[0].pageX;
let offsetY = e.offsetY !== null ? e.offsetY : e.touches[0].pageY;
//console.log("X=" + offsetX + ", Y=" + offsetY);
let x = offsetX / zoompad.offsetWidth * 100
let y = offsetY / zoompad.offsetHeight * 100
// Yes, it did go to negative at the edges (depending on the cursor?), causing wraparound of the bg img...:
if (x < 0) x = 0;
if (y < 0) y = 0;
//console.log(zoomview.style.backgroundPosition + " -> " + "zbX=" + x + ", zbY=" + y);
zoomview.style.backgroundPosition = x + '% ' + y + '%';
}
});
</script>
-->