循环中的函数多次调用。我怎么能以不同的方式解决这个问题呢?

时间:2016-07-25 14:40:42

标签: javascript loops gsap

以下代码中的my moveMask函数对于具有类.layout-box的每个HTML元素称为x次。

我很难想到一种重写代码的方法,以便每次调用事件监听器时它只运行一次函数。

我知道这可能不是一个简单的解决办法,但如果我能够了解我需要进入的方向,那么我真的很感激。

// Store SVG container element as variable
var layoutBox = document.querySelectorAll(".layout-box"),
    xPos = 0,
    yPos = 0,
    elOver = true,
    clicked = false,
    rect,
    coords,
    split = document.querySelectorAll('.words h2, .words h3, .words p, .words li');

// GSAP tweens/functions that require access to coordinates
function moveMask(valueX, valueY) {
    [].slice.call(layoutBox).forEach(function(el, i) {
        console.log("test");
        var img = el.querySelectorAll('.img');

        // Mask move animation 
        var tlMove = new TimelineMax({
            paused: true
        });
        tlMove.set(img, {
            webkitClipPath: '40px at ' + valueX + 'px ' + valueY + 'px'
        });
        el.animationMaskMove = tlMove;

        // Mask click animation
        var tlClick = tlLeave = new TimelineMax({
            paused: true
        });
        tlClick.to(img, 0.8, {
            webkitClipPath: '500px at ' + valueX + 'px ' + valueY + 'px',
        });
        tlClick.to(img, 0.4, {
            '-webkit-filter': 'grayscale(0%)',
             filter: 'grayscale(0%)'
        }, '-=0.8');
        el.animationMaskClick = tlClick;
        tlClick.progress(1).progress(0); // Forces an initial render of this tween so that it's cached for its 2nd usage

        // Mask leave animation
        var tlLeave = new TimelineMax({
            paused: true
        });
        tlLeave.to(img, 0.2, {
            webkitClipPath: '0 at ' + valueX + 'px ' + valueY + 'px',
            '-webkit-filter': 'grayscale(100%)',
             filter: 'grayscale(100%)'
        });
        el.animationMaskLeave = tlLeave;
        tlLeave.progress(1).progress(0);

        // Mask slow leave animation
        var tlLeaveSlow = new TimelineMax({
            paused: true
        });
        tlLeaveSlow.to(img, 0.6, {
            ease: Bounce.easeOut,
            webkitClipPath: '0 at ' + valueX + 'px ' + valueY + 'px',
            '-webkit-filter': 'grayscale(100%)',
             filter: 'grayscale(100%)'
        });
        el.animationMaskSlowLeave = tlLeaveSlow;
        tlLeaveSlow.progress(1).progress(0);

    });
}

// Force initial run with temporary coordinates (so tweens can be cached)
moveMask(-100, -100);

// GSAP tweens/functions that don't access to coordinates
[].slice.call(layoutBox).forEach(function(el, i) {
    console.log("test2");
    var svgContainer = el.querySelectorAll('.svg-container');
    var svgContainerLeft = el.querySelectorAll('.left');
    var svgContainerBottom = el.querySelectorAll('.bottom');
    var img = el.querySelectorAll('.img');
    var mask = el.querySelectorAll('.mask');
    var text = el.querySelectorAll('.text');
    var elSplit = el.querySelectorAll('.words');

    // Container 3d push effect 
    var tlContainer3d = new TimelineMax({
        paused: true
    });
    tlContainer3d.to(svgContainer, 0.3, {
        x: "-=6px",
        y: "+=6px"
    });
    el.animationContainer3d = tlContainer3d;
    tlContainer3d.progress(1).progress(0);

    // Container 3d push effect left
    var tlContainer3dLeft = new TimelineMax({
        paused: true
    });
    tlContainer3dLeft.to(svgContainerLeft, 0.3, {
        width: "4px"
    });
    el.animationContainer3dLeft = tlContainer3dLeft;
    tlContainer3dLeft.progress(1).progress(0);

    // Container 3d push effect bottom
    var tlContainer3dBottom = new TimelineMax({
        paused: true
    });
    tlContainer3dBottom.to(svgContainerBottom, 0.3, {
        height: "4px",
        right: "+=6px"
    });
    el.animationContainer3dBottom = tlContainer3dBottom;
    tlContainer3dBottom.progress(1).progress(0);

    // Img move animation
    var tlImgMove = new TimelineMax({
        paused: true
    });
    tlImgMove.to(img, 0.3, {
        scale: 1,
        ease: Sine.easeOut,
        '-webkit-filter': 'grayscale(0%)',
         filter: 'grayscale(0%)'
    }, 0.05);
    el.animationImgMove = tlImgMove;
    tlImgMove.progress(1).progress(0);

    // Mask click text animation
    var tlText = new TimelineMax({
        paused: true
    })
    tlText.to(elSplit, .3, {
        autoAlpha: 0
    });
    el.animationTextClick = tlText;
    tlText.progress(1).progress(0);

});

// Loop through boxes and assign event listeners
for (var x = 0; x < layoutBox.length; x++) {

    layoutBox[x].addEventListener("mousemove", function(e) {

        if (elOver) { // Only run if mousedown hasn't been triggered

            // Get coordinates of container
            rect = this.getBoundingClientRect();
            xPos = e.pageX - rect.left;
            yPos = e.pageY - rect.top - window.scrollY;

            // Add coordinates to array and pass in to moveMask function
            coords = [xPos, yPos];
            moveMask.apply(null, coords);

            this.animationMaskMove.play();

        }

    });

    layoutBox[x].addEventListener("mousedown", function(e) {

        this.animationContainer3d.play();
        this.animationContainer3dLeft.play();
        this.animationContainer3dBottom.play();
        this.animationMaskClick.play();
        this.animationTextClick.play();
        clicked = true;
        elOver = false;

    });

    layoutBox[x].addEventListener("mouseleave", function(e) {

        this.animationContainer3d.reverse();
        this.animationContainer3dLeft.reverse();
        this.animationContainer3dBottom.reverse();
        this.animationTextClick.timeScale(1.25).reverse();

        // If clicked then run slow animation
        if (clicked) {
            this.animationMaskSlowLeave.play();
        } else {
            this.animationMaskLeave.play();
        }

        clicked = false;
        elOver = true;

    });

}

编辑:

// Store SVG container element as variable
var layoutBox = document.querySelectorAll(".layout-box"),
    elOver = true,
    clicked = false,
    xPos = 0,
    yPos = 0,
    rect,
    coords;

// GSAP tweens/functions that require access to coordinates
function moveMask(el, valueX, valueY) {
        console.log("test");
        var img = el.querySelectorAll('.img');

        // Mask move animation 
        var tlMove = new TimelineMax({
            paused: true
        });
        tlMove.set(img, {
            webkitClipPath: '40px at ' + valueX + 'px ' + valueY + 'px'
        });
        el.animationMaskMove = tlMove;

        // Mask click animation
        var tlClick = tlLeave = new TimelineMax({
            paused: true
        });
        tlClick.to(img, 0.8, {
            webkitClipPath: '500px at ' + valueX + 'px ' + valueY + 'px',
        });
        tlClick.to(img, 0.4, {
            '-webkit-filter': 'grayscale(0%)',
             filter: 'grayscale(0%)'
        }, '-=0.8');
        el.animationMaskClick = tlClick;
        tlClick.progress(1).progress(0); // Forces an initial render of this tween so that it's cached for its 2nd usage

        // Mask leave animation
        var tlLeave = new TimelineMax({
            paused: true
        });
        tlLeave.to(img, 0.2, {
            webkitClipPath: '0 at ' + valueX + 'px ' + valueY + 'px',
            '-webkit-filter': 'grayscale(100%)',
             filter: 'grayscale(100%)'
        });
        el.animationMaskLeave = tlLeave;
        tlLeave.progress(1).progress(0);

        // Mask slow leave animation
        var tlLeaveSlow = new TimelineMax({
            paused: true
        });
        tlLeaveSlow.to(img, 0.6, {
            ease: Bounce.easeOut,
            webkitClipPath: '0 at ' + valueX + 'px ' + valueY + 'px',
            '-webkit-filter': 'grayscale(100%)',
             filter: 'grayscale(100%)'
        });
        el.animationMaskSlowLeave = tlLeaveSlow;
        tlLeaveSlow.progress(1).progress(0);

}

// Force initial run with temporary coordinates (so tweens can be cached)
[].forEach.call(layoutBox, function(el, i) { moveMask(el, -100, -100) }); 

// GSAP tweens/functions that don't access to coordinates
[].forEach.call(layoutBox, function(el, i) {
    console.log("test2");
    var svgContainer = el.querySelectorAll('.svg-container');
    var svgContainerLeft = el.querySelectorAll('.left');
    var svgContainerBottom = el.querySelectorAll('.bottom');
    var img = el.querySelectorAll('.img');
    var mask = el.querySelectorAll('.mask');
    var text = el.querySelectorAll('.text');
    var elSplit = el.querySelectorAll('.words');

    // Container 3d push effect 
    var tlContainer3d = new TimelineMax({
        paused: true
    });
    tlContainer3d.to(svgContainer, 0.3, {
        x: "-=6px",
        y: "+=6px"
    });
    el.animationContainer3d = tlContainer3d;
    tlContainer3d.progress(1).progress(0);

    // Container 3d push effect left
    var tlContainer3dLeft = new TimelineMax({
        paused: true
    });
    tlContainer3dLeft.to(svgContainerLeft, 0.3, {
        width: "4px"
    });
    el.animationContainer3dLeft = tlContainer3dLeft;
    tlContainer3dLeft.progress(1).progress(0);

    // Container 3d push effect bottom
    var tlContainer3dBottom = new TimelineMax({
        paused: true
    });
    tlContainer3dBottom.to(svgContainerBottom, 0.3, {
        height: "4px",
        right: "+=6px"
    });
    el.animationContainer3dBottom = tlContainer3dBottom;
    tlContainer3dBottom.progress(1).progress(0);

    // Img move animation
    var tlImgMove = new TimelineMax({
        paused: true
    });
    tlImgMove.to(img, 0.3, {
        scale: 1,
        ease: Sine.easeOut,
        '-webkit-filter': 'grayscale(0%)',
         filter: 'grayscale(0%)'
    }, 0.05);
    el.animationImgMove = tlImgMove;
    tlImgMove.progress(1).progress(0);

    // Mask click text animation
    var tlText = new TimelineMax({
        paused: true
    })
    tlText.to(elSplit, .3, {
        autoAlpha: 0
    });
    el.animationTextClick = tlText;
    tlText.progress(1).progress(0);

});

// Event listener functions
function myMouseMove(e) {

        if (elOver) { // Only run if mousedown hasn't been triggered

            // Get coordinates of container
            rect = this.getBoundingClientRect();
            xPos = e.pageX - rect.left; 
            yPos = e.pageY - rect.top - window.scrollY;

            // Add coordinates to array and pass in to moveMask function
            coords = [xPos, yPos];
            moveMask.call(null, coords);

            this.animationMaskMove.play();

        }

}

function myMouseDown(e) {

        this.animationContainer3d.play();
        this.animationContainer3dLeft.play();
        this.animationContainer3dBottom.play();
        this.animationMaskClick.play();
        this.animationTextClick.play();
        clicked = true;
        elOver = false;
};

function myMouseLeave(e) {

        this.animationContainer3d.reverse();
        this.animationContainer3dLeft.reverse();
        this.animationContainer3dBottom.reverse();
        this.animationTextClick.timeScale(1.25).reverse();

        // If clicked then run slow animation
        if (clicked) {
            this.animationMaskSlowLeave.play();
        } else {
            this.animationMaskLeave.play();
        }

        clicked = false;
        elOver = true;

};

// Loop through boxes and assign event listener
for (var x = 0; x < layoutBox.length; x++) {
    layoutBox[x].addEventListener("mousemove", myMouseMove);
    //layoutBox[x].addEventListener("mousedown", this, myMouseDown);
    //layoutBox[x].addEventListener("mouseleave", this, myMouseLeave);
};

0 个答案:

没有答案