Fistright Fistright - 5 months ago 11
CSS Question

Javascript animation issue

I have seen this animation on android and I have done a mental project to how to do it in javascript.What I don't understand is how to select the previous "card" and the next "card" to apply them animation when the card that is moving "touches" the edges of his father.Have you got any ideas?

https://drive.google.com/file/d/0B6zPGxCIHPIjbVRHU19xSFVNUDg/view?usp=drivesdk

Answer

Ok Fistright, this is my solution. Yeah I though we might solve this together but you wrote that your problem is urgent so I did it myself.

HERE you can see the working example.

The page was tested with Google Chrome 51, Mozilla Firefox 47 and Internet Explorer 11.

The whole code:

<!DOCTYPE html>
<html>
    <head>
        <title>Android Swipe for Fistright</title>
        <meta charset="UTF-8">
        <script type="text/javascript" src="./swipe.js"></script>
        <link rel="stylesheet" type="text/css" href="swipe.css">
    </head>
    <body>
        <div id="swipe-container">
            <div class="page-container" style="background-color:#7A48C1;">page one</div>
            <div class="page-container" style="background-color:#BA99E7;">page two</div>
            <div class="page-container" style="background-color:#966BD4;">page thre</div>
            <div class="page-container" style="background-color:#622BB0;">page four</div>
            <div class="page-container" style="background-color:#481295;">page five</div>
            <div class="page-container" style="background-color:#481295;">page seven</div>
            <div class="page-container" style="background-color:#481295;">page eight</div>
            <div class="page-container" style="background-color:#481295;">page nine</div>
            <div class="page-container" style="background-color:#481295;">page ten</div>
            <div class="page-container" style="background-color:#481295;">page eleven</div>
            <div class="page-container" style="background-color:#481295;">page twelve</div>
        </div>
        <script type="text/javascript">
            var s = new swipe(document.getElementById('swipe-container'));
        </script>
    </body>
</html>

This is just an example, the only thing you need to keep is:

<!DOCTYPE html>
<html>
    <head>
        <title>Android Swipe for Fistright</title>
        <meta charset="UTF-8">
        <script type="text/javascript" src="./swipe.js"></script>
        <link rel="stylesheet" type="text/css" href="swipe.css">
    </head>
    <body>
        <div id="blabla">
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
            <div class="page-container"></div>
        </div>
        <script type="text/javascript">
            var s = new swipe(document.getElementById('blabla'));
        </script>
    </body>
</html>

The css is rather simple

body,html{
    margin: 0px;
    padding: 0px;
    border: 0px;
}
#swipe-container, .page-container{
    margin: 0px;
    padding: 0px;
    border: 0px;
}

#swipe-container, .page-container{
    width: 450px;
    height: 640px;
}
.page-container{
    position: absolute;
    left:0px;
    opacity: 0;
    display:none;
    -webkit-user-select: none;
    -moz-user-select: none;
    -ms-user-select: none;
    user-select: none; 
}
#swipe-container{
    position:relative;
    cursor: pointer;
    margin:0px auto;
    margin-top: 60px;
    overflow: hidden;
    border:1px grey solid;
}

And the shortened version:

#swipe-container, .page-container{
    width: 450px;
    height: 640px;
}
#swipe-container{
    position:relative;
    overflow: hidden;
}

And now the JavaScript:

// swipe.js
// contains a class that gives the interactivity for the swiping
//
// written by Florian Völker (feirell.de) 11.06.2016


function swipe(container){
    if(typeof container == 'undefined'){
        this.conta = document.getElementById('swipe-container')
    }else{
        this.conta = container
    }

    this.pages = this.conta.getElementsByClassName('page-container')

    /*prepare all pages*/
    for (var i = this.pages.length - 1; i >= 0; i--) {
        this.resetElement(this.pages[i])
        this.pages[i].style.zIndex = this.pages.length - 1 - i
    }

    this.width = parseInt(window.getComputedStyle(this.conta,null).getPropertyValue("width").replace('px',''));

    this.conta.addEventListener('mouseenter',this.M_enter.bind(this))
    this.conta.addEventListener('mouseleave',this.M_out.bind(this))
    this.conta.addEventListener('mousemove', this.M_move.bind(this))

    this.conta.addEventListener('mousedown', this.M_down.bind(this))
    this.conta.addEventListener('mouseup', this.M_up.bind(this))

    this.start_position = false
    this.start_swipe = false
    this.mousedown = false
    this.inside = false
    this.virtualPosition = this.width/2
    this.lastRenderPosition = 0

    this.magnet_in_progress = false;
    this.magnet_destination = 0
    this.magnet_last_call = 0
    this.magnet_start = 0
    this.magnet_time = 100

    requestAnimationFrame(this.animationLoop.bind(this))
}

swipe.prototype.M_enter = function(){
    this.inside = true
};
swipe.prototype.M_out = function(ev){
    this.inside = false
    this.M_up()
};
swipe.prototype.M_up = function(ev){
    this.mousedown = false
    this.start_swipe = false
    this.start_position = false
    this.magnet()
};
swipe.prototype.M_down = function(ev){
    this.clear_magnet()
    this.start_position = ev.clientX;
    this.start_swipe = this.virtualPosition
    this.mousedown = true
};

swipe.prototype.M_move = function(ev){
    if(this.mousedown == true){
        shift = ev.clientX - this.start_position
        new_position = this.start_swipe - shift
        if (new_position <= this.width*0.5){
            this.virtualPosition = this.width*0.5
            return;
        }
        if(new_position >= (this.pages.length-0.5)*this.width ){
            this.virtualPosition = (this.pages.length-0.5)*this.width
            return;
        }
        this.virtualPosition = new_position;
    }
};

swipe.prototype.magnet = function(){
    this.clear_magnet()
    this.magnet_in_progress = true
    this.magnet_start = this.virtualPosition;
    this.magnet_destination = Math.round(((this.virtualPosition/(this.width*0.5))+1)/2)*this.width - this.width*0.5
    this.magnet_last_call = Date.now()
    //console.log('start: ',this.magnet_start,'\ndestination: ',this.magnet_destination)
};

swipe.prototype.clear_magnet = function(){
    this.magnet_in_progress = false;
    this.magnet_start = 0
    this.magnet_destination = 0
    this.magnet_last_call = 0
};
swipe.prototype.magnet_position = function(){
    var now = Date.now(),
        diff =  now - this.magnet_last_call,
        pixel = this.magnet_destination - this.magnet_start;

    this.magnet_last_call = now

    var set_to = this.virtualPosition + ((diff/this.magnet_time) * pixel)

    if(pixel > 0 && set_to > this.magnet_destination){
        var dest = this.magnet_destination
        this.clear_magnet()
        return dest
    }
    if(pixel < 0 && set_to < this.magnet_destination){
        var dest = this.magnet_destination
        this.clear_magnet()
        return dest
    }
    return set_to   
}
swipe.prototype.displayAs = function(position){
    if (position >= this.width*0.5 && position <= (this.pages.length-0.5)*this.width ) {
        var el_index = ((position/(this.width*0.5))+1)/2 -1 //the one just to adjust for the array 0 start
        if(el_index % 1 == 0){
            if(el_index-1 >= 0){
                this.pages[el_index-1].style.opacity = "0"
                this.pages[el_index-1].style.display = "none"
            }

            this.pages[el_index].style.opacity = "1"
            this.pages[el_index].style.left = "0px"
            this.pages[el_index].style.transform = "scale(1)"
            this.pages[el_index].style.display = "block"

            if(el_index+1 <= this.pages.length-1){
                this.pages[el_index+1].style.opacity = "0"
                this.pages[el_index+1].style.display = "none"
            }
        }else{
            var distance = (position+(this.width/2)) % this.width,
                a = Math.floor(el_index),
                b = Math.ceil(el_index),
                pro = distance/this.width

            this.pages[a].style.left = "-"+distance+"px"
            this.pages[a].style.display = 'block';
            this.pages[a].style.opacity = '1';

            this.pages[b].style.display = 'block';
            this.pages[b].style.opacity = pro
            this.pages[b].style.transform = "scale("+ (1 - ((1-pro) * 0.2)) +")"

            /*resetting the a-1 and b+1 elements so they are default*/
            if(a-1 >= 0 && this.pages[a-1].swipe_default == false){
                this.resetElement(this.pages[a-1])
            }
            if(b+1 <= this.pages.length-1 && this.pages[b+1].swipe_default == false){
                this.resetElement(this.pages[b+1])
            }
        }
    }
};
swipe.prototype.resetElement = function(el){
    el.swipe_default    = true
    el.style.display    = "absolute";
    el.style.display    = "none";
    el.style.left       = "0px";
    el.style.opacity    = "0";
    el.style.transform  = "scale(0)";
}
swipe.prototype.animationLoop = function(){
    if(this.magnet_in_progress == true){
        this.virtualPosition = this.magnet_position()
    }
    if(this.lastRenderPosition != this.virtualPosition){
        this.displayAs(this.virtualPosition)
        this.lastRenderPosition = this.virtualPosition
    }
    requestAnimationFrame(this.animationLoop.bind(this))
};

I though about to comment the whole javascript but this would just stretch the script and I think that it is long enough, if you have any questions, or think that comments would be a good idea feel free to ask and I will try my best to help you.

Comments