交互简历案例(48)

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>珠峰培训</title>
    <!--IMPORT CSS-->
    <link rel="stylesheet" href="css/swiper-3.4.2.min.css">
    <link rel="stylesheet" href="css/index.min.css">

    <!--PRE-FIX-FREE:设置前缀的插件-->
    <script src="js/prefixfree.min.js"></script>

    <!--REM-->
    <script>
        //=>根据当前设备的宽度,动态计算出REM的换算比例,实现页面中元素的等比缩放
        ~function anonymous(window) {
            let computedREM = function computedREM() {
                let winW = document.documentElement.clientWidth,
                    desW = 640;
                if (winW >= 640) {
                    document.documentElement.style.fontSize = '100px';
                    return;
                }
                document.documentElement.style.fontSize = winW / desW * 100 + 'px';
            };
            computedREM();
            window.addEventListener('resize', computedREM);
        }(window);
    </script>
</head>
<body>
<!--外面套一层MAIN-BOX:控制当前页面的最大宽度,防止把做好的页面在PC端预览的时候满屏展示,这样字体和盒子大小等被肆意拉伸-->
<main class="mainBox">
    <!--LOADING-->
    <section class="loadingBox">
        <div class="title">
            <h1>珠峰培训</h1>
            <h2>H5场景交互型简历</h2>
        </div>
        <div class="progress">
            <div class="current"></div>
        </div>
    </section>

    <!--PHONE-->
    <section class="phoneBox">
        <h2>
            <img src="img/zf_phoneLogo.png" alt="">
            <span>00:00</span>
        </h2>
        <div class="answer">
            <div class="markMove"></div>
            <a href="javascript:;" class="markLink"></a>
        </div>
        <div class="hang">
            <a href="javascript:;" class="markLink"></a>
        </div>
        <!--AUDIO-->
        <audio src="audio/bell.mp3" loop preload="none" id="answerBell"></audio>
        <audio src="audio/say.mp3" preload="none" id="introduction"></audio>
    </section>

    <!--MESSAGE-->
    <section class="messageBox">
        <ul class="wrapper clearfix">
            <li class="self">
                <i class="arrow"></i>
                <img src="img/zf_messageStudent.png" alt="" class="pic">
                面试官您好,我叫周啸天,来自于河北承德,2019年毕业于XXX院校,学习的是XXX专业,到目前位置工作9年,先后担任高级软件工程师、总经理助理、技术经理和总监等职务
            </li>
            <li class="inter">
                <i class="arrow"></i>
                <img src="img/zf_messageLogo.png" alt="" class="pic">
                哇塞!好牛X啊!介绍一下自己的专业技能吧!
            </li>
            <!--后期会手动在这个位置增加一条新的记录-->
            <li class="self">
                <i class="arrow"></i>
                <img src="img/zf_messageStudent.png" alt="" class="pic">
                本人擅长:原生JS、ES6、Promise等设计模式、组件和插件封装,看过JQ源码,可以开发各种Hybrid混合APP...
            </li>
            <li class="inter">
                <i class="arrow"></i>
                <img src="img/zf_messageLogo.png" alt="" class="pic">
                框架会吗?我们公司现在使用的是VUE和REACT
            </li>
            <li class="self">
                <i class="arrow"></i>
                <img src="img/zf_messageStudent.png" alt="" class="pic">
                之前的公司使用的是REACT开发,个人对于REACT渲染原理、MVC模式、SPA单页面应用、DIFF差异渲染机制以及REDUX原理等都有研究,掌握的很熟练,对于VUE之前也做过,如果公司需要可以快速入手
            </li>
            <li class="inter">
                <i class="arrow"></i>
                <img src="img/zf_messageLogo.png" alt="" class="pic">
                webpack会吗?
            </li>
            <li class="self">
                <i class="arrow"></i>
                <img src="img/zf_messageStudent.png" alt="" class="pic">
                之前项目都是基于脚手架完成的,自己偶尔去修改一些webpack配置项
            </li>
            <li class="self">
                <i class="arrow"></i>
                <img src="img/zf_messageStudent.png" alt="" class="pic">
                不过目前正在深入研究,可以搭建简单的脚手架
            </li>
            <li class="self">
                <i class="arrow"></i>
                <img src="img/zf_messageStudent.png" alt="" class="pic">
                同时对于NODE/EXPRESS等后台开发也有所涉猎,只是没有应用到项目实战中,目前也正在研究,对这个比较感兴趣
            </li>
            <li class="inter">
                <i class="arrow"></i>
                <img src="img/zf_messageLogo.png" alt="" class="pic">
                你认为你的优点在于哪?和其他人对比,公司为啥要录用你!
            </li>
            <li class="self">
                <i class="arrow"></i>
                <img src="img/zf_messageStudent.png" alt="" class="pic">
                肯吃苦、肯加班、能力高、要钱少...这些够吗?
            </li>
            <li class="inter">
                <i class="arrow"></i>
                <img src="img/zf_messageLogo.png" alt="" class="pic">
                就是你啦,明天来上班!
            </li>
        </ul>

        <div class="keyBoard">
            <span></span><!--好的,马上介绍!-->
            <a href="javascript:;" class="submit"></a>
        </div>

        <audio src="audio/music.mp3" preload="none" loop id="demonMusic"></audio>
    </section>

    <!--CUBE-->
    <section class="cubeBox">
        <ul class="cube">
            <li><img src="img/zf_cube1.png" alt=""></li>
            <li><img src="img/zf_cube2.png" alt=""></li>
            <li><img src="img/zf_cube3.png" alt=""></li>
            <li><img src="img/zf_cube4.png" alt=""></li>
            <li><img src="img/zf_cube5.png" alt=""></li>
            <li><img src="img/zf_cube6.png" alt=""></li>
        </ul>
        <img src="img/zf_cubeTip.png" alt="" class="tip">
    </section>

    <!--DETAIL-->
    <section class="detailBox">
        <div class="swiper-container">
            <div class="swiper-wrapper">
                <!--PAGE1-->
                <div class="swiper-slide page1">
                    <dl>
                        <dt>课程大纲</dt>
                        <dd>
                            <em>01</em>
                            <a href="#">HTML(5)+CSS(3)+移动端响应式布局开发及相关插件的使用</a>
                        </dd>
                        <dd>
                            <em>02</em>
                            <a href="#">JS中的闭包及堆栈内存以及THIS的处理</a>
                        </dd>
                        <dd>
                            <em>03</em>
                            <a href="#">JS中的面向对象编程,可以基于面向对象封装组件和插件等</a>
                        </dd>
                        <dd>
                            <em>04</em>
                            <a href="#">ES6中的新特性及数组对象里面的常用方法</a>
                        </dd>
                        <dd>
                            <em>05</em>
                            <a href="#">JS中的同步异步编程及Promise设计模式</a>
                        </dd>
                        <dd>
                            <em>06</em>
                            <a href="#">JS中的事件委托及事件池及发布订阅设计模式</a>
                        </dd>
                        <dd>
                            <em>07</em>
                            <a href="#">JS中的DOM操作以及重绘和回流的优化</a>
                        </dd>
                        <dd>
                            <em>08</em>
                            <a href="#">HTTP交互及AJAX库的封装以及跨域数据共享</a>
                        </dd>
                        <dd>
                            <em>09</em>
                            <a href="#">VUE:VUE-CLI/VUE-ROUTER/VUEX/VUE ELEMENT等全家桶</a>
                        </dd>
                        <dd>
                            <em>10</em>
                            <a href="#">REACT:REACT-ROUTER/REACT-REDUX/DVA/AXIOS/ANT等</a>
                        </dd>
                        <dd>
                            <em>11</em>
                            <a href="#">辅助技能:NODE/WEBPACK/GIT等</a>
                        </dd>
                    </dl>
                </div>

                <!--PAGE2-->
                <div class="swiper-slide page2">
                    <h2>课程体系</h2>
                    <img src="img/zf_course1.png" alt="">
                    <img src="img/zf_course2.png" alt="">
                    <img src="img/zf_course3.png" alt="">
                    <img src="img/zf_course4.png" alt="">
                    <img src="img/zf_course5.png" alt="">
                    <img src="img/zf_course6.png" alt="">
                    <img src="img/zf_course.png" alt="">
                </div>

                <div class="swiper-slide"></div>
                <div class="swiper-slide"></div>
                <div class="swiper-slide"></div>
                <div class="swiper-slide"></div>
            </div>
        </div>
    </section>
</main>

<!--IMPORT JS-->
<script src="js/zepto.min.js"></script>
<script src="js/swiper-3.4.2.jquery.min.js"></script>
<script src="js/makisu.min.js"></script>
<script src="js/index.js"></script>
</body>
</html>

/*
 * 虽然移动端(安卓&IOS)上的浏览器大部分都是WEBKIT内核的,但是由于很多手机操作系统版本过低(尤其是安卓手机),导致很多CSS3新特性不能有效识别,此时我们使用的大部分CSS3属性都要写两套才能兼容(加前缀的在前,不加的在后)
 *  -webkit-animation
 *  animation
 *
 * 太麻烦了,不过没关系,有JS插件可以帮我们搞定这件事情 (prefixfree.min.js), 导入插件后,它会帮我们把所有需要加前缀的都加上
 */
@import "reset.min.less";
@import (reference) "common";

html {
  font-size: 100px; /*640PX设计稿尺寸中:1REM=100PX*/
}

html, body {
  position: relative;
  z-index: -4;
  height: 100%;
  overflow: hidden;
  background: #F4F4F4;
  font-family: "Microsoft JhengHei";
}

.mainBox {
  position: relative;
  z-index: -3;
  margin: 0 auto;
  max-width: 640px;
  height: 100%;
  background: #FFF;
}

.loadingBox, .phoneBox, .messageBox, .cubeBox, .detailBox {
  display: none;
  position: relative;
  height: 100%;
  overflow: hidden;
}

/*LOADING*/
.loadingBox {
  background: #000;

  .title {
    position: absolute;
    left: 0;
    top: 50%;
    margin-top: -2.2rem; /* -0.7(正中间)+1.5(距离中间靠上的位移) */
    width: 100%;
    height: 1.4rem;
    color: #FFF;

    h1 {
      line-height: .75rem;
      font-size: .5rem;
      text-align: center;
    }

    h2 {
      margin-top: .2rem;
      line-height: .45rem;
      text-align: center;
      letter-spacing: .04rem;
    }
  }

  .progress {
    position: absolute;
    top: 50%;
    left: 50%;
    margin: .85rem 0 0 -2.3rem;
    width: 4.6rem;
    height: .3rem;
    background: #FFF;

    .current {
      position: absolute;
      top: 0;
      left: 0;
      width: 0;
      height: 100%;
      background: -webkit-linear-gradient(left bottom, #5CB85C 0%, #5CB85C 25%, #74C274 25%, #74C274 50%, #5CB85C 50%, #5CB85C 75%, #74C274 75%, #74C274 100%);
      background: linear-gradient(left bottom, #5CB85C 0%, #5CB85C 25%, #74C274 25%, #74C274 50%, #5CB85C 50%, #5CB85C 75%, #74C274 75%, #74C274 100%);
      background-size: .3rem .3rem;
      animation: loadingMove .5s linear 0s infinite both;

      /*给CURRENT设置一个过渡动画:当我们在JS中控制它的宽度在变化的时候,给其一个平稳的过渡动画效果(而不是生硬的改变)*/
      transition: .3s;
    }
  }
}

@keyframes loadingMove {
  0% {
    background-position: 0 0;
  }
  100% {
    background-position: 0 -.3rem;
  }
}

/*PHONE*/
.phoneBox {
  z-index: -2;
  background: url("../img/zf_phoneBg.jpg") no-repeat;
  background-size: cover;

  h2 {
    margin-top: .5rem;
    text-align: center;

    img {
      display: inline-block;
      width: 2.62rem;
      height: 1.25rem;
    }

    span {
      display: none;
      margin-top: .1rem;
      line-height: .3rem;
      font-size: .3rem;
      color: #FFF;
      letter-spacing: .05rem;
    }
  }

  .answer {
    position: absolute;
    bottom: .3rem;
    left: 50%;
    margin-left: -2.6rem;
    width: 5.2rem;
    height: 3.6rem;
    background: url("../img/zf_phoneListen.png") no-repeat;
    background-size: 100% 100%;

    .markMove {
      position: absolute;
      right: -.06rem;
      bottom: .48rem;
      z-index: -1;
      box-sizing: border-box;
      width: 1.6rem;
      height: 1.6rem;
      border-radius: 50%;
      border: .03rem solid #0F0;
      animation: answerMove 1s linear infinite both;
    }

    .markLink {
      .markMove; //=>把MARK-MOVE的样式继承过来使用
      z-index: 1;
      border: none;
      border-radius: 0;
      animation: none;
    }
  }

  .hang {
    position: absolute;
    bottom: .3rem;
    left: 50%;
    margin-left: -2.6rem;
    width: 5.2rem;
    height: 6.59rem;
    background: url('../img/zf_phoneDetail.png') no-repeat;
    background-size: 100% 100%;

    //=>初始位置是在PHONE的底部(看不见:溢出内容隐藏),当点击接听按钮后,控制它从底下出来即可(JS中改变样式) “我们可以基于TRANSFORM改变样式的尽量不要使用传统的样式属性,因为TRANSFORM操作开启了浏览器的硬件加速,性能更高一些”
    transform: translateY(6.89rem);
    transition: .3s;

    .markLink {
      position: absolute;
      bottom: .26rem;
      left: 50%;
      z-index: 1;
      margin-left: -.8rem;
      width: 1.6rem;
      height: 1.6rem;
    }
  }
}

@keyframes answerMove {
  from {
    transform: scale(1.2);
  }
  to {
    transform: scale(0);
  }
}

/*MESSAGE*/
.messageBox {
  background: #EAEAEA;

  .wrapper {
    position: absolute;
    top: .2rem;
    left: 0;
    width: 100%;
    transition: .3s;

    li {
      position: relative;
      max-width: 3.6rem;
      padding: .25rem;
      margin-bottom: .4rem;
      border-radius: .1rem;
      line-height: .4rem;
      font-size: .26rem;
      opacity: 0;

      &.active {
        animation: messageListMove .3s linear both;
      }

      .pic {
        position: absolute;
        top: 0;
        width: .82rem;
        height: .82rem;
        border-radius: 50%;
      }

      .arrow {
        position: absolute;
        top: .2rem;
        width: .1rem;
        height: .2rem;
      }

      &.self {
        float: left;
        margin-left: 1.25rem;
        background: #FFF;
        border: .02rem solid #CACACA;

        .pic {
          left: -1rem;
        }

        .arrow {
          left: -.1rem;
          background: url("../img/zf_messageArrow1.png") no-repeat;
          background-size: 100% 100%;
        }
      }

      &.inter {
        float: right;
        margin-right: 1.25rem;
        background: #A2E45C;
        border: .02rem solid #96B474;

        .pic {
          right: -1rem;
        }

        .arrow {
          right: -.1rem;
          background: url("../img/zf_messageArrow2.png") no-repeat;
          background-size: 100% 100%;
        }
      }
    }
  }

  .keyBoard {
    position: absolute;
    left: 0;
    bottom: -.5rem;
    box-sizing: border-box;
    width: 100%;
    height: 5.16rem;
    background: url("../img/zf_messageKeyboard.png") no-repeat;
    background-size: 100% 100%;

    /*初始位置*/
    transform: translateY(3.7rem);
    transition: .3s;

    span {
      position: absolute;
      left: .9rem;
      top: .35rem;
      width: 4rem;
      height: .4rem;
      line-height: .4rem;
      font-size: .25rem;
    }

    .submit {
      display: none;
      position: absolute;
      right: .1rem;
      bottom: .6rem;
      width: 1.47rem;
      height: .74rem;
      background: url("../img/zf_messageChat.png") no-repeat;
      background-size: 100% 100%;
    }
  }
}

@keyframes messageListMove {
  from {
    transform: translateY(1rem);
    opacity: 0;
  }
  to {
    transform: translateY(0rem);
    opacity: 1;
  }
}

/*CUBE*/
.cubeBox {
  background: url("../img/zf_cubeBg.jpg") no-repeat;
  background-size: cover;

  .cube {
    position: absolute;
    top: 50%;
    left: 50%;
    margin: -2.55rem 0 0 -2.55rem;
    width: 5.1rem;
    height: 5.1rem;

    li {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;

      img {
        display: block;
        width: 100%;
        height: 100%;
      }
    }
  }

  .tip {
    position: absolute;
    bottom: .5rem;
    left: 50%;
    margin-left: -1.97rem;
    width: 3.94rem;
    height: .44rem;
  }
}

//=>在二维平面中实现3D效果
.cubeBox {
  //1.给需要实现3D变形元素所在的舞台设置“视距”(1000~2000)
  perspective: 2000px;

  .cube {
    //2.给需要操作的元素设置3D变形效果
    transform-style: preserve-3d;

    //3.基于TRASFORM实现3D变形
    li {
      &:nth-child(1) {
        transform: translateZ(2.55rem);
      }

      &:nth-child(2) {
        transform: translateZ(-2.55rem) rotateY(180deg);
      }

      &:nth-child(3) {
        transform: translateX(2.55rem) rotateY(90deg);
      }

      &:nth-child(4) {
        transform: translateX(-2.55rem) rotateY(-90deg);
      }

      &:nth-child(5) {
        transform: translateY(-2.55rem) rotateX(90deg);
      }

      &:nth-child(6) {
        transform: translateY(2.55rem) rotateX(-90deg);
      }
    }

    //4.给魔方一个初始的旋转角度,让其可以看到3D的效果(旋转后太大了,把魔方缩小一点)
    transform: scale(0.6) rotateX(-35deg) rotateY(35deg);
    transition: .3s; //=>后期让魔方旋转的时候有一个平稳的过渡动画效果
  }
}

/*DETAIL*/
.detailBox {
  .swiper-container {
    height: 100%;
    overflow: hidden;

    .swiper-slide {
      position: relative; /*每一个页面中的元素相对于自己的页面定位*/
      width: 100%;
      height: 100%;
      overflow: hidden;

      &:nth-child(2) {
        background: #FFF9C1;
      }

      &:nth-child(3) {
        background: #E45454;
      }

      &:nth-child(4) {
        background: #FAC471;
      }

      &:nth-child(5) {
        background: #FBFFE8;
      }

      &:nth-child(6) {
        background: #5975FF;
      }
    }
  }

  //=>PAGE1
  .page1 {
    dl {
      position: absolute;
      left: 50%;
      top: 50%;
      margin: -3.6rem 0 0 -2.7rem;
      width: 5.4rem;
      height: 7.2rem;

      dt, dd {
        box-sizing: border-box;
        height: .6rem;
        line-height: .6rem;
        background: #8FBB4C;
      }

      dt {
        text-align: center;
        font-size: .4rem;
        color: yellow;
      }

      dd {
        position: relative;
        border-top: .02rem dashed rgba(255, 255, 255, .3);

        em {
          position: absolute;
          left: .15rem;
          top: 50%;
          margin-top: -.21rem;
          width: .36rem;
          height: .42rem;
          line-height: .42rem;
          text-align: center;
          font-style: normal;
          font-size: .2rem;
          color: #FFF;
          background: url("../img/zf_outline.png") no-repeat;
          background-size: 100% 100%;
        }

        a {
          position: relative;
          display: block;
          margin-left: .66rem;
          font-size: .28rem;
          color: #000;

          text-overflow: ellipsis;
          white-space: nowrap;
          overflow: hidden;
        }

        em, a {
          z-index: 1000; //=>基于MAKISU实现3D折叠,为了保证内容不被折叠创建的SPAN遮住,我们需要把内容的层级提高
        }
      }
    }
  }

  //=>PAGE2
  .page2 {
    h2 {
      margin-top: .8rem;
      line-height: .9rem;
      text-align: center;
      font-size: .6rem;
      font-weight: normal;
      opacity: 0;
    }

    img {
      position: absolute;
      top: 50%;
      left: 50%;
      margin: -.5rem 0 0 -.5rem;
      width: 1rem;
      height: 1rem;
      opacity: 0;
      transition: .5s; //=>从中心到四周的动画我们可以基于TRANSITION完成

      &:nth-last-of-type(1) {
        margin: -.85rem 0 0 -.66rem;
        width: 1.32rem;
        height: 1.7rem;
      }
    }
  }

  #page2 {
    //=>PAGE2中的动画都写在ID选择器中
    h2 {
      animation: bounceInLeft 1s both;
    }

    img {
      &:nth-last-of-type(1) {
        animation: shake 1s both;
      }

      &:not(:nth-last-of-type(1)) {
        opacity: 1;
        animation: tada 1s .5s infinite both;
      }

      &:nth-of-type(1) {
        margin-top: -2.9rem; /*-.5-2.4*/
      }

      &:nth-of-type(2) {
        margin-top: -1.7rem;
        margin-left: 1.5rem;
      }

      &:nth-of-type(3) {
        margin-top: .7rem;
        margin-left: 1.5rem;
      }

      &:nth-of-type(4) {
        margin-top: 1.9rem;
      }

      &:nth-of-type(5) {
        margin-top: .7rem;
        margin-left: -2.5rem;
      }

      &:nth-of-type(6) {
        margin-top: -1.7rem;
        margin-left: -2.5rem;
      }
    }
  }

  /*
   * 基于SWIPER实现切换到哪一个页卡,让哪一个页卡中的后代元素有动画效果
   *   1.除了编写正常的CSS样式(都写在.PAGE-X中),把需要实现动画的元素所对应的动画写在#PAGE-X中(IE选择器优先级高)
   *   2.在SWIPER插件的某些回调函数中(例如:onTransitionEnd...)获取当前展示SLIDE的索引,根据索引为其设置对应的ID值,当前展示的SLIDE有ID,其余的没有ID
   *   3.为了保证切换到这一页面的时候,元素是动画运动出来的(也就是开始啥都看不见),每个元素都是基于动画显示的(在初始样式中.PAGE? 把所有需要运动的元素透明度设置为零  加ID后执行动画效果,在动画的最后一帧位置让透明度为1即可)
   */
}

@keyframes bounceInLeft {
  from,
  60%,
  75%,
  90%,
  to {
    -webkit-animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
    animation-timing-function: cubic-bezier(0.215, 0.61, 0.355, 1);
  }

  0% {
    opacity: 0;
    -webkit-transform: translate3d(-3000px, 0, 0);
    transform: translate3d(-3000px, 0, 0);
  }

  60% {
    opacity: 1;
    -webkit-transform: translate3d(25px, 0, 0);
    transform: translate3d(25px, 0, 0);
  }

  75% {
    -webkit-transform: translate3d(-10px, 0, 0);
    transform: translate3d(-10px, 0, 0);
  }

  90% {
    -webkit-transform: translate3d(5px, 0, 0);
    transform: translate3d(5px, 0, 0);
  }

  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
    opacity: 1;
  }
}

@keyframes shake {
  from,
  to {
    -webkit-transform: translate3d(0, 0, 0);
    transform: translate3d(0, 0, 0);
  }

  0% {
    opacity: 0;
  }

  100% {
    opacity: 1;
  }

  10%,
  30%,
  50%,
  70%,
  90% {
    -webkit-transform: translate3d(-10px, 0, 0);
    transform: translate3d(-10px, 0, 0);
  }

  20%,
  40%,
  60%,
  80% {
    -webkit-transform: translate3d(10px, 0, 0);
    transform: translate3d(10px, 0, 0);
  }
}

@keyframes tada {
  from {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }

  10%,
  20% {
    -webkit-transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
    transform: scale3d(0.9, 0.9, 0.9) rotate3d(0, 0, 1, -3deg);
  }

  30%,
  50%,
  70%,
  90% {
    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, 3deg);
  }

  40%,
  60%,
  80% {
    -webkit-transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
    transform: scale3d(1.1, 1.1, 1.1) rotate3d(0, 0, 1, -3deg);
  }

  to {
    -webkit-transform: scale3d(1, 1, 1);
    transform: scale3d(1, 1, 1);
  }
}

/*
 * 关于AUDIO的一些常用属性
 *    [属性]
 *    duration:播放的总时间(S)
 *    currentTime:当前已经播放的时间(S)
 *    ended:是否已经播放完成
 *    paused:当前是否为暂停状态
 *    volume:控制音量 (0~1)
 *
 *    [方法]
 *    pause() 暂停
 *    play() 播放
 *
 *    [事件]
 *    canplay:可以正常播放(但是播放过程中可能出现卡顿)
 *    canplaythrough:资源加载完毕,可以顺畅的播放了
 *    ended:播放完成
 *    loadedmetadata:资源的基础信息已经加载完成
 *    loadeddata:整个资源都加载完成
 *    pause:触发了暂停
 *    play:触发了播放
 *    playing:正在播放中
 */

/*LOADING*/
let loadingRender = (function () {
    let $loadingBox = $('.loadingBox'),
        $current = $loadingBox.find('.current');

    let imgData = ["img/icon.png", "img/zf_concatAddress.png", "img/zf_concatInfo.png", "img/zf_concatPhone.png", "img/zf_course.png", "img/zf_course1.png", "img/zf_course2.png", "img/zf_course3.png", "img/zf_course4.png", "img/zf_course5.png", "img/zf_course6.png", "img/zf_cube1.png", "img/zf_cube2.png", "img/zf_cube3.png", "img/zf_cube4.png", "img/zf_cube5.png", "img/zf_cube6.png", "img/zf_cubeBg.jpg", "img/zf_cubeTip.png", "img/zf_emploment.png", "img/zf_messageArrow1.png", "img/zf_messageArrow2.png", "img/zf_messageChat.png", "img/zf_messageKeyboard.png", "img/zf_messageLogo.png", "img/zf_messageStudent.png", "img/zf_outline.png", "img/zf_phoneBg.jpg", "img/zf_phoneDetail.png", "img/zf_phoneListen.png", "img/zf_phoneLogo.png", "img/zf_return.png", "img/zf_style1.jpg", "img/zf_style2.jpg", "img/zf_style3.jpg", "img/zf_styleTip1.png", "img/zf_styleTip2.png", "img/zf_teacher1.png", "img/zf_teacher2.png", "img/zf_teacher3.jpg", "img/zf_teacher4.png", "img/zf_teacher5.png", "img/zf_teacher6.png", "img/zf_teacherTip.png"];

    //=>RUN:预加载图片的
    let n = 0,
        len = imgData.length;
    let run = function run(callback) {
        imgData.forEach(item => {
            let tempImg = new Image;
            tempImg.onload = () => {
                tempImg = null;
                $current.css('width', ((++n) / len) * 100 + '%');

                //=>加载完成:执行回调函数(让当前LOADING页面消失)
                if (n === len) {
                    clearTimeout(delayTimer);
                    callback && callback();
                }
            };
            tempImg.src = item;
        });
    };

    //=>MAX-DELAY:设置最长等待时间(假设10S,到达10S我们看加载多少了,如果已经达到了90%以上,我们可以正常访问内容了,如果不足这个比例,直接提示用户当前网络状况不佳,稍后重试)
    let delayTimer = null;
    let maxDelay = function maxDelay(callback) {
        delayTimer = setTimeout(() => {
            clearTimeout(delayTimer);
            if (n / len >= 0.9) {
                $current.css('width', '100%');
                callback && callback();
                return;
            }
            alert('非常遗憾,当前您的网络状况不佳,请稍后在试!');
            // window.location.href = 'http://www.qq.com';//=>此时我们不应该继续加载图片,而是让其关掉页面或者是跳转到其它页面
        }, 10000);
    };

    //=>DONE:完成
    let done = function done() {
        //=>停留一秒钟再移除进入下一环节
        let timer = setTimeout(() => {
            $loadingBox.remove();
            clearTimeout(timer);

            phoneRender.init();
        }, 1000);
    };

    return {
        init: function () {
            $loadingBox.css('display', 'block');
            run(done);
            maxDelay(done);
        }
    }
})();

/*PHONE*/
let phoneRender = (function () {
    let $phoneBox = $('.phoneBox'),
        $time = $phoneBox.find('span'),
        $answer = $phoneBox.find('.answer'),
        $answerMarkLink = $answer.find('.markLink'),
        $hang = $phoneBox.find('.hang'),
        $hangMarkLink = $hang.find('.markLink'),
        answerBell = $('#answerBell')[0],
        introduction = $('#introduction')[0];

    //=>点击ANSWER-MARK
    let answerMarkTouch = function answerMarkTouch() {
        //1.REMOVE ANSWER
        $answer.remove();
        answerBell.pause();
        $(answerBell).remove();//=>一定要先暂停播放然后再移除,否则即使移除了浏览器也会播放着这个声音

        //2.SHOW HANG
        $hang.css('transform', 'translateY(0rem)');
        $time.css('display', 'block');
        introduction.play();
        computedTime();
    };

    //=>计算播放时间
    let autoTimer = null;
    let computedTime = function computedTime() {
        //=>我们让AUDIO播放,首先会去加载资源,部分资源加载完成才会播放,才会计算出总时间DURATION等信息,所以我们可以把获取信息放到CAN-PLAY事件中
        /*let duration = 0;
        introduction.oncanplay = function () {
            duration = introduction.duration;
        };*/
        autoTimer = setInterval(() => {
            let val = introduction.currentTime,
                duration = introduction.duration;
            //=>播放完成
            if (val >= duration) {
                clearInterval(autoTimer);
                closePhone();
                return;
            }
            let minute = Math.floor(val / 60),
                second = Math.floor(val - minute * 60);
            minute = minute < 10 ? '0' + minute : minute;
            second = second < 10 ? '0' + second : second;
            $time.html(`${minute}:${second}`);
        }, 1000);
    };

    //=>关闭PHONE
    let closePhone = function closePhone() {
        clearInterval(autoTimer);
        introduction.pause();
        $(introduction).remove();
        $phoneBox.remove();

        messageRender.init();
    };

    return {
        init: function () {
            $phoneBox.css('display', 'block');

            //=>播放BELL
            answerBell.play();
            answerBell.volume = 0.3;

            $answerMarkLink.tap(answerMarkTouch);
            $hangMarkLink.tap(closePhone);
        }
    }
})();

/*MESSAGE*/
let messageRender = (function () {
    let $messageBox = $('.messageBox'),
        $wrapper = $messageBox.find('.wrapper'),
        $messageList = $wrapper.find('li'),
        $keyBoard = $messageBox.find('.keyBoard'),
        $textInp = $keyBoard.find('span'),
        $submit = $keyBoard.find('.submit'),
        demonMusic = $('#demonMusic')[0];

    let step = -1,//=>记录当前展示信息的索引
        total = $messageList.length + 1,//=>记录的是信息总条数(自己发一条所以加1)
        autoTimer = null,
        interval = 1500;//=>记录信息相继出现的间隔时间

    //=>展示信息
    let tt = 0;
    let showMessage = function showMessage() {
        ++step;
        if (step === 2) {
            //=>已经展示两条了:此时我们暂时结束自动信息发送,让键盘出来,开始执行手动发送
            clearInterval(autoTimer);
            handleSend();
            return;
        }
        let $cur = $messageList.eq(step);
        $cur.addClass('active');
        if (step >= 3) {
            //=>展示的条数已经是四条或者四条以上了,此时我们让WRAPPER向上移动(移动的距离是新展示这一条的高度)
            /*let curH = $cur[0].offsetHeight,
                wraT = parseFloat($wrapper.css('top'));
            $wrapper.css('top', wraT - curH);*/
            //=>JS中基于CSS获取TRANSFORM,得到的结果是一个矩阵
            let curH = $cur[0].offsetHeight;
            tt -= curH;
            $wrapper.css('transform', `translateY(${tt}px)`);
        }
        if (step >= total - 1) {
            //=>展示完了
            clearInterval(autoTimer);
            closeMessage();
        }
    };

    //=>手动发送
    let handleSend = function handleSend() {
        $keyBoard.css({
            transform: 'translateY(0)'
        }).one('transitionend', () => {
            //=>TRANSITION-END:监听当前元素TRASITION动画结束的事件(并且有几个样式属性改变,并且执行了过渡效果,事件就会被触发执行几次 =>用ONE方法做事件绑定,只会让其触发一次)
            let str = '好的,马上介绍!',
                n = -1,
                textTimer = null;
            textTimer = setInterval(() => {
                let orginHTML = $textInp.html();
                $textInp.html(orginHTML + str[++n]);
                if (n >= str.length - 1) {
                    //=>文字显示完成
                    clearInterval(textTimer);
                    $submit.css('display', 'block');
                }
            }, 100);
        });
    };

    //=>点击SUBMIT
    let handleSubmit = function handleSubmit() {
        //=>把新创建的LI增加到页面中第二个LI的后面
        $(`<li class="self">
            <i class="arrow"></i>
            <img src="img/zf_messageStudent.png" alt="" class="pic">
            ${$textInp.html()}
        </li>`).insertAfter($messageList.eq(1)).addClass('active');
        $messageList = $wrapper.find('li');//=>重要:把新的LI放到页面中,我们此时应该重新获取LI,让MESSAGE-LIST和页面中的LI正对应,方便后期根据索引展示对应的LI

        //=>该消失的消失
        $textInp.html('');
        $submit.css('display', 'none');
        $keyBoard.css('transform', 'translateY(3.7rem)');

        //=>继续向下展示剩余的消息
        autoTimer = setInterval(showMessage, interval);
    };

    //=>关掉MESSAGE区域
    let closeMessage = function closeMessage() {
        let delayTimer = setTimeout(() => {
            demonMusic.pause();
            $(demonMusic).remove();
            $messageBox.remove();
            clearTimeout(delayTimer);

            cubeRender.init();
        }, interval);
    };

    return {
        init: function () {
            $messageBox.css('display', 'block');

            //=>加载模块立即展示一条信息,后期间隔INTERVAL在发送一条信息
            showMessage();
            autoTimer = setInterval(showMessage, interval);

            //=>SUBMIT
            $submit.tap(handleSubmit);

            //=>MUSIC
            demonMusic.play();
            demonMusic.volume = 0.3;
        }
    }
})();

/*CUBE*/
let cubeRender = (function () {
    let $cubeBox = $('.cubeBox'),
        $cube = $('.cube'),
        $cubeList = $cube.find('li');

    //=>手指控住旋转
    let start = function start(ev) {
        //=>记录手指按在位置的起始坐标
        let point = ev.changedTouches[0];
        this.strX = point.clientX;
        this.strY = point.clientY;
        this.changeX = 0;
        this.changeY = 0;
    };
    let move = function move(ev) {
        //=>用最新手指的位置-起始的位置,记录X/Y轴的偏移
        let point = ev.changedTouches[0];
        this.changeX = point.clientX - this.strX;
        this.changeY = point.clientY - this.strY;
    };
    let end = function end(ev) {
        //=>获取CHANGE/ROTATE值
        let {changeX, changeY, rotateX, rotateY} = this,
            isMove = false;
        //=>验证是否发生移动(判断滑动误差)
        Math.abs(changeX) > 10 || Math.abs(changeY) > 10 ? isMove = true : null;
        //=>只有发生移动再处理
        if (isMove) {
            //1.左右滑=>CHANGE-X=>ROTATE-Y (正比:CHANGE越大ROTATE越大)
            //2.上下滑=>CHANGE-Y=>ROTATE-X (反比:CHANGE越大ROTATE越小)
            //3.为了让每一次操作旋转角度小一点,我们可以把移动距离的1/3作为旋转的角度即可
            rotateX = rotateX - changeY / 3;
            rotateY = rotateY + changeX / 3;
            //=>赋值给魔方盒子
            $(this).css('transform', `scale(0.6) rotateX(${rotateX}deg) rotateY(${rotateY}deg)`);
            //=>让当前旋转的角度成为下一次起始的角度
            this.rotateX = rotateX;
            this.rotateY = rotateY;
        }
        //=>清空其它记录的自定义属性值
        ['strX', 'strY', 'changeX', 'changeY'].forEach(item => this[item] = null);
    };

    return {
        init: function () {
            $cubeBox.css('display', 'block');

            //=>手指操作CUBE,让CUBE跟着旋转
            let cube = $cube[0];
            cube.rotateX = -35;
            cube.rotateY = 35;//=>记录初始的旋转角度(存储到自定义属性上)
            $cube.on('touchstart', start)
                .on('touchmove', move)
                .on('touchend', end);

            //=>点击每一个面跳转到详情区域对应的页面
            $cubeList.tap(function () {
                $cubeBox.css('display', 'none');

                //=>跳转到详情区域,通过传递点击LI的索引,让其定位到具体的SLIDE
                let index = $(this).index();
                detailRender.init(index);
            });
        }
    }
})();

/*DETAIL*/
let detailRender = (function () {
    let $detailBox = $('.detailBox'),
        swiper = null,
        $dl = $('.page1>dl');

    let swiperInit = function swiperInit() {
        swiper = new Swiper('.swiper-container', {
            effect: 'coverflow',
            onInit: move,
            onTransitionEnd: move
        });
    };

    let move = function move(swiper) {
        //=>SWIPER:当前创建的实例
        //1.判断当前是否为第一个SLIDE:如果是让3D菜单展开,不是收起3D菜单
        let activeIn = swiper.activeIndex,
            slideAry = swiper.slides;
        if (activeIn === 0) {
            //=>PAGE1
            $dl.makisu({
                selector: 'dd',
                overlap: 0.6,
                speed: 0.8
            });
            $dl.makisu('open');
        } else {
            //=>OTHER PAGE
            $dl.makisu({
                selector: 'dd',
                speed: 0
            });
            $dl.makisu('close');
        }

        //2.滑动到哪一个页面,把当前页面设置对应的ID,其余页面移除ID即可
        slideAry.forEach((item, index) => {
            if (activeIn === index) {
                item.id = `page${index + 1}`;
                return;
            }
            item.id = null;
        });
    };

    return {
        init: function (index = 0) {
            $detailBox.css('display', 'block');
            if (!swiper) {
                //=>防止重复初始化
                swiperInit();
            }
            swiper.slideTo(index, 0);//=>直接运动到具体的SLIDE页面(第二个参数是切换的速度:0立即切换没有切换的动画效果)
        }
    }
})();

/*以后在真实的项目中,如果页面中有滑动的需求,我们一定要把DOCUMENT本身滑动的默认行为阻止掉(不阻止:浏览器中预览,会触发下拉刷新或者左右滑动切换页卡等功能)*/
$(document).on('touchstart touchmove touchend', (ev) => {
    ev.preventDefault();
});


/*HASH*/
let url = window.location.href,//=>获取当前页面的URL地址  location.href='xxx'这种写法是让其跳转到某一个页面
    well = url.indexOf('#'),
    hash = well === -1 ? null : url.substr(well + 1);
switch (hash) {
    case 'loading':
        loadingRender.init();
        break;
    case 'phone':
        phoneRender.init();
        break;
    case 'message':
        messageRender.init();
        break;
    case 'cube':
        cubeRender.init();
        break;
    case 'detail':
        detailRender.init();
        break;
    default:
        loadingRender.init();
}

交互简历案例(48)交互简历案例(48)交互简历案例(48)交互简历案例(48)交互简历案例(48)交互简历案例(48)交互简历案例(48)交互简历案例(48)交互简历案例(48)交互简历案例(48)交互简历案例(48)交互简历案例(48)

 prefixfree.min.js

导入插件后,它会帮我们把所有需要加前缀的都加上

/**
 * StyleFix 1.0.3 & PrefixFree 1.0.7
 * @author Lea Verou
 * MIT license
 */
(function(){function m(a,b){return[].slice.call((b||document).querySelectorAll(a))}if(window.addEventListener){var e=window.StyleFix={link:function(a){var b=a.href||a.getAttribute("data-href");try{if(!b||"stylesheet"!==a.rel||a.hasAttribute("data-noprefix"))return}catch(p){return}var d=b.replace(/[^\/]+$/,""),f=(/^[a-z]{3,10}:/.exec(d)||[""])[0],h=(/^[a-z]{3,10}:\/\/[^\/]+/.exec(d)||[""])[0],k=/^([^?]*)\??/.exec(b)[1],g=a.parentNode,c=new XMLHttpRequest,l;c.onreadystatechange=function(){4===c.readyState&&
l()};l=function(){var b=c.responseText;if(b&&a.parentNode&&(!c.status||400>c.status||600<c.status)){if((b=e.fix(b,!0,a))&&d)var b=b.replace(/url\(\s*?((?:"|')?)(.+?)\1\s*?\)/gi,function(b,a,c){return/^([a-z]{3,10}:|#)/i.test(c)?b:/^\/\//.test(c)?'url("'+f+c+'")':/^\//.test(c)?'url("'+h+c+'")':/^\?/.test(c)?'url("'+k+c+'")':'url("'+d+c+'")'}),n=d.replace(/([\\\^\$*+[\]?{}.=!:(|)])/g,"\\$1"),b=b.replace(RegExp("\\b(behavior:\\s*?url\\('?\"?)"+n,"gi"),"$1");n=document.createElement("style");n.textContent=
"/*# sourceURL="+a.getAttribute("href")+" */\n/*@ sourceURL="+a.getAttribute("href")+" */\n"+b;n.media=a.media;n.disabled=a.disabled;n.setAttribute("data-href",a.getAttribute("href"));a.id&&(n.id=a.id);g.insertBefore(n,a);g.removeChild(a);n.media=a.media}};try{c.open("GET",b),c.send(null)}catch(p){"undefined"!=typeof XDomainRequest&&(c=new XDomainRequest,c.onerror=c.onprogress=function(){},c.onload=l,c.open("GET",b),c.send(null))}a.setAttribute("data-inprogress","")},styleElement:function(a){if(!a.hasAttribute("data-noprefix")){var b=
a.disabled;a.textContent=e.fix(a.textContent,!0,a);a.disabled=b}},styleAttribute:function(a){var b=a.getAttribute("style"),b=e.fix(b,!1,a);a.setAttribute("style",b)},process:function(){m('link[rel="stylesheet"]:not([data-inprogress])').forEach(StyleFix.link);m("style").forEach(StyleFix.styleElement);m("[style]").forEach(StyleFix.styleAttribute)},register:function(a,b){(e.fixers=e.fixers||[]).splice(void 0===b?e.fixers.length:b,0,a)},fix:function(a,b,d){if(e.fixers)for(var f=0;f<e.fixers.length;f++)a=
e.fixers[f](a,b,d)||a;return a},camelCase:function(a){return a.replace(/-([a-z])/g,function(b,a){return a.toUpperCase()}).replace("-","")},deCamelCase:function(a){return a.replace(/[A-Z]/g,function(b){return"-"+b.toLowerCase()})}};(function(){setTimeout(function(){m('link[rel="stylesheet"]').forEach(StyleFix.link)},10);document.addEventListener("DOMContentLoaded",StyleFix.process,!1)})()}})();
(function(m){function e(b,d,f,h,k){b=a[b];b.length&&(b=RegExp(d+"("+b.join("|")+")"+f,"gi"),k=k.replace(b,h));return k}if(window.StyleFix&&window.getComputedStyle){var a=window.PrefixFree={prefixCSS:function(b,d,f){var h=a.prefix;-1<a.functions.indexOf("linear-gradient")&&(b=b.replace(/(\s|:|,)(repeating-)?linear-gradient\(\s*(-?\d*\.?\d*)deg/ig,function(b,a,d,f){return a+(d||"")+"linear-gradient("+(90-f)+"deg"}));b=e("functions","(\\s|:|,)","\\s*\\(","$1"+h+"$2(",b);b=e("keywords","(\\s|:)","(\\s|;|\\}|$)",
"$1"+h+"$2$3",b);b=e("properties","(^|\\{|\\s|;)","\\s*:","$1"+h+"$2:",b);if(a.properties.length){var k=RegExp("\\b("+a.properties.join("|")+")(?!:)","gi");b=e("valueProperties","\\b",":(.+?);",function(a){return a.replace(k,h+"$1")},b)}d&&(b=e("selectors","","\\b",a.prefixSelector,b),b=e("atrules","@","\\b","@"+h+"$1",b));b=b.replace(RegExp("-"+h,"g"),"-");return b=b.replace(/-\*-(?=[a-z]+)/gi,a.prefix)},property:function(b){return(0<=a.properties.indexOf(b)?a.prefix:"")+b},value:function(b,d){b=
e("functions","(^|\\s|,)","\\s*\\(","$1"+a.prefix+"$2(",b);b=e("keywords","(^|\\s)","(\\s|$)","$1"+a.prefix+"$2$3",b);0<=a.valueProperties.indexOf(d)&&(b=e("properties","(^|\\s|,)","($|\\s|,)","$1"+a.prefix+"$2$3",b));return b},prefixSelector:function(b){return a.selectorMap[b]||b},prefixProperty:function(b,d){var f=a.prefix+b;return d?StyleFix.camelCase(f):f}};(function(){var b={},d=[],f=getComputedStyle(document.documentElement,null),h=document.createElement("div").style,k=function(a){if("-"===
a.charAt(0)){d.push(a);a=a.split("-");var c=a[1];for(b[c]=++b[c]||1;3<a.length;)a.pop(),c=a.join("-"),StyleFix.camelCase(c)in h&&-1===d.indexOf(c)&&d.push(c)}};if(f&&0<f.length)for(var g=0;g<f.length;g++)k(f[g]);else for(var c in f)k(StyleFix.deCamelCase(c));var g=0,e,p;for(p in b)f=b[p],g<f&&(e=p,g=f);a.prefix="-"+e+"-";a.Prefix=StyleFix.camelCase(a.prefix);a.properties=[];for(g=0;g<d.length;g++)c=d[g],0===c.indexOf(a.prefix)&&(e=c.slice(a.prefix.length),StyleFix.camelCase(e)in h||a.properties.push(e));
!("Ms"!=a.Prefix||"transform"in h||"MsTransform"in h)&&"msTransform"in h&&a.properties.push("transform","transform-origin");a.properties.sort()})();(function(){function b(a,b){e[b]="";e[b]=a;return!!e[b]}var d={"linear-gradient":{property:"backgroundImage",params:"red, teal"},calc:{property:"width",params:"1px + 5%"},element:{property:"backgroundImage",params:"#foo"},"cross-fade":{property:"backgroundImage",params:"url(a.png), url(b.png), 50%"},"image-set":{property:"backgroundImage",params:"url(a.png) 1x, url(b.png) 2x"}};
d["repeating-linear-gradient"]=d["repeating-radial-gradient"]=d["radial-gradient"]=d["linear-gradient"];var f={initial:"color",grab:"cursor",grabbing:"cursor","zoom-in":"cursor","zoom-out":"cursor",box:"display",flexbox:"display","inline-flexbox":"display",flex:"display","inline-flex":"display",grid:"display","inline-grid":"display","max-content":"width","min-content":"width","fit-content":"width","fill-available":"width","contain-floats":"width"};a.functions=[];a.keywords=[];var e=document.createElement("div").style,
k;for(k in d){var g=d[k],c=g.property,g=k+"("+g.params+")";!b(g,c)&&b(a.prefix+g,c)&&a.functions.push(k)}for(var l in f)c=f[l],!b(l,c)&&b(a.prefix+l,c)&&a.keywords.push(l)})();(function(){function b(a){h.textContent=a+"{}";return!!h.sheet.cssRules.length}var d={":any-link":null,"::backdrop":null,":fullscreen":null,":full-screen":":fullscreen","::placeholder":null,":placeholder":"::placeholder","::input-placeholder":"::placeholder",":input-placeholder":"::placeholder",":read-only":null,":read-write":null,
"::selection":null},e={keyframes:"name",viewport:null,document:'regexp(".")'};a.selectors=[];a.selectorMap={};a.atrules=[];var h=m.appendChild(document.createElement("style")),k;for(k in d){var g=d[k]||k,c=k.replace(/::?/,function(b){return b+a.prefix});!b(g)&&b(c)&&(a.selectors.push(g),a.selectorMap[g]=c)}for(var l in e)d=l+" "+(e[l]||""),!b("@"+d)&&b("@"+a.prefix+d)&&a.atrules.push(l);m.removeChild(h)})();a.valueProperties=["transition","transition-property","will-change"];m.className+=" "+a.prefix;
StyleFix.register(a.prefixCSS)}})(document.documentElement);

readImgList.js

读取当前img目录下的图片文件

let fs = require('fs');
let ary = fs.readdirSync('./');
let result = [];
ary.forEach(function (item) {
    if (/\.(PNG|GIF|JPG)/i.test(item)) {
        //=>图片
        result.push(`img/` + item);
    }
});
fs.writeFileSync('./result.txt', JSON.stringify(result), 'utf-8');

移动端事件

     * CLICK在移动端是单击事件行为,当触发点击操作,浏览器总会等待300MS,验证是否触发了第二次点击操作,没有触发才会执行CLICK对应的方法(CLICK在移动端的300MS延迟问题)

     *   1.不建议大家在移动端使用CLICK(如果非要使用也可以,最好导入一个插件 fastclick.min.js 就是解决300MS延迟的插件)

     *

     *   2.目前项目中移动端的点击操作等基本上都是基于第三方类库(事件库完成的)

     *     zepto:提供了移动端常用的事件操作

     *     touch.js

     *     hammer.js 

  * TouchEvent:手指事件对象

         *   changedTouches

         *   touches

         *   手指操作的信息集合,集合中记录了每一根操作的手指的相关信息(包含触发点的坐标位置),touches记录的信息只有手指在屏幕上才有,也就是手指离开屏幕的时候信息就消失了,changedTouches本意上记录的是改变的值,即使手指离开,信息值也在

let $box = $('.box');
    =>ZEPTO中提供的专门供移动端操作的事件方法
    $box.tap(ev => {
        //=>点击
    });
    $box.singleTap(ev => {
        //=>单击
    });
    $box.doubleTap(ev => {
        //=>双击
    });
    $box.longTap(ev => {
        //=>长按
    });
    //=>滑动 swipe / swipeLeft / swipeRight / swipeUp / swipeDown...
    //=>缩放 pinchIn / pinchOut ...

    //=>ZEPTO VS JQ
    //1.ZEPTO没有考虑浏览器的兼容,专门为移动端开发的小型类库,也仅仅是把JQ中的一些常规方法实现
    //了,很多方法也没有实现(例如:slideDown/show...在ZEPTO中都没有) =>为了保证ZEPTO的体积足够小
    //2.ZEPTO中提供了移动端专门操作的事件方法(例如:tap等),这些方法都是基于移动端的TOUCH
    //和GESTURE事件模型封装好的方法,JQ中并没有提供这些方法 =>ZEPTO更适合移动端
    //...



let box = document.querySelector('.box');

    box.ontouchstart = function (ev) {
        //=>按下的时候记录手指的起始位置
        let point = ev.changedTouches[0];
        this.strX = point.clientX;
        this.strY = point.clientY;
        this.isMove = false;
    };
    box.ontouchmove = function (ev) {
        let point = ev.changedTouches[0];
        this.changeX = point.clientX - this.strX;
        this.changeY = point.clientY - this.strY;
        if (Math.abs(this.changeX) > 10 || Math.abs(this.changeY) > 10) {
            //=>10是操作误差值
            this.isMove = true;
        }
    };
    box.ontouchend = function (ev) {
        if (this.isMove) {
            //=>滑动
            return;
        }
        //=>点击
        console.log('我是点击操作');
    };

上一篇:Java并发48:并发集合系列-基于CAS算法的非阻塞双向*队列ConcurrentLinkedDueue


下一篇:js各种弹框