@gudhub/ssg-web-components-library 1.0.117 → 1.0.119
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/package.json +1 -1
- package/src/components/get-in-touch-form/get-in-touch-form.scss +4 -1
- package/src/components/video-slider/animations/cascade-strips.js +89 -0
- package/src/components/video-slider/animations/fade.js +31 -0
- package/src/components/video-slider/animations/multi-strip.js +66 -0
- package/src/components/video-slider/animations/sectors.js +104 -0
- package/src/components/video-slider/animations/wipe-left.js +43 -0
- package/src/components/video-slider/animations/zoom.js +51 -0
- package/src/components/video-slider/config.js +6 -0
- package/src/components/video-slider/utils/draw-image-cover.js +27 -0
- package/src/components/video-slider/utils/easing.js +5 -0
- package/src/components/video-slider/video-slider.html +5 -0
- package/src/components/video-slider/video-slider.js +177 -0
- package/src/components/video-slider/video-slider.readme.md +218 -0
- package/src/components/video-slider/video-slider.scss +16 -0
- package/src/config.js +1 -1
- package/src/components/liqpay-payment-button/config.js +0 -6
- package/src/components/liqpay-payment-button/liqpay-payment-button.html +0 -5
- package/src/components/liqpay-payment-button/liqpay-payment-button.js +0 -23
- package/src/components/liqpay-payment-button/liqpay-payment-button.json +0 -4
- package/src/components/liqpay-payment-button/liqpay-payment-button.md +0 -0
- package/src/components/liqpay-payment-button/liqpay-payment-button.scss +0 -7
package/package.json
CHANGED
|
@@ -271,12 +271,15 @@ get-in-touch-form {
|
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
273
|
}
|
|
274
|
+
|
|
274
275
|
.recaptcha-notice {
|
|
275
|
-
margin-top:
|
|
276
|
+
margin-top: 20px;
|
|
276
277
|
font-size: 12px;
|
|
277
278
|
line-height: 1.4;
|
|
278
279
|
opacity: 0.7;
|
|
280
|
+
text-align: center;
|
|
279
281
|
}
|
|
282
|
+
|
|
280
283
|
&[data-in-popup] {
|
|
281
284
|
.get-in-touch-form {
|
|
282
285
|
padding-top: 0;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { drawImageCover } from '../utils/draw-image-cover.js';
|
|
2
|
+
|
|
3
|
+
export default function cascadeStrips({
|
|
4
|
+
ctx,
|
|
5
|
+
canvas,
|
|
6
|
+
images,
|
|
7
|
+
progress,
|
|
8
|
+
}) {
|
|
9
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
10
|
+
|
|
11
|
+
// BASE IMAGE
|
|
12
|
+
drawImageCover({
|
|
13
|
+
ctx,
|
|
14
|
+
canvas,
|
|
15
|
+
image: images[0],
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
const slidesCount =
|
|
19
|
+
images.length;
|
|
20
|
+
|
|
21
|
+
const sectorWidth =
|
|
22
|
+
canvas.width / slidesCount;
|
|
23
|
+
|
|
24
|
+
// GLOBAL WIPE POSITION
|
|
25
|
+
const totalTravel =
|
|
26
|
+
canvas.width
|
|
27
|
+
+ (
|
|
28
|
+
sectorWidth
|
|
29
|
+
* (slidesCount - 1)
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const wipeX =
|
|
33
|
+
totalTravel * progress;
|
|
34
|
+
|
|
35
|
+
for (let i = 1; i < slidesCount; i++) {
|
|
36
|
+
|
|
37
|
+
const image =
|
|
38
|
+
images[i];
|
|
39
|
+
|
|
40
|
+
// OFFSET BETWEEN WIPES
|
|
41
|
+
const offset =
|
|
42
|
+
sectorWidth * (i - 1);
|
|
43
|
+
|
|
44
|
+
// CURRENT WIPE POSITION
|
|
45
|
+
const currentX =
|
|
46
|
+
wipeX - offset;
|
|
47
|
+
|
|
48
|
+
// NOT YET VISIBLE
|
|
49
|
+
if (currentX <= 0) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
ctx.save();
|
|
54
|
+
|
|
55
|
+
ctx.beginPath();
|
|
56
|
+
|
|
57
|
+
// LAST SLIDE
|
|
58
|
+
if (i === slidesCount - 1) {
|
|
59
|
+
|
|
60
|
+
// CONTINUES TO FULLSCREEN
|
|
61
|
+
ctx.rect(
|
|
62
|
+
0,
|
|
63
|
+
0,
|
|
64
|
+
currentX,
|
|
65
|
+
canvas.height
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
} else {
|
|
69
|
+
|
|
70
|
+
// NORMAL STRIP
|
|
71
|
+
ctx.rect(
|
|
72
|
+
currentX - sectorWidth,
|
|
73
|
+
0,
|
|
74
|
+
sectorWidth,
|
|
75
|
+
canvas.height
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
ctx.clip();
|
|
80
|
+
|
|
81
|
+
drawImageCover({
|
|
82
|
+
ctx,
|
|
83
|
+
canvas,
|
|
84
|
+
image,
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
ctx.restore();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { drawImageCover } from '../utils/draw-image-cover.js';
|
|
2
|
+
|
|
3
|
+
export default function fade({
|
|
4
|
+
ctx,
|
|
5
|
+
canvas,
|
|
6
|
+
currentImage,
|
|
7
|
+
nextImage,
|
|
8
|
+
progress,
|
|
9
|
+
}) {
|
|
10
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
11
|
+
|
|
12
|
+
// CURRENT IMAGE
|
|
13
|
+
drawImageCover({
|
|
14
|
+
ctx,
|
|
15
|
+
canvas,
|
|
16
|
+
image: currentImage,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// NEXT IMAGE
|
|
20
|
+
ctx.save();
|
|
21
|
+
|
|
22
|
+
ctx.globalAlpha = progress;
|
|
23
|
+
|
|
24
|
+
drawImageCover({
|
|
25
|
+
ctx,
|
|
26
|
+
canvas,
|
|
27
|
+
image: nextImage,
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
ctx.restore();
|
|
31
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { drawImageCover } from '../utils/draw-image-cover.js';
|
|
2
|
+
|
|
3
|
+
export default function multiStrip({
|
|
4
|
+
ctx,
|
|
5
|
+
canvas,
|
|
6
|
+
currentImage,
|
|
7
|
+
nextImage,
|
|
8
|
+
progress,
|
|
9
|
+
isTransitionPhase,
|
|
10
|
+
}) {
|
|
11
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
12
|
+
|
|
13
|
+
// CURRENT IMAGE
|
|
14
|
+
drawImageCover({
|
|
15
|
+
ctx,
|
|
16
|
+
canvas,
|
|
17
|
+
image: currentImage,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
if (!isTransitionPhase) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const strips = 8;
|
|
25
|
+
|
|
26
|
+
const stripWidth = canvas.width / strips;
|
|
27
|
+
|
|
28
|
+
const stagger = 0.08;
|
|
29
|
+
|
|
30
|
+
for (let i = 0; i < strips; i++) {
|
|
31
|
+
|
|
32
|
+
const delay = i * stagger;
|
|
33
|
+
|
|
34
|
+
let localProgress =
|
|
35
|
+
(progress - delay) / (1 - (stagger * strips));
|
|
36
|
+
|
|
37
|
+
localProgress = Math.max(0, Math.min(1, localProgress));
|
|
38
|
+
|
|
39
|
+
const revealWidth =
|
|
40
|
+
stripWidth * localProgress;
|
|
41
|
+
|
|
42
|
+
const x =
|
|
43
|
+
i * stripWidth;
|
|
44
|
+
|
|
45
|
+
ctx.save();
|
|
46
|
+
|
|
47
|
+
ctx.beginPath();
|
|
48
|
+
|
|
49
|
+
ctx.rect(
|
|
50
|
+
x,
|
|
51
|
+
0,
|
|
52
|
+
revealWidth,
|
|
53
|
+
canvas.height
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
ctx.clip();
|
|
57
|
+
|
|
58
|
+
drawImageCover({
|
|
59
|
+
ctx,
|
|
60
|
+
canvas,
|
|
61
|
+
image: nextImage,
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
ctx.restore();
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { drawImageCover } from '../utils/draw-image-cover.js';
|
|
2
|
+
|
|
3
|
+
export default function sectors({
|
|
4
|
+
ctx,
|
|
5
|
+
canvas,
|
|
6
|
+
images,
|
|
7
|
+
progress,
|
|
8
|
+
}) {
|
|
9
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
10
|
+
|
|
11
|
+
const slidesCount =
|
|
12
|
+
images.length;
|
|
13
|
+
|
|
14
|
+
const sectorWidth =
|
|
15
|
+
canvas.width / slidesCount;
|
|
16
|
+
|
|
17
|
+
// BASE SLIDE
|
|
18
|
+
drawImageCover({
|
|
19
|
+
ctx,
|
|
20
|
+
canvas,
|
|
21
|
+
image: images[0],
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
for (let i = 1; i < slidesCount; i++) {
|
|
25
|
+
|
|
26
|
+
// START OF THIS SECTOR
|
|
27
|
+
const start =
|
|
28
|
+
i / slidesCount;
|
|
29
|
+
|
|
30
|
+
// END OF THIS SECTOR
|
|
31
|
+
const end =
|
|
32
|
+
(i + 1) / slidesCount;
|
|
33
|
+
|
|
34
|
+
// LOCAL PROGRESS
|
|
35
|
+
let localProgress =
|
|
36
|
+
(progress - start)
|
|
37
|
+
/ (end - start);
|
|
38
|
+
|
|
39
|
+
localProgress =
|
|
40
|
+
Math.max(
|
|
41
|
+
0,
|
|
42
|
+
Math.min(1, localProgress)
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
// NOT STARTED
|
|
46
|
+
if (localProgress <= 0) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const x =
|
|
51
|
+
i * sectorWidth;
|
|
52
|
+
|
|
53
|
+
ctx.save();
|
|
54
|
+
|
|
55
|
+
ctx.beginPath();
|
|
56
|
+
|
|
57
|
+
// LAST SECTOR
|
|
58
|
+
if (i === slidesCount - 1) {
|
|
59
|
+
|
|
60
|
+
const expandProgress =
|
|
61
|
+
Math.max(
|
|
62
|
+
0,
|
|
63
|
+
(progress - 0.875) / 0.125
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const dynamicWidth =
|
|
67
|
+
sectorWidth
|
|
68
|
+
+ (
|
|
69
|
+
(canvas.width - sectorWidth)
|
|
70
|
+
* expandProgress
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
ctx.rect(
|
|
74
|
+
x,
|
|
75
|
+
0,
|
|
76
|
+
dynamicWidth,
|
|
77
|
+
canvas.height
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
} else {
|
|
81
|
+
|
|
82
|
+
ctx.rect(
|
|
83
|
+
x,
|
|
84
|
+
0,
|
|
85
|
+
sectorWidth,
|
|
86
|
+
canvas.height
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
ctx.clip();
|
|
91
|
+
|
|
92
|
+
// FADE-IN
|
|
93
|
+
ctx.globalAlpha =
|
|
94
|
+
localProgress;
|
|
95
|
+
|
|
96
|
+
drawImageCover({
|
|
97
|
+
ctx,
|
|
98
|
+
canvas,
|
|
99
|
+
image: images[i],
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
ctx.restore();
|
|
103
|
+
}
|
|
104
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { drawImageCover } from '../utils/draw-image-cover.js';
|
|
2
|
+
import { easeInOutCubic } from '../utils/easing.js';
|
|
3
|
+
|
|
4
|
+
export default function wipeLeft({
|
|
5
|
+
ctx,
|
|
6
|
+
canvas,
|
|
7
|
+
currentImage,
|
|
8
|
+
nextImage,
|
|
9
|
+
progress,
|
|
10
|
+
}) {
|
|
11
|
+
const eased = easeInOutCubic(progress);
|
|
12
|
+
|
|
13
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
14
|
+
|
|
15
|
+
drawImageCover({
|
|
16
|
+
ctx,
|
|
17
|
+
canvas,
|
|
18
|
+
image: currentImage,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const revealWidth = canvas.width * eased;
|
|
22
|
+
|
|
23
|
+
ctx.save();
|
|
24
|
+
|
|
25
|
+
ctx.beginPath();
|
|
26
|
+
|
|
27
|
+
ctx.rect(
|
|
28
|
+
0,
|
|
29
|
+
0,
|
|
30
|
+
revealWidth,
|
|
31
|
+
canvas.height
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
ctx.clip();
|
|
35
|
+
|
|
36
|
+
drawImageCover({
|
|
37
|
+
ctx,
|
|
38
|
+
canvas,
|
|
39
|
+
image: nextImage,
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
ctx.restore();
|
|
43
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { drawImageCover } from '../utils/draw-image-cover.js';
|
|
2
|
+
|
|
3
|
+
export default function zoom({
|
|
4
|
+
ctx,
|
|
5
|
+
canvas,
|
|
6
|
+
currentImage,
|
|
7
|
+
nextImage,
|
|
8
|
+
progress,
|
|
9
|
+
isTransitionPhase,
|
|
10
|
+
}) {
|
|
11
|
+
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
12
|
+
|
|
13
|
+
if (!isTransitionPhase) {
|
|
14
|
+
drawImageCover({
|
|
15
|
+
ctx,
|
|
16
|
+
canvas,
|
|
17
|
+
image: currentImage,
|
|
18
|
+
scale: 1.05,
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// CURRENT IMAGE
|
|
25
|
+
ctx.save();
|
|
26
|
+
|
|
27
|
+
ctx.globalAlpha = 1 - progress;
|
|
28
|
+
|
|
29
|
+
drawImageCover({
|
|
30
|
+
ctx,
|
|
31
|
+
canvas,
|
|
32
|
+
image: currentImage,
|
|
33
|
+
scale: 1 + (progress * 0.1),
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
ctx.restore();
|
|
37
|
+
|
|
38
|
+
// NEXT IMAGE
|
|
39
|
+
ctx.save();
|
|
40
|
+
|
|
41
|
+
ctx.globalAlpha = progress;
|
|
42
|
+
|
|
43
|
+
drawImageCover({
|
|
44
|
+
ctx,
|
|
45
|
+
canvas,
|
|
46
|
+
image: nextImage,
|
|
47
|
+
scale: 1.1 - (progress * 0.1),
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
ctx.restore();
|
|
51
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function drawImageCover({
|
|
2
|
+
ctx,
|
|
3
|
+
canvas,
|
|
4
|
+
image,
|
|
5
|
+
scale = 1,
|
|
6
|
+
offsetX = 0,
|
|
7
|
+
offsetY = 0,
|
|
8
|
+
}) {
|
|
9
|
+
const canvasRatio = canvas.width / canvas.height;
|
|
10
|
+
const imageRatio = image.width / image.height;
|
|
11
|
+
|
|
12
|
+
let drawWidth;
|
|
13
|
+
let drawHeight;
|
|
14
|
+
|
|
15
|
+
if (imageRatio > canvasRatio) {
|
|
16
|
+
drawHeight = canvas.height * scale;
|
|
17
|
+
drawWidth = drawHeight * imageRatio;
|
|
18
|
+
} else {
|
|
19
|
+
drawWidth = canvas.width * scale;
|
|
20
|
+
drawHeight = drawWidth / imageRatio;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const x = ((canvas.width - drawWidth) / 2) + offsetX;
|
|
24
|
+
const y = ((canvas.height - drawHeight) / 2) + offsetY;
|
|
25
|
+
|
|
26
|
+
ctx.drawImage(image, x, y, drawWidth, drawHeight);
|
|
27
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import html from './video-slider.html';
|
|
2
|
+
import './video-slider.scss';
|
|
3
|
+
|
|
4
|
+
import wipeLeft from './animations/wipe-left.js';
|
|
5
|
+
import fade from './animations/fade.js';
|
|
6
|
+
import zoom from './animations/zoom.js';
|
|
7
|
+
import multiStrip from './animations/multi-strip.js';
|
|
8
|
+
import cascadeStrips from './animations/cascade-strips.js';
|
|
9
|
+
import sectors from './animations/sectors.js';
|
|
10
|
+
|
|
11
|
+
class VideoSlider extends GHComponent {
|
|
12
|
+
constructor() {
|
|
13
|
+
super();
|
|
14
|
+
|
|
15
|
+
this.animations = {
|
|
16
|
+
wipeLeft,
|
|
17
|
+
fade,
|
|
18
|
+
zoom,
|
|
19
|
+
multiStrip,
|
|
20
|
+
cascadeStrips,
|
|
21
|
+
sectors
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async onServerRender() {
|
|
26
|
+
|
|
27
|
+
this.ghId = this.getAttribute('data-gh-id') || null;
|
|
28
|
+
this.chapter = this.getAttribute('data-chapter') || 'pages';
|
|
29
|
+
this.json = this.ghId
|
|
30
|
+
? await super.getGhData(this.ghId, this.chapter)
|
|
31
|
+
: console.error('data-gh-id attribute is required for video-slider component');
|
|
32
|
+
|
|
33
|
+
this.setAttribute(
|
|
34
|
+
'data-animation',
|
|
35
|
+
this.json.animation
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
this.setAttribute(
|
|
39
|
+
'data-slide-duration',
|
|
40
|
+
this.json.slideDuration
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
this.setAttribute(
|
|
44
|
+
'data-transition-duration',
|
|
45
|
+
this.json.transitionDuration
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
this.setAttribute(
|
|
49
|
+
'data-images',
|
|
50
|
+
JSON.stringify(this.json.images)
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
super.render(html);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async onClientReady() {
|
|
57
|
+
|
|
58
|
+
this.config = {
|
|
59
|
+
animation: this.getAttribute('data-animation'),
|
|
60
|
+
|
|
61
|
+
slideDuration:
|
|
62
|
+
Number(this.getAttribute('data-slide-duration')),
|
|
63
|
+
|
|
64
|
+
transitionDuration:
|
|
65
|
+
Number(this.getAttribute('data-transition-duration'))
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
this.images = JSON.parse(this.getAttribute('data-images'));
|
|
69
|
+
|
|
70
|
+
this.canvas = this.querySelector('canvas');
|
|
71
|
+
|
|
72
|
+
this.ctx = this.canvas.getContext('2d');
|
|
73
|
+
|
|
74
|
+
this.canvas.width = 1280;
|
|
75
|
+
this.canvas.height = 720;
|
|
76
|
+
|
|
77
|
+
this.loadedImages = await this.preloadImages();
|
|
78
|
+
|
|
79
|
+
this.startLoop();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
preloadImages() {
|
|
83
|
+
return Promise.all(
|
|
84
|
+
this.images.map((url) => {
|
|
85
|
+
return new Promise((resolve, reject) => {
|
|
86
|
+
|
|
87
|
+
const image = new Image();
|
|
88
|
+
|
|
89
|
+
image.crossOrigin = 'anonymous';
|
|
90
|
+
|
|
91
|
+
image.onload = () => {
|
|
92
|
+
resolve(image);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
image.onerror = () => reject(url);
|
|
96
|
+
|
|
97
|
+
image.src = url;
|
|
98
|
+
});
|
|
99
|
+
})
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
startLoop() {
|
|
104
|
+
this.startTime = performance.now();
|
|
105
|
+
|
|
106
|
+
const render = (time) => {
|
|
107
|
+
const elapsed = time - this.startTime;
|
|
108
|
+
|
|
109
|
+
const totalSlides = this.loadedImages.length;
|
|
110
|
+
|
|
111
|
+
const singleSlideTotal =
|
|
112
|
+
this.config.slideDuration + this.config.transitionDuration;
|
|
113
|
+
|
|
114
|
+
const totalDuration =
|
|
115
|
+
singleSlideTotal * totalSlides;
|
|
116
|
+
|
|
117
|
+
const timelineTime =
|
|
118
|
+
elapsed % totalDuration;
|
|
119
|
+
|
|
120
|
+
const currentSlide =
|
|
121
|
+
Math.floor(timelineTime / singleSlideTotal);
|
|
122
|
+
|
|
123
|
+
const nextSlide =
|
|
124
|
+
(currentSlide + 1) % totalSlides;
|
|
125
|
+
|
|
126
|
+
const localTime =
|
|
127
|
+
timelineTime % singleSlideTotal;
|
|
128
|
+
|
|
129
|
+
const isTransitionPhase =
|
|
130
|
+
localTime >= this.config.slideDuration;
|
|
131
|
+
|
|
132
|
+
const transitionTime =
|
|
133
|
+
localTime - this.config.slideDuration;
|
|
134
|
+
|
|
135
|
+
const progress = isTransitionPhase
|
|
136
|
+
? transitionTime / this.config.transitionDuration
|
|
137
|
+
: 0;
|
|
138
|
+
|
|
139
|
+
this.renderFrame({
|
|
140
|
+
currentImage: this.loadedImages[currentSlide],
|
|
141
|
+
nextImage: this.loadedImages[nextSlide],
|
|
142
|
+
progress,
|
|
143
|
+
isTransitionPhase,
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
requestAnimationFrame(render);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
requestAnimationFrame(render);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
renderFrame({
|
|
153
|
+
currentImage,
|
|
154
|
+
nextImage,
|
|
155
|
+
progress,
|
|
156
|
+
isTransitionPhase,
|
|
157
|
+
}) {
|
|
158
|
+
if (!currentImage) return;
|
|
159
|
+
|
|
160
|
+
const animation =
|
|
161
|
+
this.animations[this.config.animation];
|
|
162
|
+
|
|
163
|
+
if (!animation) return;
|
|
164
|
+
|
|
165
|
+
animation({
|
|
166
|
+
ctx: this.ctx,
|
|
167
|
+
canvas: this.canvas,
|
|
168
|
+
currentImage,
|
|
169
|
+
nextImage,
|
|
170
|
+
progress,
|
|
171
|
+
isTransitionPhase,
|
|
172
|
+
images: this.loadedImages,
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
window.customElements.define('video-slider', VideoSlider);
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Video Slider Component
|
|
2
|
+
|
|
3
|
+
## Description
|
|
4
|
+
|
|
5
|
+
`video-slider` is a canvas-based animated image slider that supports multiple transition effects between slides.
|
|
6
|
+
|
|
7
|
+
The component loads configuration and images from GudHub data and automatically starts the animation loop after initialization.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Data Structure
|
|
12
|
+
|
|
13
|
+
The component expects the following JSON structure:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"video-slider": {
|
|
18
|
+
"animation": "fade",
|
|
19
|
+
"slideDuration": "100",
|
|
20
|
+
"transitionDuration": "2000",
|
|
21
|
+
"images": [
|
|
22
|
+
"https://app.gudhub.com/userdata/12345/image1.jpg",
|
|
23
|
+
"https://app.gudhub.com/userdata/12354/image2.jpg",
|
|
24
|
+
"https://app.gudhub.com/userdata/11345/image3.jpg"
|
|
25
|
+
]
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Configuration Parameters
|
|
31
|
+
|
|
32
|
+
| Property | Type | Required | Description |
|
|
33
|
+
| ------------------ | ------------- | -------- | ------------------------------------------------------ |
|
|
34
|
+
| animation | string | Yes | Animation type used between slides |
|
|
35
|
+
| slideDuration | string/number | Yes | Duration of static slide display in milliseconds |
|
|
36
|
+
| transitionDuration | string/number | Yes | Duration of slide transition animation in milliseconds |
|
|
37
|
+
| images | array | Yes | Ordered list of image URLs |
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Supported Animations
|
|
42
|
+
|
|
43
|
+
The following animation values are supported:
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
wipeLeft
|
|
47
|
+
fade
|
|
48
|
+
zoom
|
|
49
|
+
multiStrip
|
|
50
|
+
cascadeStrips
|
|
51
|
+
sectors
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Example:
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"animation": "zoom"
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Slide Duration
|
|
65
|
+
|
|
66
|
+
Defines how long a slide remains visible before transition starts.
|
|
67
|
+
|
|
68
|
+
Example:
|
|
69
|
+
|
|
70
|
+
```json
|
|
71
|
+
{
|
|
72
|
+
"slideDuration": "3000"
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Result:
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
3 seconds display
|
|
80
|
+
+
|
|
81
|
+
transition animation
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Transition Duration
|
|
87
|
+
|
|
88
|
+
Defines how long the transition animation lasts.
|
|
89
|
+
|
|
90
|
+
Example:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"transitionDuration": "1500"
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Result:
|
|
99
|
+
|
|
100
|
+
```text
|
|
101
|
+
1.5 second transition
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Images
|
|
107
|
+
|
|
108
|
+
Images must be provided as an ordered array of URLs.
|
|
109
|
+
|
|
110
|
+
The component displays images in the exact order they appear in the array.
|
|
111
|
+
|
|
112
|
+
Example:
|
|
113
|
+
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"images": [
|
|
117
|
+
"image-1.jpg",
|
|
118
|
+
"image-2.jpg",
|
|
119
|
+
"image-3.jpg"
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Display order:
|
|
125
|
+
|
|
126
|
+
```text
|
|
127
|
+
image-1
|
|
128
|
+
↓
|
|
129
|
+
image-2
|
|
130
|
+
↓
|
|
131
|
+
image-3
|
|
132
|
+
↓
|
|
133
|
+
image-1
|
|
134
|
+
(repeat)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
# Usage
|
|
140
|
+
|
|
141
|
+
## Static Pages
|
|
142
|
+
|
|
143
|
+
For static pages only `data-gh-id` is required.
|
|
144
|
+
|
|
145
|
+
```html
|
|
146
|
+
<video-slider
|
|
147
|
+
data-gh-id="video-slider"
|
|
148
|
+
></video-slider>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Dynamic Pages
|
|
154
|
+
|
|
155
|
+
For dynamic pages an additional `data-chapter` attribute must be specified.
|
|
156
|
+
|
|
157
|
+
```html
|
|
158
|
+
<video-slider
|
|
159
|
+
data-gh-id="video-slider"
|
|
160
|
+
data-chapter="areas"
|
|
161
|
+
></video-slider>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### data-chapter
|
|
165
|
+
|
|
166
|
+
Defines the chapter from which GudHub should load dynamic page data.
|
|
167
|
+
|
|
168
|
+
Example:
|
|
169
|
+
|
|
170
|
+
```html
|
|
171
|
+
data-chapter="areas"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
# Required Attributes
|
|
177
|
+
|
|
178
|
+
| Attribute | Required | Description |
|
|
179
|
+
| ------------ | ------------------ | ------------------------------------------ |
|
|
180
|
+
| data-gh-id | Yes | GudHub component identifier |
|
|
181
|
+
| data-chapter | Dynamic pages only | Chapter used to retrieve current item data |
|
|
182
|
+
|
|
183
|
+
---
|
|
184
|
+
|
|
185
|
+
# Example
|
|
186
|
+
|
|
187
|
+
```html
|
|
188
|
+
<video-slider
|
|
189
|
+
data-gh-id="video-slider"
|
|
190
|
+
data-chapter="areas"
|
|
191
|
+
></video-slider>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
```json
|
|
195
|
+
{
|
|
196
|
+
"video-slider": {
|
|
197
|
+
"animation": "fade",
|
|
198
|
+
"slideDuration": "3000",
|
|
199
|
+
"transitionDuration": "1500",
|
|
200
|
+
"images": [
|
|
201
|
+
"https://example.com/slide-1.jpg",
|
|
202
|
+
"https://example.com/slide-2.jpg",
|
|
203
|
+
"https://example.com/slide-3.jpg"
|
|
204
|
+
]
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
# Notes
|
|
212
|
+
|
|
213
|
+
* All images should be publicly accessible URLs.
|
|
214
|
+
* Images are preloaded before animation starts.
|
|
215
|
+
* The slider automatically loops through all images.
|
|
216
|
+
* Images are displayed using a cover-fit algorithm similar to CSS `object-fit: cover`.
|
|
217
|
+
* Animation starts automatically after component initialization.
|
|
218
|
+
* If an invalid animation name is provided, no transition animation will be rendered.
|
package/src/config.js
CHANGED
|
@@ -67,9 +67,9 @@ export { GoogleAnalytics } from './components/google-analytics/config.js';
|
|
|
67
67
|
export { GoogleTag } from './components/google-tag/config.js';
|
|
68
68
|
export { cookiesPopup } from './components/cookies-popup/config.js';
|
|
69
69
|
export { infoTable } from './components/info-table/config.js';
|
|
70
|
-
export { liqpayPaymentButton } from './components/liqpay-payment-button/config.js';
|
|
71
70
|
export { liqpayComponent } from './components/liqpay-component/config.js';
|
|
72
71
|
export { faqComponent } from './components/faq-component/config.js';
|
|
72
|
+
export { videoSlider } from './components/video-slider/config.js';
|
|
73
73
|
|
|
74
74
|
// export { liqPayComponent } from './components/liqpay-component/config.js';
|
|
75
75
|
// export { htmlTextFromEditorJs } from './components/html-text-from-editor-js/config.js';
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import html from './liqpay-payment-button.html';
|
|
2
|
-
import './liqpay-payment-button.scss';
|
|
3
|
-
import jsonTemplate from './liqpay-payment-button.json';
|
|
4
|
-
|
|
5
|
-
class liqpayPaymentButton extends window.GHComponent {
|
|
6
|
-
constructor() {
|
|
7
|
-
super();
|
|
8
|
-
super.setDefaultData(jsonTemplate);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async onServerRender() {
|
|
12
|
-
this.ghId = this.getAttribute('data-gh-id') || null;
|
|
13
|
-
this.json = await super.getGhData(this.ghId, 'areas');
|
|
14
|
-
|
|
15
|
-
console.log("AAAAAAAAAAAAAAAAAAAAAAAA", this.json);
|
|
16
|
-
|
|
17
|
-
if (this.json) {
|
|
18
|
-
super.render(html);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
window.customElements.define('liqpay-payment-button', liqpayPaymentButton);
|
|
File without changes
|