@hyper-proto/iv-viewer 2.3.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 +249 -0
- package/dist/iv-viewer.css +221 -0
- package/dist/iv-viewer.es.js +1432 -0
- package/dist/iv-viewer.js +1442 -0
- package/dist/iv-viewer.min.css +1 -0
- package/dist/iv-viewer.min.js +1 -0
- package/iv-viewer.d.ts +54 -0
- package/lib/FullScreen.js +114 -0
- package/lib/ImageViewer.js +962 -0
- package/lib/Slider.js +109 -0
- package/lib/dist.js +11 -0
- package/lib/index.js +22 -0
- package/lib/iv-viewer.css +221 -0
- package/lib/util.js +174 -0
- package/package.json +60 -0
- package/src/FullScreen.js +76 -0
- package/src/ImageViewer.js +988 -0
- package/src/Slider.js +97 -0
- package/src/dist.js +6 -0
- package/src/index.js +5 -0
- package/src/scss/_iv-viewer.scss +268 -0
- package/src/scss/_variables.scss +43 -0
- package/src/scss/build.scss +1 -0
- package/src/util.js +158 -0
package/src/Slider.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { noop } from './util';
|
|
2
|
+
|
|
3
|
+
class Slider {
|
|
4
|
+
constructor (container, {
|
|
5
|
+
onStart, onMove, onEnd, isSliderEnabled,
|
|
6
|
+
}) {
|
|
7
|
+
this.container = container;
|
|
8
|
+
this.isSliderEnabled = isSliderEnabled;
|
|
9
|
+
this.onStart = onStart || noop;
|
|
10
|
+
this.onMove = onMove || noop;
|
|
11
|
+
this.onEnd = onEnd || noop;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
startHandler = (eStart) => {
|
|
15
|
+
if (!this.isSliderEnabled()) return;
|
|
16
|
+
|
|
17
|
+
this.removeListeners();
|
|
18
|
+
|
|
19
|
+
eStart.preventDefault();
|
|
20
|
+
|
|
21
|
+
const { moveHandler, endHandler, onStart } = this;
|
|
22
|
+
|
|
23
|
+
const isTouchEvent = eStart.type === 'touchstart' || eStart.type === 'touchend';
|
|
24
|
+
|
|
25
|
+
this.touchMoveEvent = isTouchEvent ? 'touchmove' : 'mousemove';
|
|
26
|
+
this.touchEndEvent = isTouchEvent ? 'touchend' : 'mouseup';
|
|
27
|
+
|
|
28
|
+
this.sx = isTouchEvent ? eStart.touches[0].clientX : eStart.clientX;
|
|
29
|
+
|
|
30
|
+
this.sy = isTouchEvent ? eStart.touches[0].clientY : eStart.clientY;
|
|
31
|
+
|
|
32
|
+
onStart(eStart, {
|
|
33
|
+
x: this.sx,
|
|
34
|
+
y: this.sy,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
// add listeners
|
|
38
|
+
document.addEventListener(this.touchMoveEvent, moveHandler);
|
|
39
|
+
document.addEventListener(this.touchEndEvent, endHandler);
|
|
40
|
+
/*
|
|
41
|
+
add end handler in context menu as well.
|
|
42
|
+
As mouseup event is not trigger on context menu open
|
|
43
|
+
https://bugs.chromium.org/p/chromium/issues/detail?id=506801
|
|
44
|
+
*/
|
|
45
|
+
document.addEventListener('contextmenu', endHandler);
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
moveHandler = (eMove) => {
|
|
49
|
+
if (!this.isSliderEnabled()) return;
|
|
50
|
+
|
|
51
|
+
eMove.preventDefault();
|
|
52
|
+
const { sx, sy, onMove } = this;
|
|
53
|
+
|
|
54
|
+
const isTouchEvent = this.touchMoveEvent === 'touchmove';
|
|
55
|
+
|
|
56
|
+
// get the coordinates
|
|
57
|
+
const mx = isTouchEvent ? eMove.touches[0].clientX : eMove.clientX;
|
|
58
|
+
const my = isTouchEvent ? eMove.touches[0].clientY : eMove.clientY;
|
|
59
|
+
|
|
60
|
+
onMove(eMove, {
|
|
61
|
+
dx: mx - sx,
|
|
62
|
+
dy: my - sy,
|
|
63
|
+
mx,
|
|
64
|
+
my,
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
endHandler = () => {
|
|
69
|
+
if (!this.isSliderEnabled()) return;
|
|
70
|
+
this.removeListeners();
|
|
71
|
+
this.onEnd();
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
// remove previous events if it's not removed
|
|
75
|
+
// - Case when while sliding mouse moved out of document and released there
|
|
76
|
+
removeListeners () {
|
|
77
|
+
if (!this.touchMoveEvent) return;
|
|
78
|
+
document.removeEventListener(this.touchMoveEvent, this.moveHandler);
|
|
79
|
+
document.removeEventListener(this.touchEndEvent, this.endHandler);
|
|
80
|
+
document.removeEventListener('contextmenu', this.endHandler);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
init () {
|
|
84
|
+
['touchstart', 'mousedown'].forEach((evt) => {
|
|
85
|
+
this.container.addEventListener(evt, this.startHandler);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
destroy () {
|
|
90
|
+
['touchstart', 'mousedown'].forEach((evt) => {
|
|
91
|
+
this.container.removeEventListener(evt, this.startHandler);
|
|
92
|
+
});
|
|
93
|
+
this.removeListeners();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export default Slider;
|
package/src/dist.js
ADDED
package/src/index.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
@use './variables' as *;
|
|
2
|
+
|
|
3
|
+
.iv {
|
|
4
|
+
&-container {
|
|
5
|
+
overflow: hidden;
|
|
6
|
+
position: relative;
|
|
7
|
+
user-select: none;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
&-fullscreen {
|
|
11
|
+
position: fixed;
|
|
12
|
+
background: $iv-dark-gray;
|
|
13
|
+
width: 100%;
|
|
14
|
+
height: 100%;
|
|
15
|
+
top: 0;
|
|
16
|
+
left: 0;
|
|
17
|
+
display: none;
|
|
18
|
+
z-index: 1000;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
&-fullscreen-container {
|
|
22
|
+
position: relative;
|
|
23
|
+
height: 100%;
|
|
24
|
+
width: 100%;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
&-fullscreen-close {
|
|
28
|
+
position: absolute;
|
|
29
|
+
width: $iv-close-icon-size;
|
|
30
|
+
height: $iv-close-icon-size;
|
|
31
|
+
right: calc($iv-boundary-space / 2);
|
|
32
|
+
top: calc($iv-boundary-space / 2);
|
|
33
|
+
padding: calc($iv-boundary-space / 2);
|
|
34
|
+
cursor: pointer;
|
|
35
|
+
text-align: center;
|
|
36
|
+
overflow: hidden;
|
|
37
|
+
text-shadow: $iv-fullscreen-close-text-shadow;
|
|
38
|
+
transition: all ease 200ms;
|
|
39
|
+
|
|
40
|
+
&:after,
|
|
41
|
+
&:before {
|
|
42
|
+
content: "";
|
|
43
|
+
height: $iv-fullscreen-close-height;
|
|
44
|
+
width: $iv-close-icon-size;
|
|
45
|
+
background: $iv-white;
|
|
46
|
+
position: absolute;
|
|
47
|
+
top: 50%;
|
|
48
|
+
left: 50%;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
&:before {
|
|
52
|
+
transform: translate(-50%, -50%) rotate(45deg);
|
|
53
|
+
}
|
|
54
|
+
&:after {
|
|
55
|
+
transform: translate(-50%, -50%) rotate(-45deg);
|
|
56
|
+
}
|
|
57
|
+
&:hover {
|
|
58
|
+
transform: rotate(90deg);
|
|
59
|
+
transform-origin: 50% 50%;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/***** snap view css *****/
|
|
64
|
+
&-snap-view {
|
|
65
|
+
width: calc($iv-snap-view-width + 2px);
|
|
66
|
+
height: calc($iv-snap-view-height + 2px);
|
|
67
|
+
position: absolute;
|
|
68
|
+
top: $iv-boundary-space;
|
|
69
|
+
border: 1px solid $iv-snap-view-border-color;
|
|
70
|
+
background: $iv-black;
|
|
71
|
+
z-index: 100;
|
|
72
|
+
box-sizing: border-box;
|
|
73
|
+
transition: opacity ease 400ms;
|
|
74
|
+
opacity: 0;
|
|
75
|
+
|
|
76
|
+
@if ($iv-snap-view-on-left) {
|
|
77
|
+
left: $iv-boundary-space;
|
|
78
|
+
} @else {
|
|
79
|
+
right: $iv-boundary-space;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
&-snap-image-wrap {
|
|
84
|
+
display: inline-block;
|
|
85
|
+
position: absolute;
|
|
86
|
+
max-width: $iv-snap-view-width;
|
|
87
|
+
max-height: $iv-snap-view-height;
|
|
88
|
+
top: 50%;
|
|
89
|
+
left: 50%;
|
|
90
|
+
transform: translate(-50%, -50%);
|
|
91
|
+
overflow: hidden;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
&-snap-image {
|
|
95
|
+
position: relative;
|
|
96
|
+
touch-action: none;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
&-snap-handle {
|
|
100
|
+
box-sizing: border-box;
|
|
101
|
+
position: absolute;
|
|
102
|
+
border: $iv-zoom-handle-border;
|
|
103
|
+
transform: translate3d(0, 0, 0);
|
|
104
|
+
box-shadow: 0 0 0 200px rgba($iv-black, 0.5);
|
|
105
|
+
cursor: pointer;
|
|
106
|
+
cursor: grab;
|
|
107
|
+
|
|
108
|
+
&:active {
|
|
109
|
+
cursor: grabbing;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/*** zoom actions ***/
|
|
114
|
+
|
|
115
|
+
&-zoom-actions {
|
|
116
|
+
width: 100%;
|
|
117
|
+
box-sizing: content-box;
|
|
118
|
+
position: absolute;
|
|
119
|
+
top: 150px;
|
|
120
|
+
left: -1px;
|
|
121
|
+
height: $iv-zoom-slider-height;
|
|
122
|
+
border: $iv-zoom-handle-border;
|
|
123
|
+
border-top: 0;
|
|
124
|
+
background: rgba($iv-black, 0.3);
|
|
125
|
+
|
|
126
|
+
&--has-buttons {
|
|
127
|
+
.iv-zoom-slider {
|
|
128
|
+
left: $iv-zoom-button-width;
|
|
129
|
+
right: $iv-zoom-button-width;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
&-zoom-handle {
|
|
135
|
+
width: $iv-zoom-handle-width;
|
|
136
|
+
height: $iv-zoom-handle-height;
|
|
137
|
+
background: $iv-handle-color;
|
|
138
|
+
position: absolute;
|
|
139
|
+
cursor: pointer;
|
|
140
|
+
cursor: grab;
|
|
141
|
+
|
|
142
|
+
&:active {
|
|
143
|
+
cursor: grabbing;
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
&-zoom-slider {
|
|
148
|
+
box-sizing: inherit;
|
|
149
|
+
position: absolute;
|
|
150
|
+
top: 0;
|
|
151
|
+
bottom: 0;
|
|
152
|
+
left: 0;
|
|
153
|
+
right: 0;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
&-button-zoom {
|
|
157
|
+
position: absolute;
|
|
158
|
+
top: 0;
|
|
159
|
+
bottom: 0;
|
|
160
|
+
width: $iv-zoom-button-width;
|
|
161
|
+
cursor: pointer;
|
|
162
|
+
display: flex;
|
|
163
|
+
align-items: center;
|
|
164
|
+
justify-content: center;
|
|
165
|
+
&:before,
|
|
166
|
+
&:after {
|
|
167
|
+
content: "";
|
|
168
|
+
height: $iv-zoom-button-icon-height;
|
|
169
|
+
width: $iv-zoom-button-icon-width;
|
|
170
|
+
background: $iv-zoom-button-color;
|
|
171
|
+
position: absolute;
|
|
172
|
+
}
|
|
173
|
+
&--in,
|
|
174
|
+
&--out {
|
|
175
|
+
@extend .iv-button-zoom;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
&--in {
|
|
179
|
+
right: 0;
|
|
180
|
+
&:after {
|
|
181
|
+
transform: rotate(90deg);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
&--out {
|
|
185
|
+
left: 0;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**** snap view css end *****/
|
|
190
|
+
&-image-mode {
|
|
191
|
+
display: $iv-image-mode-display;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
&-image-view {
|
|
195
|
+
position: absolute;
|
|
196
|
+
height: 100%;
|
|
197
|
+
width: 100%;
|
|
198
|
+
top: 0;
|
|
199
|
+
left: 0;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
&-image-wrap {
|
|
203
|
+
display: inline-block;
|
|
204
|
+
&:active {
|
|
205
|
+
cursor: move;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
&-image {
|
|
210
|
+
max-width: 100%;
|
|
211
|
+
max-height: 100%;
|
|
212
|
+
position: absolute;
|
|
213
|
+
touch-action: none;
|
|
214
|
+
transform: translate3d(0, 0, 0);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
&-loader {
|
|
218
|
+
top: 50%;
|
|
219
|
+
left: 50%;
|
|
220
|
+
border-radius: 50%;
|
|
221
|
+
width: $iv-loader-width;
|
|
222
|
+
height: $iv-loader-width;
|
|
223
|
+
z-index: 100;
|
|
224
|
+
margin-top: -16px;
|
|
225
|
+
margin-left: -16px;
|
|
226
|
+
font-size: 5px;
|
|
227
|
+
position: absolute;
|
|
228
|
+
text-indent: -9999em;
|
|
229
|
+
border: $iv-loader-border-color;
|
|
230
|
+
border-left: $iv-loader-active-border-color;
|
|
231
|
+
transform: translateZ(0);
|
|
232
|
+
animation: loading-icon 1.1s infinite linear;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
&-loader:after {
|
|
236
|
+
width: 10em;
|
|
237
|
+
height: 10em;
|
|
238
|
+
border-radius: 50%;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@-webkit-keyframes loading-icon {
|
|
242
|
+
0% {
|
|
243
|
+
-webkit-transform: rotate(0deg);
|
|
244
|
+
transform: rotate(0deg);
|
|
245
|
+
}
|
|
246
|
+
100% {
|
|
247
|
+
-webkit-transform: rotate(360deg);
|
|
248
|
+
transform: rotate(360deg);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
@keyframes loading-icon {
|
|
252
|
+
0% {
|
|
253
|
+
-webkit-transform: rotate(0deg);
|
|
254
|
+
transform: rotate(0deg);
|
|
255
|
+
}
|
|
256
|
+
100% {
|
|
257
|
+
-webkit-transform: rotate(360deg);
|
|
258
|
+
transform: rotate(360deg);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
@media screen and (max-width: 767px) {
|
|
263
|
+
&-snap-view {
|
|
264
|
+
z-index: -1;
|
|
265
|
+
visibility: hidden;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
//=========colors=========//
|
|
2
|
+
$iv-white: #fff !default;
|
|
3
|
+
$iv-light-gray: #aaa !default;
|
|
4
|
+
$iv-gray: #6d6d6d !default;
|
|
5
|
+
$iv-dark-gray: #0d0d0d !default;
|
|
6
|
+
$iv-black: black;
|
|
7
|
+
|
|
8
|
+
//========variables========//
|
|
9
|
+
$iv-close-icon-size: 24px !default;
|
|
10
|
+
$iv-boundary-space: 20px !default;
|
|
11
|
+
$iv-handle-color: $iv-white !default;
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
//========snapview========//
|
|
15
|
+
$iv-snap-view-border-color: $iv-light-gray !default;
|
|
16
|
+
$iv-snap-view-width: 150px !default;
|
|
17
|
+
$iv-snap-view-height: 150px !default;
|
|
18
|
+
$iv-snap-view-on-left: true !default;
|
|
19
|
+
|
|
20
|
+
//========zoom========//
|
|
21
|
+
$iv-zoom-slider-height: 20px !default;
|
|
22
|
+
$iv-zoom-handle-height: $iv-zoom-slider-height !default;
|
|
23
|
+
$iv-zoom-handle-width: 20px !default;
|
|
24
|
+
$iv-zoom-handle-border: 1px solid $iv-light-gray !default;
|
|
25
|
+
$iv-zoom-button-width: 24px !default;
|
|
26
|
+
$iv-zoom-button-icon-height: 2px !default;
|
|
27
|
+
$iv-zoom-button-icon-width: 10px !default;
|
|
28
|
+
$iv-zoom-button-color: $iv-white !default;
|
|
29
|
+
$iv-zoom-button-spacing: 4px !default;
|
|
30
|
+
|
|
31
|
+
//========fullscreen========//
|
|
32
|
+
$iv-fullscreen-bg-color: $iv-dark-gray !default;
|
|
33
|
+
$iv-fullscreen-close-text-shadow: 0 0 3px $iv-gray !default;
|
|
34
|
+
$iv-fullscreen-close-height: 4px !default;
|
|
35
|
+
|
|
36
|
+
//========imagemode========//
|
|
37
|
+
$iv-image-mode-display: inline-block !default;
|
|
38
|
+
|
|
39
|
+
//========loader========//
|
|
40
|
+
$iv-loader-width: 32px !default;
|
|
41
|
+
$iv-loader-height: 32px !default;
|
|
42
|
+
$iv-loader-border-color: 1.1em solid rgba($iv-black, 0.2) !default;
|
|
43
|
+
$iv-loader-active-border-color: 1.1em solid $iv-white !default;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@use './iv-viewer';
|
package/src/util.js
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// constants
|
|
2
|
+
export const ZOOM_CONSTANT = 15; // increase or decrease value for zoom on mouse wheel
|
|
3
|
+
export const MOUSE_WHEEL_COUNT = 5; // A mouse delta after which it should stop preventing default behaviour of mouse wheel
|
|
4
|
+
|
|
5
|
+
export function noop () {}
|
|
6
|
+
export function preventDefault (e) {
|
|
7
|
+
e.preventDefault();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// ease out method
|
|
11
|
+
/*
|
|
12
|
+
t : current time,
|
|
13
|
+
b : initial value,
|
|
14
|
+
c : changed value,
|
|
15
|
+
d : duration
|
|
16
|
+
*/
|
|
17
|
+
export function easeOutQuart (t, b, c, d) {
|
|
18
|
+
t /= d;
|
|
19
|
+
t -= 1;
|
|
20
|
+
return -c * (t * t * t * t - 1) + b;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function createElement (options) {
|
|
24
|
+
const elem = document.createElement(options.tagName);
|
|
25
|
+
if (options.id) elem.id = options.id;
|
|
26
|
+
if (options.html) elem.innerHTML = options.html;
|
|
27
|
+
if (options.className) elem.className = options.className;
|
|
28
|
+
if (options.src) elem.src = options.src;
|
|
29
|
+
if (options.style) elem.style.cssText = options.style;
|
|
30
|
+
if (options.child) elem.appendChild(options.child);
|
|
31
|
+
|
|
32
|
+
// Insert before
|
|
33
|
+
if (options.insertBefore) {
|
|
34
|
+
options.parent.insertBefore(elem, options.insertBefore);
|
|
35
|
+
|
|
36
|
+
// Standard append
|
|
37
|
+
} else {
|
|
38
|
+
options.parent.appendChild(elem);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return elem;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// method to add class
|
|
45
|
+
export function addClass (el, className) {
|
|
46
|
+
const classNameAry = className.split(' ');
|
|
47
|
+
|
|
48
|
+
if (classNameAry.length > 1) {
|
|
49
|
+
classNameAry.forEach((classItem) => addClass(el, classItem));
|
|
50
|
+
} else if (el.classList) {
|
|
51
|
+
el.classList.add(className);
|
|
52
|
+
} else {
|
|
53
|
+
el.className += ` ${className}`;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// method to remove class
|
|
58
|
+
export function removeClass (el, className) {
|
|
59
|
+
const classNameAry = className.split(' ');
|
|
60
|
+
if (classNameAry.length > 1) {
|
|
61
|
+
classNameAry.forEach((classItem) => removeClass(el, classItem));
|
|
62
|
+
} else if (el.classList) {
|
|
63
|
+
el.classList.remove(className);
|
|
64
|
+
} else {
|
|
65
|
+
el.className = el.className.replace(new RegExp(`(^|\\b)${className.split(' ').join('|')}(\\b|$)`, 'gi'), ' ');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// function to check if image is loaded
|
|
70
|
+
export function imageLoaded (img) {
|
|
71
|
+
return img.complete && (typeof img.naturalWidth === 'undefined' || img.naturalWidth !== 0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export function toArray (list) {
|
|
75
|
+
if (!(list instanceof NodeList || list instanceof HTMLCollection)) return [list];
|
|
76
|
+
return Array.prototype.slice.call(list);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function assign (target, ...rest) {
|
|
80
|
+
rest.forEach((obj) => {
|
|
81
|
+
Object.keys(obj).forEach((key) => {
|
|
82
|
+
target[key] = obj[key];
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
return target;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function css (elements, properties) {
|
|
89
|
+
const elmArray = toArray(elements);
|
|
90
|
+
|
|
91
|
+
if (typeof properties === 'string') {
|
|
92
|
+
return window.getComputedStyle(elmArray[0])[properties];
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
elmArray.forEach((element) => {
|
|
96
|
+
Object.keys(properties).forEach((key) => {
|
|
97
|
+
const value = properties[key];
|
|
98
|
+
element.style[key] = value;
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export function removeCss (element, property) {
|
|
106
|
+
element.style.removeProperty(property);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function wrap (element, { tag = 'div', className, id, style }) {
|
|
110
|
+
const wrapper = document.createElement(tag);
|
|
111
|
+
if (className) wrapper.className = className;
|
|
112
|
+
if (id) wrapper.id = id;
|
|
113
|
+
if (style) wrapper.style = style;
|
|
114
|
+
element.parentNode.insertBefore(wrapper, element);
|
|
115
|
+
element.parentNode.removeChild(element);
|
|
116
|
+
wrapper.appendChild(element);
|
|
117
|
+
return wrapper;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export function unwrap (element) {
|
|
121
|
+
const parent = element.parentNode;
|
|
122
|
+
|
|
123
|
+
if (parent !== document.body) {
|
|
124
|
+
parent.parentNode.insertBefore(element, parent);
|
|
125
|
+
parent.parentNode.removeChild(parent);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
export function remove (elements) {
|
|
130
|
+
const elmArray = toArray(elements);
|
|
131
|
+
elmArray.forEach((element) => {
|
|
132
|
+
element.parentNode.removeChild(element);
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function clamp (num, min, max) {
|
|
137
|
+
return Math.min(Math.max(num, min), max);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function assignEvent (element, events, handler) {
|
|
141
|
+
if (typeof events === 'string') events = [events];
|
|
142
|
+
|
|
143
|
+
events.forEach((event) => {
|
|
144
|
+
element.addEventListener(event, handler);
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
return () => {
|
|
148
|
+
events.forEach((event) => {
|
|
149
|
+
element.removeEventListener(event, handler);
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export function getTouchPointsDistance (touches) {
|
|
155
|
+
const touch0 = touches[0];
|
|
156
|
+
const touch1 = touches[1];
|
|
157
|
+
return Math.sqrt((touch1.pageX - touch0.pageX) ** 2 + (touch1.pageY - touch0.pageY) ** 2);
|
|
158
|
+
}
|