{"id":35359,"date":"2021-02-17T19:43:49","date_gmt":"2021-02-17T19:43:49","guid":{"rendered":"https:\/\/www.myedme.com\/login\/?p=35359"},"modified":"2021-02-17T21:26:28","modified_gmt":"2021-02-17T21:26:28","slug":"swiping-template","status":"publish","type":"post","link":"https:\/\/myedme.com\/login\/swiping-template\/","title":{"rendered":"Swiping Template"},"content":{"rendered":"\n<!doctype html>\n<html>\n\n<head>\n    <meta charset=\"utf-8\">\n    <title>Build a Full Featured Tinder Like Carousel in Vanilla JavaScript<\/title>\n    <style>\n        html,\n        body {\n            width: 100%;\n            height: 100%;\n            margin: 0;\n            padding: 0;\n        }\n        \n        #board {\n            width: 100%;\n            height: 100%;\n            position: relative;\n            overflow: hidden;\n            background-color: rgb(245, 247, 250);\n            min-height: 300px;\n            min-width: 300px;\n        }\n        \n        .card {\n            width: 320px;\n            height: 320px;\n            position: absolute;\n            top: 50%;\n            left: 50%;\n            border-radius: 1%;\n            box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.1);\n            background-color: white;\n            transform: translateX(-50%) translateY(-50%) scale(0.95);\n        }\n    <\/style>\n<\/head>\n\n<body>\n    <div id=\"board\">\n    <\/div>\n<\/body>\n<script src=\"https:\/\/cdnjs.cloudflare.com\/ajax\/libs\/hammer.js\/2.0.8\/hammer.min.js\"><\/script>\n<script>\n    \/* LikeCarousel (c) 2019 Simone P.M. github.com\/simonepm - Licensed MIT *\/\n    function startSwipe() {\n\n        class Carousel {\n\n            constructor(element) {\n\n                this.board = element\n\n                \/\/ add first two cards programmatically\n                this.push()\n                this.push()\n\n                \/\/ handle gestures\n                this.handle()\n\n            }\n            handle() {\n\n                \/\/ list all cards\n                this.cards = this.board.querySelectorAll('.card')\n\n                \/\/ get top card\n                this.topCard = this.cards[this.cards.length - 1]\n\n                \/\/ get next card\n                this.nextCard = this.cards[this.cards.length - 2]\n\n                \/\/ if at least one card is present\n                if (this.cards.length > 0) {\n\n                    \/\/ set default top card position and scale\n                    this.topCard.style.transform =\n                        'translateX(-50%) translateY(-50%) rotate(0deg) rotateY(0deg) scale(1)'\n\n                    \/\/ destroy previous Hammer instance, if present\n                    if (this.hammer) this.hammer.destroy()\n\n                    \/\/ listen for tap and pan gestures on top card\n                    this.hammer = new Hammer(this.topCard)\n                    this.hammer.add(new Hammer.Tap())\n                    this.hammer.add(new Hammer.Pan({\n                        position: Hammer.position_ALL,\n                        threshold: 0\n                    }))\n\n                    \/\/ pass events data to custom callbacks\n                    this.hammer.on('tap', (e) => {\n                        this.onTap(e)\n                    })\n                    this.hammer.on('pan', (e) => {\n                        this.onPan(e)\n                    })\n\n                }\n\n            }\n\n            onTap(e) {\n\n                \/\/ get finger position on top card\n                let propX = (e.center.x - e.target.getBoundingClientRect().left) \/ e.target.clientWidth\n\n                \/\/ get rotation degrees around Y axis (+\/- 15) based on finger position\n                let rotateY = 15 * (propX < 0.05 ? -1 : 1)\n\n                \/\/ enable transform transition\n                this.topCard.style.transition = 'transform 100ms ease-out'\n\n                \/\/ apply rotation around Y axis\n                this.topCard.style.transform =\n                    'translateX(-50%) translateY(-50%) rotate(0deg) rotateY(' + rotateY + 'deg) scale(1)'\n\n                \/\/ wait for transition end\n                setTimeout(() => {\n                    \/\/ reset transform properties\n                    this.topCard.style.transform =\n                        'translateX(-50%) translateY(-50%) rotate(0deg) rotateY(0deg) scale(1)'\n                }, 100)\n\n            }\n\n            onPan(e) {\n\n                if (!this.isPanning) {\n\n                    this.isPanning = true\n\n                    \/\/ remove transition properties\n                    this.topCard.style.transition = null\n                    if (this.nextCard) this.nextCard.style.transition = null\n\n                    \/\/ get top card coordinates in pixels\n                    let style = window.getComputedStyle(this.topCard)\n                    let mx = style.transform.match(\/^matrix\\((.+)\\)$\/)\n                    this.startPosX = mx ? parseFloat(mx[1].split(', ')[4]) : 0\n                    this.startPosY = mx ? parseFloat(mx[1].split(', ')[5]) : 0\n\n                    \/\/ get top card bounds\n                    let bounds = this.topCard.getBoundingClientRect()\n\n                    \/\/ get finger position on top card, top (1) or bottom (-1)\n                    this.isDraggingFrom =\n                        (e.center.y - bounds.top) > this.topCard.clientHeight \/ 2 ? -1 : 1\n\n                }\n\n                \/\/ get new coordinates\n                let posX = e.deltaX + this.startPosX\n                let posY = e.deltaY + this.startPosY\n\n                \/\/ get ratio between swiped pixels and the axes\n                let propX = e.deltaX \/ this.board.clientWidth\n                let propY = e.deltaY \/ this.board.clientHeight\n\n                \/\/ get swipe direction, left (-1) or right (1)\n                let dirX = e.deltaX < 0 ? -1 : 1\n\n                \/\/ get degrees of rotation, between 0 and +\/- 45\n                let deg = this.isDraggingFrom * dirX * Math.abs(propX) * 45\n\n                \/\/ get scale ratio, between .95 and 1\n                let scale = (95 + (5 * Math.abs(propX))) \/ 100\n\n                \/\/ move and rotate top card\n                this.topCard.style.transform =\n                    'translateX(' + posX + 'px) translateY(' + posY + 'px) rotate(' + deg + 'deg) rotateY(0deg) scale(1)'\n\n                \/\/ scale up next card\n                if (this.nextCard) this.nextCard.style.transform =\n                    'translateX(-50%) translateY(-50%) rotate(0deg) rotateY(0deg) scale(' + scale + ')'\n\n                if (e.isFinal) {\n\n                    this.isPanning = false\n\n                    let successful = false\n\n                    \/\/ set back transition properties\n                    this.topCard.style.transition = 'transform 200ms ease-out'\n                    if (this.nextCard) this.nextCard.style.transition = 'transform 100ms linear'\n\n                    \/\/ check threshold and movement direction\n                    if (propX > 0.25 && e.direction == Hammer.DIRECTION_RIGHT) {\n\n                        successful = true\n                            \/\/ get right border position\n                        posX = this.board.clientWidth\n                            \/\/Old:                    } else if (propY < -0.25&#038;&#038; e.direction == Hammer.DIRECTION_LEFT) {\n                    } else if (propX < -0.25) {\n                        if (e.direction == Hammer.DIRECTION_LEFT) {\n                            successful = true\n                                \/\/ get left border position\n                            posX = -(this.board.clientWidth + this.topCard.clientWidth)\n                        }\n                    } else if (propY < -0.25) {\n                        if (e.direction == Hammer.DIRECTION_UP) {\n\n                            successful = true\n                                \/\/ get top border position\n                            posY = -(this.board.clientHeight + this.topCard.clientHeight)\n                        }\n                    }\n\n                    if (successful) {\n\n                        \/\/ throw card in the chosen direction\n                        this.topCard.style.transform =\n                            'translateX(' + posX + 'px) translateY(' + posY + 'px) rotate(' + deg + 'deg)'\n\n                        \/\/ wait transition end\n                        setTimeout(() => {\n                            \/\/ remove swiped card\n                            this.board.removeChild(this.topCard)\n                                \/\/ add new card\n                            this.push()\n                                \/\/ handle gestures on new top card\n                            this.handle()\n                        }, 200)\n\n                    } else {\n\n                        \/\/ reset cards position and size\n                        this.topCard.style.transform =\n                            'translateX(-50%) translateY(-50%) rotate(0deg) rotateY(0deg) scale(1)'\n                        if (this.nextCard) this.nextCard.style.transform =\n                            'translateX(-50%) translateY(-50%) rotate(0deg) rotateY(0deg) scale(0.95)'\n\n                    }\n\n                }\n\n            }\n\n            push() {\n\n                let card = document.createElement('div')\n\n                card.classList.add('card')\n\n                card.style.backgroundImage =\n                    \"url('https:\/\/picsum.photos\/320\/320\/?random=\" + Math.round(Math.random() * 1000000) + \"')\"\n\n                this.board.insertBefore(card, this.board.firstChild)\n                console.log(\"trace 5. This: \" + this);\n            }\n        }\n        let board = document.querySelector('#board')\n        let carouselR = new Carousel(board)\n        console.log(\"trace 6\");\n        carouselR.board = board;\n\n        \/\/ add first two cards programmatically\n        carouselR.push()\n        carouselR.push()\n        \n        \/\/ handle gestures\n        carouselR.handle()\n        console.log(\"trace 7. carouselR: \" + carouselR);\n\n    }\n\n    window.addEventListener('load', startSwipe, false);\n    console.log(\"trace 1\");\n<\/script>\n\n<\/html>\n","protected":false},"excerpt":{"rendered":"<p>Build a Full Featured Tinder Like Carousel in Vanilla JavaScript<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"nf_dc_page":"","_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1],"tags":[],"class_list":["post-35359","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/posts\/35359","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/comments?post=35359"}],"version-history":[{"count":5,"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/posts\/35359\/revisions"}],"predecessor-version":[{"id":35380,"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/posts\/35359\/revisions\/35380"}],"wp:attachment":[{"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/media?parent=35359"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/categories?post=35359"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/myedme.com\/login\/wp-json\/wp\/v2\/tags?post=35359"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}