admin管理员组文章数量:1415145
I have a feature on my website where the logo scrolls vertically depending on the users position on the site.
You can see it working on Chrome here
However it does not work on Safari, which includes mobile and tablet.
The scroll position does not seem to change at all in the console.
// logo positioning
let logos, logoHeight, barTopMargin;
let viewportHeight;
window.addEventListener('load', init);
window.addEventListener('resize', setSizes);
document.addEventListener('scroll', update);
function init(lockUpdate) {
logos = document.querySelectorAll('.scroll-text');
setSizes(lockUpdate);
}
function update() {
// ensure initialization and prevent recursive call
if (!logos) init(true);
//*************************************************
/**************************************************
THIS LINE MUST BE HERE.
**************************************************/
let maxScrollDist = document.documentElement.scrollHeight - viewportHeight;
//*************************************************
let currentScrollPos = document.documentElement.scrollTop;
let newTop;
let middle = currentScrollPos + viewportHeight/2;
let middleY = maxScrollDist/2;
if (middle >= (maxScrollDist+viewportHeight)/2) {
let p = (middleY - Math.floor(middle - (maxScrollDist+viewportHeight)/2))*100/middleY;
newTop = viewportHeight/2 - logoHeight/2;
newTop += (100-p)*(viewportHeight/2)/100;
newTop -= (100-p)*(barTopMargin +logoHeight/2)/100;
newTop = Math.max(newTop, viewportHeight/2 - logoHeight/2); /*fix*/
} else {
let p = (middleY - Math.floor(-middle + (maxScrollDist+viewportHeight)/2))*100/middleY;
newTop = barTopMargin*(100-p)/100+(viewportHeight/2 - (logoHeight/2)*p/100 )*p/100;
newTop = Math.min(newTop, viewportHeight/2 - logoHeight/2); /*fix*/
}
logos.forEach(function(el) {
el.style.top = newTop + "px";
});
}
function setSizes(lockUpdate) {
logoHeight = logos[0].offsetHeight;
barTopMargin = parseInt(getComputedStyle(document.querySelector('#page'), '::before').top);
viewportHeight = window.innerHeight;
if (lockUpdate === true) return;
update();
}
I have a feature on my website where the logo scrolls vertically depending on the users position on the site.
You can see it working on Chrome here
However it does not work on Safari, which includes mobile and tablet.
The scroll position does not seem to change at all in the console.
// logo positioning
let logos, logoHeight, barTopMargin;
let viewportHeight;
window.addEventListener('load', init);
window.addEventListener('resize', setSizes);
document.addEventListener('scroll', update);
function init(lockUpdate) {
logos = document.querySelectorAll('.scroll-text');
setSizes(lockUpdate);
}
function update() {
// ensure initialization and prevent recursive call
if (!logos) init(true);
//*************************************************
/**************************************************
THIS LINE MUST BE HERE.
**************************************************/
let maxScrollDist = document.documentElement.scrollHeight - viewportHeight;
//*************************************************
let currentScrollPos = document.documentElement.scrollTop;
let newTop;
let middle = currentScrollPos + viewportHeight/2;
let middleY = maxScrollDist/2;
if (middle >= (maxScrollDist+viewportHeight)/2) {
let p = (middleY - Math.floor(middle - (maxScrollDist+viewportHeight)/2))*100/middleY;
newTop = viewportHeight/2 - logoHeight/2;
newTop += (100-p)*(viewportHeight/2)/100;
newTop -= (100-p)*(barTopMargin +logoHeight/2)/100;
newTop = Math.max(newTop, viewportHeight/2 - logoHeight/2); /*fix*/
} else {
let p = (middleY - Math.floor(-middle + (maxScrollDist+viewportHeight)/2))*100/middleY;
newTop = barTopMargin*(100-p)/100+(viewportHeight/2 - (logoHeight/2)*p/100 )*p/100;
newTop = Math.min(newTop, viewportHeight/2 - logoHeight/2); /*fix*/
}
logos.forEach(function(el) {
el.style.top = newTop + "px";
});
}
function setSizes(lockUpdate) {
logoHeight = logos[0].offsetHeight;
barTopMargin = parseInt(getComputedStyle(document.querySelector('#page'), '::before').top);
viewportHeight = window.innerHeight;
if (lockUpdate === true) return;
update();
}
Share
Improve this question
edited Nov 17, 2019 at 23:59
n1stre
6,0964 gold badges23 silver badges42 bronze badges
asked Nov 4, 2019 at 12:22
Mr ToadMr Toad
2562 gold badges14 silver badges46 bronze badges
3
- Possible duplicate of stackoverflow./questions/1830080/… – Prabhjot Singh Kainth Commented Nov 15, 2019 at 15:55
- Have a look at some of these suggestions: github./nuxt/nuxt.js/issues/2512 – Brett Gregson Commented Nov 15, 2019 at 15:55
- Thanks Brett - I did actually look at this, but unfortunately I don't understand JS or the syntax enough to know HOW to apply this information. – Mr Toad Commented Nov 20, 2019 at 12:48
1 Answer
Reset to default 6 +100The reason behind this behavior is laid inside the difference in scrolling implementation between the browsers. For example Chrome calculates page scrolling based on the <html>
, while Safari does the same on the <body>
.
Chrome:
Safari:
Considering this info it would reasonable to assume that in Safari document.documentElement
is pletely unaware of page global scrolling value.
And to fix this issue you could define a helper func that uses document.scrollingElement
with fallback to getBoundingClientRect
on document.documentElement
:
function getScrollingElement() {
if (document.scrollingElement) {
return document.scrollingElement;
}
const docElement = document.documentElement;
const docElementRect = docElement.getBoundingClientRect();
return {
scrollHeight: Math.ceil(docElementRect.height),
scrollTop: Math.abs(docElementRect.top)
}
}
and use it in your update
func:
function update() {
// ensure initialization and prevent recursive call
if (!logos) init(true);
//*************************************************
/**************************************************
THIS LINE MUST BE HERE.
**************************************************/
let maxScrollDist = getScrollingElement().scrollHeight - viewportHeight;
//*************************************************
let currentScrollPos = getScrollingElement().scrollTop;
// ...
}
function getScrollingElement() {
// ...
}
Full code:
// logo positioning
let logos, logoHeight, barTopMargin;
let viewportHeight;
window.addEventListener('load', init);
window.addEventListener('resize', setSizes);
document.addEventListener('scroll', update);
function init(lockUpdate) {
logos = document.querySelectorAll('.scroll-text');
setSizes(lockUpdate);
}
function update() {
// ensure initialization and prevent recursive call
if (!logos) init(true);
//*************************************************
/**************************************************
THIS LINE MUST BE HERE.
**************************************************/
let maxScrollDist = getScrollingElement().scrollHeight - viewportHeight;
//*************************************************
let currentScrollPos = getScrollingElement().scrollTop;
let newTop;
let middle = currentScrollPos + viewportHeight/2;
let middleY = maxScrollDist/2;
if (middle >= (maxScrollDist+viewportHeight)/2) {
let p = (middleY - Math.floor(middle - (maxScrollDist+viewportHeight)/2))*100/middleY;
newTop = viewportHeight/2 - logoHeight/2;
newTop += (100-p)*(viewportHeight/2)/100;
newTop -= (100-p)*(barTopMargin +logoHeight/2)/100;
newTop = Math.max(newTop, viewportHeight/2 - logoHeight/2); /*fix*/
} else {
let p = (middleY - Math.floor(-middle + (maxScrollDist+viewportHeight)/2))*100/middleY;
newTop = barTopMargin*(100-p)/100+(viewportHeight/2 - (logoHeight/2)*p/100 )*p/100;
newTop = Math.min(newTop, viewportHeight/2 - logoHeight/2); /*fix*/
}
logos.forEach(function(el) {
el.style.top = newTop + "px";
});
}
function getScrollingElement() {
if (document.scrollingElement) {
return document.scrollingElement;
}
const docElement = document.documentElement;
const docElementRect = docElement.getBoundingClientRect();
return {
scrollHeight: Math.ceil(docElementRect.height),
scrollTop: Math.abs(docElementRect.top)
}
}
function setSizes(lockUpdate) {
logoHeight = logos[0].offsetHeight;
barTopMargin = parseInt(getComputedStyle(document.querySelector('#page'), '::before').top);
viewportHeight = window.innerHeight;
if (lockUpdate === true) return;
update();
}
Hope this helps.
本文标签: javascriptWhy does ScrollTop position not work on mobile SafariStack Overflow
版权声明:本文标题:javascript - Why does ScrollTop position not work on mobile Safari? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745208946a2647773.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论