Кроме того, при увеличении штифта ScrollTrigger/Seplage Feels Fresset по сравнению с неквалифицированной базовой линией (Drift).
spect seectset по сравнению с неквалифицированной базовой линией (Drift).
Код: Выделить всё
px-lock + GSAP MRE
(function(){
var vv = window.visualViewport;
var z = (vv && typeof vv.scale === 'number' && vv.scale !== 1) ? vv.scale
: (window.devicePixelRatio || 1);
var scale = (z < 1) ? (1 / z) : 1; // neutralize only zoom-out
var root = document.documentElement;
root.style.setProperty('--pxlock-scale', String(scale));
root.setAttribute('data-scale', scale === 1 ? '1' : 'x');
})();
:root { --pxlock-scale: 1; --pxlock-zoom: 1; }
/* auto-detect: Chromium uses zoom; FF/Safari use transform */
:root[data-pxmode="zoom"] #px-lock { zoom: var(--pxlock-zoom); }
:root[data-pxmode="transform"] #px-lock {
transform-origin: top left;
transform: scale(var(--pxlock-scale));
width: calc(100% / var(--pxlock-scale));
min-height: calc(100% / var(--pxlock-scale));
backface-visibility: hidden;
will-change: transform;
}
:root[data-pxmode="transform"][data-scale="1"] #px-lock {
transform:none; width:auto; min-height:auto;
}
body { margin: 0; font-family: system-ui, sans-serif; color: #eee; background:#0c1624; }
.site-header { position: sticky; top:0; background:#0b1220; padding:16px; z-index:10; }
.hero { height: 100vh; display:grid; place-items:center; }
.scroll-lock-section {
min-height: 85vh; display:flex; align-items:center; justify-content:center; padding: 0 20px;
}
.scroll-fade-text { font-size:48px; line-height:1.5; text-align:center; max-width:1000px; }
.scroll-fade-text .word { color: gray; transition: color .4s ease; }
.filler { height: 120vh; }
[b]Header[/b]
Hero
Want to move to a tax free country? We are here to help you move your personal taxes to a country that does not tax your broad income. We can help you to get your Paraguayan residency and also register you at a Tax Office (DNIT).
// ---------- px-lock runtime ----------
(function () {
const root = document.documentElement;
const supportsZoom = ('zoom' in root.style); // Chrome/Edge true, FF/Safari false
root.setAttribute('data-pxmode', supportsZoom ? 'zoom' : 'transform');
let last = { scale: 1, mode: root.getAttribute('data-pxmode') };
function readZoom() {
const vv = window.visualViewport;
const zVV = (vv && typeof vv.scale === 'number' && vv.scale > 0) ? vv.scale : 1; // Chromium/Safari 17+
const zDPR = (typeof window.devicePixelRatio === 'number' && window.devicePixelRatio > 0) ? window.devicePixelRatio : 1;
const zSW = (window.screen && window.innerWidth) ? (screen.width / window.innerWidth) : 1;// Chromium-friendly
const zOW = (typeof window.outerWidth === 'number' && window.outerWidth > 0 && window.innerWidth > 0)
? (window.outerWidth / window.innerWidth) : 1; // FF/Safari desktop
const z = Math.min(zVV, zDPR, zSW, zOW);
return Math.max(0.01, Math.min(1, +z.toFixed(3))); // (0,1], smaller = more zoom-out
}
let raf = 0;
function applyScale() {
if (raf) return;
raf = requestAnimationFrame(() => {
raf = 0;
const z = readZoom();
const neutral = (z < 1) ? (1 / z) : 1; // only neutralize zoom-out
root.style.setProperty('--pxlock-scale', String(neutral));
root.style.setProperty('--pxlock-zoom', String(neutral));
root.setAttribute('data-scale', neutral === 1 ? '1' : 'x');
const mode = root.getAttribute('data-pxmode');
window.__pxPinType = (mode === 'transform' && neutral !== 1) ? 'transform' : 'fixed';
const changed = Math.abs(neutral - last.scale) > 0.0005 || last.mode !== mode;
if (changed) {
last = { scale: neutral, mode };
window.dispatchEvent(new CustomEvent('pxlock:scalechange', { detail: { scale: neutral, mode } }));
}
});
}
// initial
applyScale();
// events that hint zoom/DPR changes
const vv = window.visualViewport;
if (vv) {
vv.addEventListener('resize', applyScale, { passive: true });
vv.addEventListener('scroll', applyScale, { passive: true });
}
window.addEventListener('resize', applyScale, { passive: true });
window.addEventListener('orientationchange', applyScale);
window.addEventListener('focus', applyScale);
document.addEventListener('visibilitychange', () => { if (!document.hidden) applyScale(); });
})();
// ---------- GSAP / ScrollTrigger ----------
let scrollSplit;
function cleanupAnimation() {
ScrollTrigger.getAll().forEach(t => t.kill());
if (scrollSplit) { try { scrollSplit.revert(); } catch(e) {} scrollSplit = null; }
}
function setupAnimation() {
const target = document.querySelector('.scroll-fade-text');
if (!target || target.textContent.trim() === '') return;
scrollSplit = new SplitType(target, { types: 'words', wordClass: 'word' });
gsap.to(scrollSplit.words, {
color: "white",
stagger: 0.3,
ease: "none",
scrollTrigger: {
trigger: ".scroll-lock-section",
start: "top top",
end: "+=1000",
scrub: true,
pin: true,
invalidateOnRefresh: true,
// I tried these variations too (didn't fully fix drift):
// pinType: window.__pxPinType || 'fixed',
// pinnedContainer: document.getElementById('px-lock'),
// pinReparent: true
}
});
}
document.addEventListener('DOMContentLoaded', setupAnimation);
// Rebuild only the trigger on px-lock scale changes (no re-split)
let __rebuildTO = 0;
window.addEventListener('pxlock:scalechange', () => {
if (!scrollSplit) return;
const prev = ScrollTrigger.getAll().map(t => t.progress);
clearTimeout(__rebuildTO);
__rebuildTO = setTimeout(() => {
ScrollTrigger.getAll().forEach(t => t.kill(false));
// rebuild:
gsap.to(scrollSplit.words, {
color: "white",
stagger: 0.3,
ease: "none",
scrollTrigger: {
trigger: ".scroll-lock-section",
start: "top top",
end: "+=1000",
scrub: true,
pin: true,
invalidateOnRefresh: true,
}
});
// try to restore progress roughly
const all = ScrollTrigger.getAll();
all.forEach((t,i)=>{ try { t.progress(prev[i] || 0); } catch(e){} });
ScrollTrigger.update();
}, 32);
});
Код: Выделить всё
visualViewport.scale, devicePixelRatio, screen.width/innerWidth, outerWidth/innerWidth(FF/Safari hint).
Код: Выделить всё
Baseline-at-load relative measurements.
Код: Выделить всё
rAF throttling; hysteresis; clamping.
2. Стратегии PIN GSAP
Код: Выделить всё
pinType: 'transform' | 'fixed' (tied to mode).
Код: Выделить всё
pinnedContainer: #px-lock, pinReparent: true.
Код: Выделить всё
Rebuild only the trigger on scale changes; preserve progress.
Код: Выделить всё
min-height: 85vh on the pinned section to avoid cropping with longer i18n content.
3. I18n
Код: Выделить всё
On language swap: cleanupAnimation() (kill triggers + revert SplitType), then apply text, then setupAnimation() (split once per language).
ожидаемое поведение
Во всех современных браузерах (Chrome, Firefox, Safari macos), на любом уровне масштабирования, особенно на 80%, страница должна уже нейтрализована (визуально одинаковый размер на уровне Zoom). 80% - без дрейфа или смещения. Только позже (во время выполнения) он исправляется.
GSAP чувствует себя отключенным при увеличении, даже после восстановления триггера. Первая краска на FF/Safari:
Есть ли надежный, предварительный метод обнаружения увеличения на Firefox/Safari (настольный компьютер) для написания-Pxlock Scale перед CSS (например, Chromium VisualViewport.Scale + DPR)? (Я бы предпочел не скрывать страницу на загрузке.) < /P>
2. Scrolltrigger внутри масштабированного дерева:
Какой правильный/официальный подход GSAP для поддержания PIN/раскрыть визуально, когда пространство координат Scroller «виртуализируется» от родительского преобразования (наш шкала #px-lock)? Нормализуйте Scrolltop/Height по текущей шкале, даже если мы используем Scroller документа по умолчанию?
3. Альтернативный подход: < /strong>
Веб-сайты, которые ведут себя именно так, как мы хотим (например, coinband.io, csullagoadosiseses.com.br), кажутся «нейтрализованы Zoom». Достигается ли это с помощью PX-блока JS, или они используют трюк с макетом жидкости (масштабирование REM/EM/VW), который выглядит нейтрализованным? SplitType (unpkg)
macOS (последний), Chrome/Edge, Firefox, Safari (17+)
Заголовок находится вне #px-lock; Секция Scrolly находится внутри #px-lock . Краска на FF/Safari) была бы очень оценена. Рад отрегулировать MRE, если существует более канонический способ структурирования, закрепляющего внутри масштабированного предка. Это веб -разработчик в течение многих лет сказал мне, что это плавный веб -сайт, к сожалению, он не может мне помочь, поскольку не работает с такими веб -сайтами и никогда не делал его. Но я не понимаю, как Эм или Рим, не вел себя как примеры ...
Подробнее здесь: https://stackoverflow.com/questions/797 ... ss-refresh