emacroh5lib 1.0.38 → 1.0.41

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.
@@ -0,0 +1,443 @@
1
+ <template>
2
+ <div class="duo-viewer" v-if="show" ref="duoViewer" @click="clickAgent">
3
+ <div class="duo-viewer-mask">
4
+ <video :width="width" :height="height" :src="realSrc" type="video/mp4" class="duo-viewer-mask__image"
5
+ controls="controls" autoplay="autoplay" loop="loop">
6
+ 您的浏览器不支持 HTML5 video 标签。
7
+ </video>
8
+ </div>
9
+ <div class="duo-viewer-footer" v-if="showThumbnail">
10
+ <div class="duo-viewer-footer__title">{{ realName }}</div>
11
+ <div class="duo-viewer-footer__toolbar">
12
+ <ul>
13
+ <li class="duo-viewer-footer__zoom-in" data-viewer-action="zoom-in"></li>
14
+ <li class="duo-viewer-footer__zoom-out" data-viewer-action="zoom-out"></li>
15
+ <li class="duo-viewer-footer__one-to-one" data-viewer-action="one-to-one"></li>
16
+ <li class="duo-viewer-footer__prev" data-viewer-action="prev"></li>
17
+
18
+ <li class="duo-viewer-footer__play" data-viewer-action="play"></li>
19
+
20
+ <li class="duo-viewer-footer__next" data-viewer-action="next"></li>
21
+ <li class="duo-viewer-footer__reset" data-viewer-action="reset"></li>
22
+ <li class="duo-viewer-footer__rotate-left" data-viewer-action="rotate-left"></li>
23
+ <li class="duo-viewer-footer__rotate-right" data-viewer-action="rotate-right"></li>
24
+ </ul>
25
+ </div>
26
+ <div class="duo-viewer-footer__navbar">
27
+ <div class="duo-viewer-footer__navbar-thumbnail-wrap">
28
+ <div ref="duoViewerImageThumbnailList" class="duo-viewer-footer__navbar-thumbnail-list"
29
+ :style="{ width: `${listLength * 34}px` }">
30
+ <div :key="item + i" v-for="(item, i) in list" :class="
31
+ i === index
32
+ ? 'duo-viewer-footer__navbar-thumbnail-item viewer-current'
33
+ : 'duo-viewer-footer__navbar-thumbnail-item'
34
+ ">
35
+ <img data-viewer-action="select" :data-viewer-action-index="i" :src="getVideoImg(item, i)"
36
+ :alt="alt" class="duo-viewer-footer__navbar-thumbnail-image" />
37
+ </div>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ </div>
42
+ <div class="duo-viewer-close" @click="handleClose">
43
+ <div class="duo-viewer-close__off"></div>
44
+ </div>
45
+ </div>
46
+ </template>
47
+
48
+ <script>
49
+
50
+ import { EMacro } from "../../utilities/File";
51
+
52
+ export default {
53
+ name: "ImageViewer",
54
+ data() {
55
+ return {
56
+ viewerSrc: "",
57
+ image: null,
58
+ listDataCache: [],
59
+ index: 0,
60
+ imgUrl: "",
61
+ isCreatePoster: false
62
+ };
63
+ },
64
+ props: {
65
+ // Image src list
66
+ list: {
67
+ type: Array,
68
+ default: [],
69
+ },
70
+ // Control is show of viewer
71
+ show: {
72
+ type: Boolean,
73
+ default: false,
74
+ },
75
+ // Default index
76
+ currentIndex: {
77
+ type: Number,
78
+ default: 0,
79
+ },
80
+ name: {
81
+ type: [String, Array],
82
+ default: null,
83
+ },
84
+ width: {
85
+ type: String,
86
+ default: null,
87
+ },
88
+ height: {
89
+ type: String,
90
+ default: null,
91
+ },
92
+ imgList: {
93
+ type: [String, Array],
94
+ default: null,
95
+ },
96
+ showThumbnail: {
97
+ type: Boolean,
98
+ default: false,
99
+ }
100
+ },
101
+ computed: {
102
+ listLength() {
103
+ return this.list.length;
104
+ },
105
+ realSrc() {
106
+ if (this.width === null && this.height === null) {
107
+ EMacro.getVideoScale(this.list[this.index]).then(info => {
108
+ this.width = info[0]
109
+ this.height = info[1]
110
+ });
111
+ }
112
+ return this.list[this.index];
113
+ },
114
+ realName() {
115
+ if (this.name == null) {
116
+ return this.list[this.index];
117
+ } else if (typeof this.name == "string") {
118
+ return this.name
119
+ } else if (Array.isArray(this.name)) {
120
+ return this.name[this.index];
121
+ } else {
122
+ return "未命名"
123
+ }
124
+ },
125
+ currentData() {
126
+ return this.listDataCache[this.index];
127
+ },
128
+ },
129
+ watch: {
130
+ show(val) {
131
+ if (val) {
132
+
133
+ if (this.imgList === null && this.showThumbnail) {
134
+ this.imgList = new Array();
135
+ this.isCreatePoster = true
136
+ }
137
+ for (let i = 0; i < this.list.length; i++) {
138
+ this.createVideoImg(this.list[i], i);
139
+ }
140
+ this.$emit("open");
141
+ this.index = this.currentIndex;
142
+ this.init();
143
+ } else {
144
+ this.$emit("close");
145
+ }
146
+ },
147
+ },
148
+ mounted() {
149
+
150
+ },
151
+ methods: {
152
+ getVideoImg(url, i) {
153
+
154
+ if (this.imgList !== null && typeof this.imgList == "string") {
155
+ return this.imgList
156
+ } else if (this.imgList !== null && Array.isArray(this.imgList)) {
157
+ return this.imgList[i]
158
+ } else {
159
+ return ""
160
+ }
161
+ },
162
+ async createVideoImg(url, i) {
163
+ if (!this.isCreatePoster) {
164
+ return
165
+ }
166
+ const base64 = await EMacro.getVideoBase64(url)
167
+ this.imgList.push(base64)
168
+ },
169
+ // Global init
170
+ init() {
171
+ // this.initMouseWheel();
172
+ this.keydown();
173
+ },
174
+
175
+ // Reset Rotate
176
+ resetRotate() {
177
+ let image = this.image,
178
+ oldTransform = this.getCurrentTransform(image);
179
+
180
+ oldTransform.rotate = `0deg`;
181
+
182
+ this.setTransform(image, oldTransform);
183
+ },
184
+
185
+ // Reset zoom action
186
+ resetZoom() {
187
+ let image = this.image;
188
+ const imageObject = new Image();
189
+
190
+ imageObject.src = this.list[this.index];
191
+
192
+ const { width, height } = imageObject;
193
+
194
+ this.setStyleByName(image, "width", `${width}px`);
195
+ this.setStyleByName(image, "height", `${height}px`);
196
+
197
+ this.listDataCache[this.index].width = `${width}px`;
198
+ this.listDataCache[this.index].height = `${height}px`;
199
+ },
200
+
201
+ // Reset all action
202
+ resetAll() {
203
+ this.resetZoom();
204
+ this.resetRotate();
205
+ this.resetPosition();
206
+ this.initListDataCache(this.index);
207
+ },
208
+
209
+ // Rotate action
210
+ rotate(type) {
211
+ let image = this.image,
212
+ oldTransform = this.getCurrentTransform(image),
213
+ oldRotate = Math.round(
214
+ Math.atan2(+oldTransform.skewY, +oldTransform.scaleX) *
215
+ (180 / Math.PI)
216
+ ),
217
+ changeValue = type === "left" ? -90 : 90,
218
+ rotateValue = oldRotate + changeValue;
219
+
220
+ oldTransform.rotate = `${rotateValue}deg`;
221
+
222
+ oldTransform.translateX = `${oldTransform.translateX}px`;
223
+ oldTransform.translateY = `${oldTransform.translateY}px`;
224
+ this.currentData.transform = oldTransform;
225
+ this.setTransform(image, oldTransform);
226
+ },
227
+
228
+ // Get style by name
229
+ getStyleByName(obj, type) {
230
+ return window.getComputedStyle(obj, null)[type];
231
+ },
232
+
233
+ // Set style by name
234
+ setStyleByName(obj, key, value) {
235
+ obj && (obj.style[key] = value);
236
+ },
237
+
238
+ // Get element current transform
239
+ getCurrentTransform(obj) {
240
+ let value,
241
+ transform = this.getStyleByName(obj, "transform");
242
+
243
+ if (transform === "none") return;
244
+
245
+ value = transform.split("(")[1].split(")")[0].split(",");
246
+
247
+ return {
248
+ scaleX: value[0].trim(),
249
+ skewY: value[1].trim(),
250
+ // skewX: value[2].trim(),
251
+ // scaleY: value[3].trim(),
252
+ translateX: value[4].trim(),
253
+ translateY: value[5].trim(),
254
+ };
255
+ },
256
+ // Next or prev action
257
+ switchAction(a) {
258
+ let lastIndex = this.index;
259
+ switch (a) {
260
+ case "prev":
261
+ // prev action
262
+ this.index += this.index <= 0 ? 0 : -1;
263
+ break;
264
+ case "next":
265
+ // next action
266
+ let srcListLength = this.listLength - 1;
267
+
268
+ this.index +=
269
+ this.index >= srcListLength ? srcListLength - this.index : 1;
270
+ break;
271
+ default:
272
+ this.index = +a;
273
+ break;
274
+ }
275
+ this.judgeThumbnailListMove(lastIndex, this.index);
276
+
277
+ // this.setStyleByName(this.image, "width", this.currentData.width);
278
+ // this.setStyleByName(this.image, "height", this.currentData.height);
279
+ // this.setStyleByName(this.image, "left", this.currentData.left);
280
+ // this.setStyleByName(this.image, "top", this.currentData.top);
281
+ // this.setTransform(this.image, this.currentData.transform);
282
+ },
283
+ // To judge thumbnail list move
284
+ judgeThumbnailListMove(lastIndex, index) {
285
+ if (lastIndex == index) return;
286
+
287
+ let translateX = 0,
288
+ lastTransform = 0,
289
+ step = index - lastIndex,
290
+ move = step * 34,
291
+ length = this.listLength,
292
+ target = this.$refs["duoViewerImageThumbnailList"];
293
+
294
+ if (!target) return;
295
+
296
+ lastTransform = this.getCurrentTransform(target);
297
+
298
+ if (lastTransform) {
299
+ translateX = Math.abs(+lastTransform.translateX);
300
+ }
301
+
302
+ this.setTransform(target, {
303
+ scaleX: "1",
304
+ skewY: "0",
305
+ translateX: `-${translateX + move}px`,
306
+ translateY: "0%",
307
+ rotate: "0deg",
308
+ });
309
+ },
310
+ // Set element Transform
311
+ setTransform(obj, transformValue) {
312
+ let str = "";
313
+
314
+ str += `translateX(${transformValue["translateX"]}) `;
315
+ str += `translateY(${transformValue["translateY"]}) `;
316
+ transformValue["rotate"] &&
317
+ (str += `rotate(${transformValue["rotate"]}) `);
318
+
319
+ this.setStyleByName(obj, "transform", str);
320
+ },
321
+
322
+ // FullScreen action
323
+ requestFullScreen() {
324
+ let element = this.$refs["duoViewer"],
325
+ requestMethod =
326
+ element.requestFullScreen ||
327
+ element.webkitRequestFullScreen ||
328
+ element.mozRequestFullScreen ||
329
+ element.msRequestFullScreen;
330
+
331
+ if (requestMethod) {
332
+ requestMethod.call(element);
333
+ } else if (typeof window.ActiveXObject !== "undefined") {
334
+ // ie
335
+ let wscript = new ActiveXObject("WScript.Shell");
336
+ wscript !== null && wscript.SendKeys("{F11}");
337
+ }
338
+ },
339
+
340
+ // Keydown action
341
+ keydown() {
342
+ window.addEventListener("keydown", (e) => {
343
+ e = event || window.event || arguments.callee.caller.arguments[0];
344
+
345
+ if (e && e.keyCode == 40) {
346
+ // down
347
+ this.zoom("out");
348
+ }
349
+ if (e && e.keyCode == 37) {
350
+ // left
351
+ this.switchAction("prev");
352
+ }
353
+ if (e && e.keyCode == 39) {
354
+ // right
355
+ this.switchAction("next");
356
+ }
357
+ if (e && e.keyCode == 38) {
358
+ // up
359
+ this.zoom("in");
360
+ }
361
+ if (e && e.keyCode == 27) {
362
+ // esc
363
+ this.handleClose()
364
+ }
365
+ });
366
+ },
367
+
368
+ // Init mouse wheel event
369
+ initMouseWheel() {
370
+ const scrollFn = (e) => {
371
+ e = e || window.event;
372
+ if (e.wheelDelta) {
373
+ // for IE/Google
374
+ if (e.wheelDelta > 0) {
375
+ this.zoom("out");
376
+ }
377
+ if (e.wheelDelta < 0) {
378
+ this.zoom("in");
379
+ }
380
+ } else if (e.detail) {
381
+ // for Firefox
382
+ if (e.detail > 0) {
383
+ this.zoom("out");
384
+ }
385
+ if (e.detail < 0) {
386
+ this.zoom("in");
387
+ }
388
+ }
389
+ };
390
+
391
+ document.addEventListener &&
392
+ document.addEventListener("DOMMouseScroll", scrollFn, false);
393
+ window.onmousewheel = document.onmousewheel = scrollFn;
394
+ },
395
+
396
+ // Agent
397
+ clickAgent(e) {
398
+ switch (e.target.getAttribute("data-viewer-action")) {
399
+ case "zoom-in":
400
+ this.zoom("in");
401
+ break;
402
+ case "zoom-out":
403
+ this.zoom("out");
404
+ break;
405
+ case "one-to-one":
406
+ this.resetZoom();
407
+ break;
408
+ case "prev":
409
+ this.switchAction("prev");
410
+ break;
411
+ case "play":
412
+ this.requestFullScreen();
413
+ break;
414
+ case "next":
415
+ this.switchAction("next");
416
+ break;
417
+ case "reset":
418
+ this.resetAll();
419
+ break;
420
+ case "select":
421
+ this.switchAction(e.target.getAttribute("data-viewer-action-index"));
422
+ break;
423
+ case "rotate-left":
424
+ this.rotate("left");
425
+ break;
426
+ case "rotate-right":
427
+ this.rotate("right");
428
+ break;
429
+ }
430
+ },
431
+ // On close
432
+ handleClose() {
433
+ this.imgList = null
434
+ this.isCreatePoster = false
435
+ this.$emit("update:show", false);
436
+ },
437
+ },
438
+ };
439
+ </script>
440
+
441
+ <style lang="less" scoped>
442
+ @import "./style/css/index.css";
443
+ </style>
@@ -0,0 +1,186 @@
1
+ .duo-viewer {
2
+ position: fixed;
3
+ top: 0;
4
+ left: 0;
5
+ z-index: 10000;
6
+ width: 100%;
7
+ height: 100vh;
8
+ }
9
+ .duo-viewer-mask {
10
+ position: absolute;
11
+ top: 0;
12
+ left: 0;
13
+ width: 100%;
14
+ height: 100%;
15
+ background: rgba(0, 0, 0, 0.6);
16
+ z-index: 9;
17
+ }
18
+ .duo-viewer-mask__image {
19
+ cursor: grab;
20
+ height: 750px;
21
+ position: absolute;
22
+ top: 50%;
23
+ left: 50%;
24
+ transform: translate(-50%, -50%);
25
+ z-index: 8;
26
+ transition-property: transform, height, width;
27
+ transition-duration: 0.3s, 0.3s, 0.3s;
28
+ }
29
+ .duo-viewer-footer {
30
+ position: absolute;
31
+ text-align: center;
32
+ bottom: 0;
33
+ left: 0;
34
+ width: 100%;
35
+ z-index: 10;
36
+ }
37
+ .duo-viewer-footer__title {
38
+ color: #cfcfcf;
39
+ position: absolute;
40
+ bottom: 95px;
41
+ left: 50%;
42
+ transform: translate(-50%, 0%);
43
+ z-index: 10;
44
+ width: 100%;
45
+ }
46
+ .duo-viewer-footer__toolbar {
47
+ position: absolute;
48
+ bottom: 60px;
49
+ left: 50%;
50
+ transform: translate(-50%, 0%);
51
+ z-index: 10;
52
+ }
53
+ .duo-viewer-footer__toolbar li {
54
+ margin: 2px;
55
+ background-color: rgba(0, 0, 0, 0.5);
56
+ border-radius: 50%;
57
+ cursor: pointer;
58
+ float: left;
59
+ height: 28px;
60
+ overflow: hidden;
61
+ -webkit-transition: background-color 0.15s;
62
+ transition: background-color 0.15s;
63
+ width: 28px;
64
+ position: relative;
65
+ }
66
+ .duo-viewer-footer__toolbar li::after {
67
+ position: absolute;
68
+ top: 0;
69
+ left: 0;
70
+ width: 100%;
71
+ height: 100%;
72
+ content: "";
73
+ display: inline-block;
74
+ background: url("../images/icons.png") no-repeat;
75
+ }
76
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__zoom-in::after {
77
+ background-position: 4px 3px;
78
+ }
79
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__zoom-out::after {
80
+ background-position: -16px 3px;
81
+ }
82
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__one-to-one::after {
83
+ background-position: -35px 3px;
84
+ }
85
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__reset::after {
86
+ background-position: -56px 3px;
87
+ }
88
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__prev::after {
89
+ background-position: -77px 3px;
90
+ }
91
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__play {
92
+ width: 34px;
93
+ height: 34px;
94
+ margin-top: -2px;
95
+ }
96
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__play::after {
97
+ background-position: -93px 6px;
98
+ }
99
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__next::after {
100
+ background-position: -116px 3px;
101
+ }
102
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__rotate-left::after {
103
+ background-position: -136px 3px;
104
+ }
105
+ .duo-viewer-footer__toolbar li.duo-viewer-footer__rotate-right::after {
106
+ background-position: -156px 3px;
107
+ }
108
+ .duo-viewer-footer__navbar {
109
+ width: 100%;
110
+ height: 50px;
111
+ background: rgba(0, 0, 0, 0.9);
112
+ overflow: hidden;
113
+ }
114
+ .duo-viewer-footer__navbar-thumbnail-image {
115
+ height: 100%;
116
+ width: 80px;
117
+ -o-object-fit: fill;
118
+ object-fit: fill;
119
+ transform: translateX(-30px);
120
+ }
121
+ .duo-viewer-footer__navbar-thumbnail-item {
122
+ margin: 0 2px;
123
+ color: transparent;
124
+ cursor: pointer;
125
+ float: left;
126
+ font-size: 0;
127
+ width: 30px;
128
+ opacity: 0.2;
129
+ overflow: hidden;
130
+ -webkit-transition: opacity 0.15s;
131
+ transition: opacity 0.15s;
132
+ }
133
+ .duo-viewer-footer__navbar-thumbnail-item.viewer-current {
134
+ opacity: 0.9;
135
+ }
136
+ .duo-viewer-footer__navbar-thumbnail-wrap {
137
+ position: relative;
138
+ overflow: hidden;
139
+ width: 660px;
140
+ height: inherit;
141
+ margin: 0 auto;
142
+ }
143
+ .duo-viewer-footer__navbar-thumbnail-list {
144
+ padding: 10px 0;
145
+ width: auto;
146
+ box-sizing: border-box;
147
+ position: absolute;
148
+ top: 0;
149
+ left: 50%;
150
+ transition: all 0.3s;
151
+ }
152
+ .duo-viewer-close {
153
+ background-color: rgba(0, 0, 0, 0.9);
154
+ border-radius: 0% 0% 0% 100%;
155
+ cursor: pointer;
156
+ height: 50px;
157
+ overflow: hidden;
158
+ position: absolute;
159
+ right: 0;
160
+ top: 0;
161
+ transition: background-color 0.15s;
162
+ width: 50px;
163
+ z-index: 10;
164
+ line-height: 50px;
165
+ text-align: center;
166
+ }
167
+ .duo-viewer-close__off {
168
+ margin: 18px 12px;
169
+ position: relative;
170
+ width: 2em;
171
+ height: 0.3em;
172
+ background-color: #fff;
173
+ transform: rotate(45deg);
174
+ border-radius: 0.15em;
175
+ }
176
+ .duo-viewer-close__off:after {
177
+ content: "";
178
+ position: absolute;
179
+ width: 2em;
180
+ height: 0.3em;
181
+ top: 0;
182
+ left: 0;
183
+ background-color: #fff;
184
+ transform: rotate(90deg);
185
+ border-radius: 0.15em;
186
+ }