├── .gitignore ├── Gruntfile.js ├── LICENSE ├── README.md ├── css └── app.css ├── dist ├── app.css └── app.min.js ├── images └── onepixel.png ├── index.html ├── js └── app.js ├── package.json └── views └── pc.html /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | node_modules -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function(grunt) { 2 | var pkg = grunt.file.readJSON("package.json"); 3 | 4 | grunt.initConfig({ 5 | pkg:pkg, 6 | //配置js压缩混淆插件 7 | uglify:{ 8 | options:{ 9 | banner:'/*! <%=pkg.name%> <%=pkg.version%> | <%=grunt.template.today("yyyy-mm-dd HH:MM:ss")%> */\n' 10 | }, 11 | build:{ 12 | src:'js/app.js', 13 | dest:'dist/app.min.js' 14 | } 15 | }, 16 | //配置css压缩插件 17 | cssmin:{ 18 | options: { 19 | shorthandCompacting: false, 20 | roundingPrecision: -1 21 | }, 22 | build: { 23 | src:'css/app.css', 24 | dest:'dist/app.css' 25 | } 26 | }, 27 | watch:{ 28 | scripts: { 29 | files: ['js/*.*','css/*.*'], 30 | tasks: ['cssmin','uglify'], 31 | options: { 32 | spawn: false 33 | } 34 | } 35 | } 36 | }); 37 | 38 | grunt.loadNpmTasks('grunt-contrib-uglify'); 39 | grunt.loadNpmTasks('grunt-contrib-cssmin'); 40 | grunt.loadNpmTasks('grunt-contrib-watch'); 41 | 42 | grunt.registerTask('default',['cssmin','uglify','watch']); 43 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 git-onepixel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # H5单页面手势滑屏切换示例 2 | 3 | - 手指在屏幕上滑动时,页面跟随移动 4 | - 当手指离开屏幕时,计算手指在屏幕上停留的时间 5 | 6 | - 如果停留时间小于300ms,则认为是快速滑动切换,页面切换到下一页 7 | 8 | - 如果停留时间大于300ms,则认为是慢速滑动,慢速滑动按如下规则处理: 9 | - 如果滑动距离小于屏幕宽度的50%,则回退到上一页 10 | - 如果滑动距离大于屏幕宽度的50%,则切换到下一页 11 | 12 | ## 对于多手指触摸操作: 13 | - 第一个手指触摸时,正常滑动 14 | - 第二个手指按下时,不做任何响应操作,继续原有的滑动 15 | - 当任意一个手指离开屏幕时,结束滑动,剩余的手指操作不做任何处理 16 | - 当第二个手指再次按下时,触发新的滑动开始,但由于获取的是touches[0],因此,第一个手指移动才会引起页面的滑动 17 | - 支持多手指同时按下时进行滑动 18 | 19 | -------------------------------------------------------------------------------- /css/app.css: -------------------------------------------------------------------------------- 1 | html,body{ 2 | width: 100%; 3 | height: 100%; 4 | margin: 0; 5 | padding: 0; 6 | position: relative; 7 | overflow: hidden; 8 | font-family: Arial; 9 | background: #000; 10 | } 11 | .container{ 12 | position:absolute; 13 | height: 200px; 14 | top: 50%; 15 | margin-top:-100px; 16 | } 17 | .viewport{ 18 | width: 500%; 19 | height: 100%; 20 | display: -webkit-box; 21 | overflow: hidden; 22 | /*pointer-events: none; 去掉这句话*/ 23 | -webkit-transform: translate3d(0,0,0); 24 | backface-visibility: hidden; 25 | position: relative; 26 | } 27 | .pageview{ 28 | -webkit-box-flex: 1; 29 | width: 0; 30 | margin: 0 5px; 31 | } 32 | .pagenumber{ 33 | display: -webkit-box; 34 | position: absolute; 35 | bottom: 5%; 36 | left: 35%; 37 | height: 1em; 38 | width: 30%; 39 | } 40 | .pagenumber div{ 41 | -webkit-box-flex: 1; 42 | width: 0; 43 | position: relative; 44 | } 45 | .pagenumber .now:after { 46 | background: rgba(255,255,255,1) !important; 47 | } 48 | .pagenumber div:after{ 49 | content: ""; 50 | width: 6px; 51 | height: 6px; 52 | background: rgba(255,255,255,0.3); 53 | border-radius: 50%; 54 | position: absolute; 55 | top: 50%; 56 | left: 50%; 57 | margin-top: -3px; 58 | margin-left: -3px; 59 | } 60 | h3{ 61 | text-align: center; 62 | font-family: Microsoft YaHei,Arial; 63 | color: #fff; 64 | font-size: 1.5em; 65 | font-weight: normal; 66 | padding: 1em 0; 67 | margin: 0; 68 | } 69 | button{ 70 | width: 40%; 71 | margin: auto; 72 | height: 3em; 73 | background: #fff6de; 74 | line-height: 3rem; 75 | color: #000; 76 | padding: 0; 77 | border: none; 78 | display: block; 79 | } 80 | @media screen and (max-width: 360px) { 81 | html,body{font-size: 15px} 82 | } 83 | @media screen and (min-width: 360px) and (max-width: 400px) { 84 | html,body{font-size: 16px} 85 | } 86 | @media screen and (min-width: 400px) and (max-width: 460px) { 87 | html,body{font-size: 18px} 88 | } 89 | @media screen and (min-width: 460px){ 90 | html,body{font-size: 24px} 91 | } 92 | 93 | -------------------------------------------------------------------------------- /dist/app.css: -------------------------------------------------------------------------------- 1 | .viewport,body,html{height:100%;overflow:hidden;position:relative}body,html{width:100%;margin:0;padding:0;font-family:Arial}.viewport{width:500%;display:-webkit-box;-webkit-transform:translate3d(0,0,0);backface-visibility:hidden}.pageview{-webkit-box-flex:1;width:0}.pagenumber{display:-webkit-box;position:absolute;bottom:2em;left:35%;height:2em;width:30%}.pagenumber div{-webkit-box-flex:1;width:0;position:relative}.pagenumber .now:after{background:rgba(255,255,255,1)!important}.pagenumber div:after{content:"";width:.4em;height:.4em;background:rgba(255,255,255,.5);border-radius:2em;position:absolute;top:50%;left:50%;margin-top:-.2em;margin-left:-.2em}h3{text-align:center;font-family:Microsoft YaHei,Arial;color:#fff;font-size:1.7em;font-weight:400;padding:1em 0;margin:0}button{width:40%;margin:auto;height:3em;background:#fff6de;line-height:3rem;color:#000;padding:0;border:none;display:block}@media screen and (max-width:360px){body,html{font-size:15px}}@media screen and (min-width:360px) and (max-width:400px){body,html{font-size:16px}}@media screen and (min-width:400px) and (max-width:460px){body,html{font-size:18px}}@media screen and (min-width:460px){body,html{font-size:24px}} -------------------------------------------------------------------------------- /dist/app.min.js: -------------------------------------------------------------------------------- 1 | /*! H5SPA 1.0.0 | 2016-08-20 22:47:44 */ 2 | !function(a,b){var c=0,d=-1,e=1,f=null,g={init:function(){/(windows)/i.test(navigator.userAgent)&&(location.href="views/pc.html"),b.addEventListener("DOMContentLoaded",function(){f=b.querySelectorAll(".pagenumber div"),g.bindTouchEvent(),g.bindBtnClick(),g.setPageNow()}.bind(g),!1)}(),bindBtnClick:function(){var a=b.querySelector("#testbtn");a.addEventListener("touchstart",function(){console.log("touch")})},transform:function(a){this.style.webkitTransform="translate3d("+a+"px,0,0)",c=a},setPageNow:function(){-1!=d&&(f[d].className=""),d=e-1,f[d].className="now"},bindTouchEvent:function(){var d,g,h=b.querySelector("#viewport"),i=a.innerWidth,j=-i*(f.length-1),k=0,l=0,m="left",n=!1,o=0;b.addEventListener("touchstart",function(a){a.preventDefault();var b=a.touches[0];d=b.pageX,g=b.pageY,k=c,h.style.webkitTransition="",o=(new Date).getTime(),n=!1}.bind(this),!1),b.addEventListener("touchmove",function(a){a.preventDefault();var b=a.touches[0],c=b.pageX-d,e=b.pageY-g;if(Math.abs(c)>Math.abs(e)){l=c;var f=k+c;0>=f&&f>=j&&(this.transform.call(h,f),n=!0),m=c>0?"right":"left"}}.bind(this),!1),b.addEventListener("touchend",function(a){a.preventDefault();var b=0,d=(new Date).getTime()-o;n&&(h.style.webkitTransition="0.3s ease -webkit-transform",300>d?(b="left"==m?c-(i+l):c+i-l,b=b>0?0:b,b=j>b?j:b):Math.abs(l)/i<.5?b=c-l:(b="left"==m?c-(i+l):c+i-l,b=b>0?0:b,b=j>b?j:b),this.transform.call(h,b),e=Math.round(Math.abs(b)/i)+1,setTimeout(function(){this.setPageNow()}.bind(this),100))}.bind(this),!1)}}}(window,document); -------------------------------------------------------------------------------- /images/onepixel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/git-onepixel/guesture/517e014fdd7a5fe6329bc97941f5147900cf0f3f/images/onepixel.png -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 |