After following your suggestion, the performance of iOS Safari improved slightly. However, it still is not good enough. I tried putting my code on Codepen to create a demo, but it did not work properly. The code contains about 40 canvas DOM elements in canvases1 to canvases4, and the animation involves spreading these canvases with a goat, sorry to post such a long code here.
function bannerOutAnimation() {
let bannerOut = gsap.timeline({
scrollTrigger: {
trigger: ".second-page",
start: "top bottom",
scrub: 1,
end: `+=${window.innerHeight}`,
toggleActions: "play none none reverse",
ignoreMobileResize: true
},
force3D: true, // 触发硬件加速
});
const canvases1 = gsap.utils.toArray('.addCanvas:nth-of-type(4n+2)');
const canvases2 = gsap.utils.toArray('.addCanvas:nth-of-type(4n+3)');
const canvases3 = gsap.utils.toArray('.addCanvas:nth-of-type(4n+4)');
const canvases4 = gsap.utils.toArray('.addCanvas:nth-of-type(4n+5)');
bannerOut.to(".banner-paraBox", {
opacity: 0,
y: -window.innerHeight / 2,
duration: 500 / window.innerHeight
}).to(canvases1, {
y: (index, target) => {
let yDistance;
if (index >= Math.round(blocksNum.x / 2)) {
if (index == Math.round(blocksNum.x / 2)) {
yDistance = window.innerHeight * 2
} else if (index % Math.round(blocksNum.x / 2) == 1) {
yDistance = window.innerHeight * 1.8
} else if (index % Math.round(blocksNum.x / 2) == 2) {
yDistance = window.innerHeight * 1.6
} else if (index % Math.round(blocksNum.x / 2) == 3) {
yDistance = window.innerHeight * 1.4
} else if (index % Math.round(blocksNum.x / 2) == 4) {
yDistance = window.innerHeight * 1.2
} else if (index % Math.round(blocksNum.x / 2) == 0) {
yDistance = window.innerHeight * 1
}
} else {
if (index % Math.round(blocksNum.x / 2) == 4) {
yDistance = window.innerHeight * 1.8
} else if (index % Math.round(blocksNum.x / 2) == 3) {
yDistance = window.innerHeight * 1.6
} else if (index % Math.round(blocksNum.x / 2) == 2) {
yDistance = window.innerHeight * 1.4
} else if (index % Math.round(blocksNum.x / 2) == 1) {
yDistance = window.innerHeight * 1.2
} else if (index % Math.round(blocksNum.x / 2) == 0) {
yDistance = window.innerHeight * 1
}
}
return `-${yDistance}px`;
},
duration: 1
}, "<").to(canvases2, {
y: (index, target) => {
let yDistance;
if (index % 2 == 0) {
yDistance = window.innerHeight * 1.6
} else {
yDistance = window.innerHeight * 1.35
}
return `-${yDistance}px`;
},
duration: 1
}, "<").fromTo(canvases2, {
x: 0
}, {
x: (index, target) => {
let xDistance;
let side = index < Math.round(blocksNum.x / 2) ? -1 : 1
if (index >= Math.round(blocksNum.x / 2)) {
if (index == Math.round(blocksNum.x / 2)) {
xDistance = 0
} else if (index % Math.round(blocksNum.x / 2) == 1) {
xDistance = side * 35
} else if (index % Math.round(blocksNum.x / 2) == 2) {
xDistance = side * 70
} else if (index % Math.round(blocksNum.x / 2) == 3) {
xDistance = side * 105
} else if (index % Math.round(blocksNum.x / 2) == 4) {
xDistance = side * 140
} else if (index % Math.round(blocksNum.x / 2) == 0) {
xDistance = side * 175
}
} else {
if (index % Math.round(blocksNum.x / 2) == 4) {
xDistance = side * 35
} else if (index % Math.round(blocksNum.x / 2) == 3) {
xDistance = side * 70
} else if (index % Math.round(blocksNum.x / 2) == 2) {
xDistance = side * 105
} else if (index % Math.round(blocksNum.x / 2) == 1) {
xDistance = side * 140
} else if (index % Math.round(blocksNum.x / 2) == 0) {
xDistance = side * 175
}
}
return `${xDistance}px`;
},
}, "<").to(canvases3, {
y: (index, target) => {
let yDistance;
if (index >= Math.round(blocksNum.x / 2)) {
if (index == Math.round(blocksNum.x / 2)) {
yDistance = window.innerHeight * 1.5
} else if (index % Math.round(blocksNum.x / 2) == 1) {
yDistance = window.innerHeight * 1.3
} else if (index % Math.round(blocksNum.x / 2) == 2) {
yDistance = window.innerHeight * 1.2
} else if (index % Math.round(blocksNum.x / 2) == 3) {
yDistance = window.innerHeight * 1.1
} else if (index % Math.round(blocksNum.x / 2) == 4) {
yDistance = window.innerHeight * 1
} else if (index % Math.round(blocksNum.x / 2) == 0) {
yDistance = window.innerHeight * 0.9
}
} else {
if (index % Math.round(blocksNum.x / 2) == 4) {
yDistance = window.innerHeight * 1.3
} else if (index % Math.round(blocksNum.x / 2) == 3) {
yDistance = window.innerHeight * 1.2
} else if (index % Math.round(blocksNum.x / 2) == 2) {
yDistance = window.innerHeight * 1.1
} else if (index % Math.round(blocksNum.x / 2) == 1) {
yDistance = window.innerHeight * 1
} else if (index % Math.round(blocksNum.x / 2) == 0) {
yDistance = window.innerHeight * 0.9
}
}
return `-${yDistance}px`;
},
duration: 1
}, "<").fromTo(canvases3, {
x: 0
}, {
x: (index, target) => {
let xDistance;
let side = index < Math.round(blocksNum.x / 2) ? -1 : 1
if (index >= Math.round(blocksNum.x / 2)) {
if (index == Math.round(blocksNum.x / 2)) {
xDistance = 0
} else if (index % Math.round(blocksNum.x / 2) == 1) {
xDistance = side * window.innerWidth / 35
} else if (index % Math.round(blocksNum.x / 2) == 2) {
xDistance = side * window.innerWidth / 35 * 2
} else if (index % Math.round(blocksNum.x / 2) == 3) {
xDistance = side * window.innerWidth / 35 * 3
} else if (index % Math.round(blocksNum.x / 2) == 4) {
xDistance = side * window.innerWidth / 35 * 4
} else if (index % Math.round(blocksNum.x / 2) == 0) {
xDistance = side * window.innerWidth / 35 * 5
}
} else {
if (index % Math.round(blocksNum.x / 2) == 4) {
xDistance = side * window.innerWidth / 35
} else if (index % Math.round(blocksNum.x / 2) == 3) {
xDistance = side * window.innerWidth / 35 * 2
} else if (index % Math.round(blocksNum.x / 2) == 2) {
xDistance = side * window.innerWidth / 35 * 3
} else if (index % Math.round(blocksNum.x / 2) == 1) {
xDistance = side * window.innerWidth / 35 * 4
} else if (index % Math.round(blocksNum.x / 2) == 0) {
xDistance = side * window.innerWidth / 35 * 5
}
}
return `${xDistance}px`;
},
}, "<").to(canvases4, {
y: (index, target) => {
let yDistance;
if (index >= Math.round(blocksNum.x / 2)) {
if (index == Math.round(blocksNum.x / 2)) {
yDistance = window.innerHeight * 1.3
} else if (index % Math.round(blocksNum.x / 2) == 1) {
yDistance = window.innerHeight * 1.2
} else if (index % Math.round(blocksNum.x / 2) == 2) {
yDistance = window.innerHeight * 1.1
} else if (index % Math.round(blocksNum.x / 2) == 3) {
yDistance = window.innerHeight * 0.9
} else if (index % Math.round(blocksNum.x / 2) == 4) {
yDistance = window.innerHeight * 0.6
} else if (index % Math.round(blocksNum.x / 2) == 0) {
yDistance = window.innerHeight * 0.4
}
} else {
if (index % Math.round(blocksNum.x / 2) == 4) {
yDistance = window.innerHeight * 1.4
} else if (index % Math.round(blocksNum.x / 2) == 3) {
yDistance = window.innerHeight * 1.2
} else if (index % Math.round(blocksNum.x / 2) == 2) {
yDistance = window.innerHeight * 0.9
} else if (index % Math.round(blocksNum.x / 2) == 1) {
yDistance = window.innerHeight * 0.6
} else if (index % Math.round(blocksNum.x / 2) == 0) {
yDistance = window.innerHeight * 0.4
}
}
return `-${yDistance}px`;
},
duration: 1
}, "<").fromTo(canvases4, {
x: 0
}, {
x: (index, target) => {
let xDistance;
let side = index < Math.round(blocksNum.x / 2) ? -1 : 1
if (index >= Math.round(blocksNum.x / 2)) {
if (index == Math.round(blocksNum.x / 2)) {
xDistance = 0
} else if (index % Math.round(blocksNum.x / 2) == 1) {
xDistance = side * window.innerWidth / 30
} else if (index % Math.round(blocksNum.x / 2) == 2) {
xDistance = side * window.innerWidth / 30 * 2
} else if (index % Math.round(blocksNum.x / 2) == 3) {
xDistance = side * window.innerWidth / 30 * 3
} else if (index % Math.round(blocksNum.x / 2) == 4) {
xDistance = side * window.innerWidth / 30 * 4
} else if (index % Math.round(blocksNum.x / 2) == 0) {
xDistance = side * window.innerWidth / 30 * 5
}
} else {
if (index % Math.round(blocksNum.x / 2) == 4) {
xDistance = side * window.innerWidth / 30
} else if (index % Math.round(blocksNum.x / 2) == 3) {
xDistance = side * window.innerWidth / 30 * 2
} else if (index % Math.round(blocksNum.x / 2) == 2) {
xDistance = side * window.innerWidth / 30 * 3
} else if (index % Math.round(blocksNum.x / 2) == 1) {
xDistance = side * window.innerWidth / 30 * 4
} else if (index % Math.round(blocksNum.x / 2) == 0) {
xDistance = side * window.innerWidth / 30 * 5
}
}
return `${xDistance}px`;
},
}, "<").from(".second-page", {
duration: 0.6,
opacity: 0,
}, "<")
}