Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recalculate scrolling div position when used in a clipping path

I am using clipping paths to change my logo colour base on the background colour.

In addition to this the logo scrolls from top to bottom based on the users vertical position on the page. Top of page = logo at top, bottom of page = logo at bottom etc.

Unfortunately when I added the clipping paths the logos lost their scroll position and after the first one, do not work at all.

Is there a way around this? Also, the logo position was a little off to start with so if there is any way of addressing this at the same time.

You can see the original question here: div position based on scroll position

I have tried this, but I can't seem to get it to work.

Scroll position lost when hiding div

I am using Advanced Custom Fields and each sections PHP file has this in the header as part of the clipping path using either the white or dark version of the logo accordingly. Its parent is positioned relatively and its child absolutely.

div class="logo-scroll">
        <div class="scroll-text">
                    <a href="/home"><img width="53px" height="260px" src="/wp-content/uploads/2019/07/sheree-walker-web-design-edinburgh-vertical-01.svg"/></a>
       </div>
</div>  

The Javascript

const docHeight = Math.max(document.documentElement.scrollHeight, document.body.scrollHeight);
const logo = document.querySelector('.scroll-text');
const logoHeight = logo.offsetHeight;
// to get the pseudoelement's '#page::before' top we use getComputedStyle method
const barTopMargin = parseInt(getComputedStyle(document.querySelector('#page'), '::before').top);

let viewportHeight, barHeight, maxScrollDist, currentScrollPos, scrollFraction;

logo.style.top = barTopMargin + 'px';

window.addEventListener('load', update);
window.addEventListener('resize', setSizes);
document.addEventListener('scroll', update);

setSizes();


function update() {
    currentScrollPos = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
    scrollFraction = currentScrollPos / (docHeight - viewportHeight);

    logo.style.top = barTopMargin + (scrollFraction * maxScrollDist) + 'px';
}

function setSizes() {
    viewportHeight = window.innerHeight;
    // to get the pseudoelement's '#page::before' height we use getComputedStyle method
    barHeight = parseInt(getComputedStyle(document.querySelector('#page'), '::before').height); 
    maxScrollDist = barHeight - logoHeight;
    update();
}

The CSS

.logo-scroll .scroll-text img {
    padding: 0 6px 0 17px;
}


#page::before {
    content: "";
    position: fixed;
    top: 30px;
    bottom: 30px;
    left: 30px;
    right: 30px;
    border: 2px solid white;
    pointer-events: none;
    -webkit-transition: all 2s; /* Safari prior 6.1 */
    transition: all 2s;
}

.logo-scroll {
    position: fixed;
    left: 30px;
    top: 30px;
    bottom: 30px;
    border-right: 2px solid white;
    width: 75px;
    z-index: 10;
}

.scroll-text {
    position: fixed;
}
like image 522
Mr Toad Avatar asked Aug 04 '19 11:08

Mr Toad


1 Answers

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();
}

updated and tested.

to check it put this code in your console:

document.removeEventListener('scroll', update);
document.onscroll = function() {
    let _logoHeight     = logos[0].offsetHeight;
    let _barTopMargin   = parseInt(getComputedStyle(document.querySelector('#page'), '::before').top);
    let _viewportHeight = window.innerHeight;
    let _maxScrollDist  = document.documentElement.scrollHeight - _viewportHeight;

    let currentScrollPos = document.documentElement.scrollTop;
    let percent100 = currentScrollPos + _viewportHeight;

    let scrolledPercent = currentScrollPos * 100/_maxScrollDist;

    let newTop = ((_viewportHeight - _logoHeight/2)*scrolledPercent/100);

    let middle = currentScrollPos + _viewportHeight/2;
    let middleY = _maxScrollDist/2; // 100

    if (middle >= (_maxScrollDist+_viewportHeight)/2) {
        let y1 = middleY - Math.floor(middle - (_maxScrollDist+_viewportHeight)/2);
        let p = y1*100/middleY;

        newTop = _viewportHeight/2 - _logoHeight/2;
        newTop += (100-p)*(_viewportHeight/2)/100;
        newTop -= (100-p)*(30 +_logoHeight/2)/100;

        newTop = Math.max(newTop, _viewportHeight/2 - _logoHeight/2); /*fix*/

    } else {
        let y2 = middleY - Math.floor(-middle + (_maxScrollDist+_viewportHeight)/2);
        let p = y2*100/middleY;
        newTop = 30*(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";
    });
}

CSS fix: custom.css :: line 767

@media (max-width: 1000px)...
.scroll-text {
    padding-left: 13px;
    /*width: 27px;*/
}
.scroll-text img {
    /* remove it. but if necessary move it to .scroll-text rule above
    width: 27px; */
}

custom.css :: line 839

@media (max-width: 599px)...
.logo-scroll {
    /*display: none; why! remove it*/
}

custom.css :: line 268

.scroll-text {
    position: fixed;
    /* height: 280px; remove it*/
    padding-left: 20px;
}

see this capture


finally, have a nice day and goodby.

like image 65
tdjprog Avatar answered Nov 15 '22 13:11

tdjprog