Skip to content

Commit dd7cf75

Browse files
committed
Optimize animations for tablet devices
1 parent a38fe1e commit dd7cf75

File tree

6 files changed

+74
-63
lines changed

6 files changed

+74
-63
lines changed

index.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html lang="en">
33
<head>
44
<meta charset="UTF-8" />
5-
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
5+
<link rel="icon" type="image/svg+xml" href="/logo.png" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<title>BioDetect</title>
88
</head>

public/logo.png

24.8 KB
Loading

public/logo.svg

-1
This file was deleted.

src/components/WebgiViewer.jsx

+29-14
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
import React, {
22
useRef,
3-
useState,
43
useCallback,
5-
forwardRef,
6-
useImperativeHandle,
74
useEffect,
85
} from "react";
96
import {
@@ -17,7 +14,6 @@ import {
1714
GLTFAnimationPlugin,
1815
BloomPlugin,
1916
GammaCorrectionPlugin,
20-
mobileAndTabletCheck,
2117
} from "webgi";
2218
import gsap from "gsap";
2319
import { ScrollTrigger } from "gsap/src/ScrollTrigger";
@@ -27,14 +23,19 @@ gsap.registerPlugin(ScrollTrigger);
2723

2824
const WebgiViewer = () => {
2925
const canvasRef = useRef(null);
26+
const isMobile = window.innerWidth < 768;
27+
const isTablet =
28+
(window.innerWidth >= 768 && window.innerWidth <= 1024) ||
29+
/ipad|android(?!.*mobile)|tablet|playbook|silk/i.test(navigator.userAgent);
3030

3131
const memoizedScrollAnimation = useCallback(
32-
(position, target, onUpdate) => {
32+
(position, target, onUpdate, viewer, isTablet) => {
3333
if (position && target && onUpdate) {
34-
scrollAnimation(position, target, onUpdate);
34+
scrollAnimation(position, target, onUpdate, viewer, isTablet);
3535
}
36-
}, []
37-
)
36+
},
37+
[]
38+
);
3839

3940
const setupViewer = useCallback(async () => {
4041
const viewer = new ViewerApp({
@@ -53,17 +54,23 @@ const WebgiViewer = () => {
5354
await viewer.addPlugin(GammaCorrectionPlugin);
5455
await viewer.addPlugin(SSRPlugin);
5556
await viewer.addPlugin(SSAOPlugin);
56-
await viewer.addPlugin(GLTFAnimationPlugin)
57+
await viewer.addPlugin(GLTFAnimationPlugin);
5758
await viewer.addPlugin(BloomPlugin);
5859

5960
viewer.renderer.refreshPipeline();
6061

61-
await assetManager.addFromPath("scene.glb");
62+
const model = await assetManager.addFromPath("scene.glb");
63+
console.log("Model loaded: ", model);
64+
65+
if (!model) {
66+
console.error("Model not loaded.");
67+
return;
68+
}
6269

6370
const gltfAnims = viewer.getPlugin(GLTFAnimationPlugin);
6471

65-
const resetOnEnd = true
66-
await gltfAnims.playClip('Take 001', resetOnEnd)
72+
const resetOnEnd = true;
73+
await gltfAnims.playClip("Take 001", resetOnEnd);
6774

6875
viewer.getPlugin(TonemapPlugin).config.clipBackground = true;
6976

@@ -75,21 +82,29 @@ const WebgiViewer = () => {
7582
const onUpdate = () => {
7683
needsUpdate = true;
7784
viewer.setDirty();
78-
}
85+
};
7986

8087
viewer.addEventListener("preFrame", () => {
8188
if (needsUpdate) {
8289
camera.positionTargetUpdated(true);
8390
needsUpdate = false;
8491
}
8592
});
86-
memoizedScrollAnimation(position, target, onUpdate)
93+
memoizedScrollAnimation(position, target, onUpdate, viewer, isTablet);
8794
}, []);
8895

8996
useEffect(() => {
9097
setupViewer();
9198
}, []);
9299

100+
if (isMobile) {
101+
return (
102+
<div>
103+
Sorry, 3D model is not available on mobile devices.
104+
</div>
105+
);
106+
}
107+
93108
return (
94109
<div id="webgi-canvas-container">
95110
<canvas id="webgi-canvas" ref={canvasRef} />

src/index.css

+6-18
Original file line numberDiff line numberDiff line change
@@ -56,24 +56,6 @@ body::-webkit-scrollbar-thumb {
5656
background: transparent;
5757
}
5858

59-
#webgi-canvas-container .button {
60-
background: #0071e3;
61-
color: #fff;
62-
cursor: pointer;
63-
text-align: center;
64-
white-space: nowrap;
65-
font-size: 17px;
66-
font-weight: 400;
67-
min-width: 28px;
68-
padding: 8px 16px;
69-
border-radius: 980px;
70-
position: absolute;
71-
top: 30px;
72-
border: none;
73-
z-index: 1;
74-
transition-duration: 0.3s;
75-
}
76-
7759
.display-section.wrapper {
7860
margin-left: auto;
7961
margin-right: auto;
@@ -275,6 +257,7 @@ nav .link-styled {
275257
letter-spacing: -0.022em;
276258
position: relative;
277259
min-width: auto;
260+
pointer-events: none;
278261
}
279262

280263
.first-plant {
@@ -710,6 +693,11 @@ nav .link-styled {
710693
}
711694

712695
/* Media Queries */
696+
@media screen and (max-width: 1024px) {
697+
#webgi-canvas-container {
698+
margin-top: -16rem;
699+
}
700+
}
713701

714702
@media screen and (max-width: 950px) {
715703
.jumbotron-section.wrapper {

src/lib/scroll-animation.js

+38-29
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,52 @@
11
import gsap from "gsap";
22

3-
export const scrollAnimation = (position, target, onUpdate) => {
3+
export const scrollAnimation = (position, target, onUpdate, viewer, isTablet) => {
44
const tl = gsap.timeline();
5+
const model = viewer.scene.getObjectByName("Sketchfab_Scene");
56

6-
tl.to(position, {
7-
x: 8.2617479743,
8-
y: 0.0262229300,
9-
z: 4.8205182659,
7+
const scale = isTablet ? 0.6 : 0.9;
8+
9+
tl.to(model.scale, {
10+
x: scale,
11+
y: scale,
12+
z: scale,
13+
duration: 1,
14+
ease: "power2.inOut"
15+
})
16+
.to(position, {
17+
x: 8.26,
18+
y: 0.03,
19+
z: 4.82,
1020
scrollTrigger: {
1121
trigger: '.first-plant',
12-
start: 'top 75%',
22+
start: isTablet ? 'top 20%' : 'top 75%',
1323
end: 'top top',
14-
scrub: 2,
24+
scrub: 3,
1525
immediateRender: false,
1626
ease: "power2.inOut"
1727
},
1828
onUpdate
1929
})
2030
.to(target, {
21-
x: 3.50,
31+
x: isTablet ? 2.50 : 3.50,
2232
y: 0.00,
2333
z: 0.00,
2434
scrollTrigger: {
2535
trigger: '.first-plant',
26-
start: 'top 75%',
36+
start: isTablet ? 'top 20%' : 'top 75%',
2737
end: 'top top',
28-
scrub: 2,
38+
scrub: 3,
2939
immediateRender: false,
3040
ease: "power2.inOut"
3141
},
3242
})
3343
.to(position, {
34-
x: -1.8849842312,
35-
y: -8.957473565,
36-
z: 0.4051478909,
44+
x: isTablet ? -1.00 : -1.88,
45+
y: isTablet ? -9.02 : -8.96,
46+
z: isTablet ? 0.38 : 0.41,
3747
scrollTrigger: {
3848
trigger: '.description-section',
39-
start: 'top 75%',
49+
start: isTablet ? 'top 30%' : 'top 75%',
4050
end: 'top top',
4151
scrub: 2,
4252
immediateRender: false,
@@ -45,24 +55,24 @@ export const scrollAnimation = (position, target, onUpdate) => {
4555
onUpdate
4656
})
4757
.to(target, {
48-
x: -1.90,
49-
y: 0.36,
50-
z: 0.00,
58+
x: isTablet ? -1.00 : -1.90,
59+
y: isTablet ? -2.50 : 0.36,
60+
z: isTablet ? 0.00 : 0.00,
5161
scrollTrigger: {
5262
trigger: '.description-section',
53-
start: 'top 75%',
63+
start: isTablet ? 'top 30%' : 'top 75%',
5464
end: 'top top',
5565
scrub: 2,
5666
immediateRender: false
5767
},
5868
})
5969
.to(position, {
60-
x: -0.2774669079,
61-
y: 2.41,
62-
z: 9.752114362,
70+
x: isTablet ? 0.06 : -0.28,
71+
y: isTablet ? 0.48 : 2.41,
72+
z: isTablet ? 11.24 : 9.75,
6373
scrollTrigger: {
6474
trigger: '.display-section',
65-
start: 'top 75%',
75+
start: isTablet ? 'top 20%' : 'top 75%',
6676
end: 'top top',
6777
scrub: 2,
6878
immediateRender: false,
@@ -76,19 +86,19 @@ export const scrollAnimation = (position, target, onUpdate) => {
7686
z: 0.00,
7787
scrollTrigger: {
7888
trigger: '.display-section',
79-
start: 'top 75%',
89+
start: isTablet ? 'top 20%' : 'top 75%',
8090
end: 'top top',
8191
scrub: 2,
8292
immediateRender: false
8393
},
8494
})
8595
.to(position, {
86-
x: 1.8031021426,
87-
y: -9.5813723357,
88-
z: 2.671923614,
96+
x: 1.80,
97+
y: -9.58,
98+
z: 2.67,
8999
scrollTrigger: {
90100
trigger: '.about-section',
91-
start: 'top 85%',
101+
start: isTablet ? 'top 20%' : 'top 85%',
92102
end: 'top top',
93103
scrub: 2,
94104
immediateRender: false,
@@ -102,11 +112,10 @@ export const scrollAnimation = (position, target, onUpdate) => {
102112
z: -1.80,
103113
scrollTrigger: {
104114
trigger: '.about-section',
105-
start: 'top 50%',
115+
start: isTablet ? 'top 20%' : 'top 50%',
106116
end: 'top top',
107117
scrub: 2,
108118
immediateRender: false
109119
},
110120
})
111-
112121
}

0 commit comments

Comments
 (0)