Spaces:
Running
Running
simpler arrow shape
Browse files- index.html +17 -41
index.html
CHANGED
@@ -14,14 +14,12 @@
|
|
14 |
height: 100vh;
|
15 |
background-color: black;
|
16 |
}
|
17 |
-
|
18 |
.video-container {
|
19 |
position: relative;
|
20 |
width: 80vw; /* Set the width to 80% of the page */
|
21 |
height: 45vw; /* Maintain aspect ratio */
|
22 |
overflow: hidden;
|
23 |
}
|
24 |
-
|
25 |
video {
|
26 |
position: absolute;
|
27 |
top: 0;
|
@@ -30,16 +28,14 @@
|
|
30 |
height: 100%;
|
31 |
object-fit: cover;
|
32 |
}
|
33 |
-
|
34 |
.second-video {
|
35 |
clip-path: inset(0 50% 0 0);
|
36 |
}
|
37 |
-
|
38 |
.slider {
|
39 |
position: absolute;
|
40 |
top: 0;
|
41 |
left: 30%;
|
42 |
-
width:
|
43 |
height: 100%;
|
44 |
background: rgb(0, 80, 150);
|
45 |
cursor: ew-resize;
|
@@ -48,46 +44,40 @@
|
|
48 |
border-radius: 4px;
|
49 |
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
|
50 |
}
|
51 |
-
|
52 |
.slider::before,
|
53 |
.slider::after {
|
54 |
-
content:
|
55 |
position: absolute;
|
56 |
top: 50%;
|
57 |
transform: translateY(-50%);
|
58 |
-
width:
|
59 |
-
height:
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
text-align: center;
|
64 |
-
line-height: 30px; /* Center text vertically */
|
65 |
-
transition: opacity 0.3s, transform 0.3s; /* Smooth transition */
|
66 |
}
|
67 |
-
|
68 |
.slider::before {
|
69 |
-
left: -
|
|
|
|
|
70 |
}
|
71 |
-
|
72 |
.slider::after {
|
73 |
-
right: -
|
|
|
|
|
74 |
}
|
75 |
-
|
76 |
.slider.ready:hover::before,
|
77 |
.slider.ready:hover::after {
|
78 |
-
transform: translateY(-50%) scale(1.
|
79 |
}
|
80 |
-
|
81 |
.slider.ready::before,
|
82 |
.slider.ready::after {
|
83 |
-
opacity: 0.
|
84 |
}
|
85 |
-
|
86 |
.slider.ready:hover::before,
|
87 |
.slider.ready:hover::after {
|
88 |
-
opacity: 1;
|
89 |
}
|
90 |
-
|
91 |
@keyframes slide-animation {
|
92 |
0% {
|
93 |
left: 100%;
|
@@ -114,7 +104,7 @@
|
|
114 |
<div class="video-container" id="videoContainer">
|
115 |
<video id="video1" src="flir_brain_padded.mp4" playsinline autoplay loop muted></video>
|
116 |
<video id="video2" class="second-video" src="flir_20240905_120243.mp4" playsinline autoplay loop muted></video>
|
117 |
-
<div class="slider" id="slider"
|
118 |
</div>
|
119 |
|
120 |
<script>
|
@@ -122,10 +112,8 @@
|
|
122 |
const container = document.getElementById('videoContainer');
|
123 |
const video1 = document.getElementById('video1');
|
124 |
const video2 = document.getElementById('video2');
|
125 |
-
|
126 |
let isDragging = false;
|
127 |
const syncTolerance = 0.1; // Tolerance in seconds for syncing
|
128 |
-
|
129 |
// Function to sync the second video to the first video
|
130 |
function syncVideos(mainVideo, secondaryVideo) {
|
131 |
if (Math.abs(mainVideo.currentTime - secondaryVideo.currentTime) > syncTolerance) {
|
@@ -137,41 +125,32 @@
|
|
137 |
secondaryVideo.play();
|
138 |
}
|
139 |
}
|
140 |
-
|
141 |
// Set up timeupdate event listeners for smoother sync
|
142 |
video1.addEventListener('timeupdate', () => syncVideos(video1, video2));
|
143 |
video2.addEventListener('timeupdate', () => syncVideos(video2, video1));
|
144 |
-
|
145 |
// Mouse events for slider
|
146 |
slider.addEventListener('mousedown', () => isDragging = true);
|
147 |
window.addEventListener('mouseup', () => isDragging = false);
|
148 |
-
|
149 |
window.addEventListener('mousemove', (event) => {
|
150 |
if (!isDragging) return;
|
151 |
handleSlide(event.clientX);
|
152 |
});
|
153 |
-
|
154 |
// Touch events for slider
|
155 |
slider.addEventListener('touchstart', () => isDragging = true);
|
156 |
window.addEventListener('touchend', () => isDragging = false);
|
157 |
-
|
158 |
window.addEventListener('touchmove', (event) => {
|
159 |
if (!isDragging) return;
|
160 |
handleSlide(event.touches[0].clientX);
|
161 |
});
|
162 |
-
|
163 |
function handleSlide(positionX) {
|
164 |
const rect = container.getBoundingClientRect();
|
165 |
const offsetX = positionX - rect.left;
|
166 |
const sliderPosition = Math.max(0, Math.min(offsetX, rect.width));
|
167 |
-
|
168 |
// Move slider position
|
169 |
slider.style.left = `${sliderPosition}px`;
|
170 |
-
|
171 |
// Adjust second video visibility using clip-path
|
172 |
video2.style.clipPath = `inset(0 ${rect.width - sliderPosition}px 0 0)`;
|
173 |
}
|
174 |
-
|
175 |
// Function to update clip-path in real-time
|
176 |
function updateClipPath() {
|
177 |
const rect = container.getBoundingClientRect();
|
@@ -179,16 +158,13 @@
|
|
179 |
video2.style.clipPath = `inset(0 ${rect.width - sliderPosition}px 0 0)`;
|
180 |
requestAnimationFrame(updateClipPath);
|
181 |
}
|
182 |
-
|
183 |
// Enable user control after the animation ends
|
184 |
slider.addEventListener('animationend', () => {
|
185 |
slider.classList.add('ready');
|
186 |
slider.style.animation = 'none';
|
187 |
slider.style.cursor = 'ew-resize';
|
188 |
slider.style.pointerEvents = 'auto';
|
189 |
-
slider.setAttribute('data-arrow', '<'); // Set left arrow after animation ends
|
190 |
});
|
191 |
-
|
192 |
// Start updating clip-path once the page loads
|
193 |
window.onload = () => updateClipPath();
|
194 |
</script>
|
|
|
14 |
height: 100vh;
|
15 |
background-color: black;
|
16 |
}
|
|
|
17 |
.video-container {
|
18 |
position: relative;
|
19 |
width: 80vw; /* Set the width to 80% of the page */
|
20 |
height: 45vw; /* Maintain aspect ratio */
|
21 |
overflow: hidden;
|
22 |
}
|
|
|
23 |
video {
|
24 |
position: absolute;
|
25 |
top: 0;
|
|
|
28 |
height: 100%;
|
29 |
object-fit: cover;
|
30 |
}
|
|
|
31 |
.second-video {
|
32 |
clip-path: inset(0 50% 0 0);
|
33 |
}
|
|
|
34 |
.slider {
|
35 |
position: absolute;
|
36 |
top: 0;
|
37 |
left: 30%;
|
38 |
+
width: 2px;
|
39 |
height: 100%;
|
40 |
background: rgb(0, 80, 150);
|
41 |
cursor: ew-resize;
|
|
|
44 |
border-radius: 4px;
|
45 |
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
|
46 |
}
|
|
|
47 |
.slider::before,
|
48 |
.slider::after {
|
49 |
+
content: '';
|
50 |
position: absolute;
|
51 |
top: 50%;
|
52 |
transform: translateY(-50%);
|
53 |
+
width: 20px;
|
54 |
+
height: 20px;
|
55 |
+
background-size: contain;
|
56 |
+
background-repeat: no-repeat;
|
57 |
+
transition: opacity 0.3s;
|
|
|
|
|
|
|
58 |
}
|
|
|
59 |
.slider::before {
|
60 |
+
left: -22px;
|
61 |
+
/* Simplified arrowhead pointing left */
|
62 |
+
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="rgb(0, 80, 150)"><polygon points="14,7 8,12 14,17"/></svg>');
|
63 |
}
|
|
|
64 |
.slider::after {
|
65 |
+
right: -22px;
|
66 |
+
/* Simplified arrowhead pointing right */
|
67 |
+
background-image: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="rgb(0, 80, 150)"><polygon points="10,7 16,12 10,17"/></svg>');
|
68 |
}
|
|
|
69 |
.slider.ready:hover::before,
|
70 |
.slider.ready:hover::after {
|
71 |
+
transform: translateY(-50%) scale(1.2);
|
72 |
}
|
|
|
73 |
.slider.ready::before,
|
74 |
.slider.ready::after {
|
75 |
+
opacity: 0.7;
|
76 |
}
|
|
|
77 |
.slider.ready:hover::before,
|
78 |
.slider.ready:hover::after {
|
79 |
+
opacity: 1;
|
80 |
}
|
|
|
81 |
@keyframes slide-animation {
|
82 |
0% {
|
83 |
left: 100%;
|
|
|
104 |
<div class="video-container" id="videoContainer">
|
105 |
<video id="video1" src="flir_brain_padded.mp4" playsinline autoplay loop muted></video>
|
106 |
<video id="video2" class="second-video" src="flir_20240905_120243.mp4" playsinline autoplay loop muted></video>
|
107 |
+
<div class="slider" id="slider"></div>
|
108 |
</div>
|
109 |
|
110 |
<script>
|
|
|
112 |
const container = document.getElementById('videoContainer');
|
113 |
const video1 = document.getElementById('video1');
|
114 |
const video2 = document.getElementById('video2');
|
|
|
115 |
let isDragging = false;
|
116 |
const syncTolerance = 0.1; // Tolerance in seconds for syncing
|
|
|
117 |
// Function to sync the second video to the first video
|
118 |
function syncVideos(mainVideo, secondaryVideo) {
|
119 |
if (Math.abs(mainVideo.currentTime - secondaryVideo.currentTime) > syncTolerance) {
|
|
|
125 |
secondaryVideo.play();
|
126 |
}
|
127 |
}
|
|
|
128 |
// Set up timeupdate event listeners for smoother sync
|
129 |
video1.addEventListener('timeupdate', () => syncVideos(video1, video2));
|
130 |
video2.addEventListener('timeupdate', () => syncVideos(video2, video1));
|
|
|
131 |
// Mouse events for slider
|
132 |
slider.addEventListener('mousedown', () => isDragging = true);
|
133 |
window.addEventListener('mouseup', () => isDragging = false);
|
|
|
134 |
window.addEventListener('mousemove', (event) => {
|
135 |
if (!isDragging) return;
|
136 |
handleSlide(event.clientX);
|
137 |
});
|
|
|
138 |
// Touch events for slider
|
139 |
slider.addEventListener('touchstart', () => isDragging = true);
|
140 |
window.addEventListener('touchend', () => isDragging = false);
|
|
|
141 |
window.addEventListener('touchmove', (event) => {
|
142 |
if (!isDragging) return;
|
143 |
handleSlide(event.touches[0].clientX);
|
144 |
});
|
|
|
145 |
function handleSlide(positionX) {
|
146 |
const rect = container.getBoundingClientRect();
|
147 |
const offsetX = positionX - rect.left;
|
148 |
const sliderPosition = Math.max(0, Math.min(offsetX, rect.width));
|
|
|
149 |
// Move slider position
|
150 |
slider.style.left = `${sliderPosition}px`;
|
|
|
151 |
// Adjust second video visibility using clip-path
|
152 |
video2.style.clipPath = `inset(0 ${rect.width - sliderPosition}px 0 0)`;
|
153 |
}
|
|
|
154 |
// Function to update clip-path in real-time
|
155 |
function updateClipPath() {
|
156 |
const rect = container.getBoundingClientRect();
|
|
|
158 |
video2.style.clipPath = `inset(0 ${rect.width - sliderPosition}px 0 0)`;
|
159 |
requestAnimationFrame(updateClipPath);
|
160 |
}
|
|
|
161 |
// Enable user control after the animation ends
|
162 |
slider.addEventListener('animationend', () => {
|
163 |
slider.classList.add('ready');
|
164 |
slider.style.animation = 'none';
|
165 |
slider.style.cursor = 'ew-resize';
|
166 |
slider.style.pointerEvents = 'auto';
|
|
|
167 |
});
|
|
|
168 |
// Start updating clip-path once the page loads
|
169 |
window.onload = () => updateClipPath();
|
170 |
</script>
|