zoukankan      html  css  js  c++  java
  • JGUI源码:Accordion鼠标中键滚动和手机端滑动实现(2)

    本文是抽屉组件在PC端滚动鼠标中键、手机端滑动时,滚动数据列表实现方法,没有使用iscroll等第三方插件,支持火狐,谷歌,IE8+等浏览器。

    演示在:www.jgui.com   

    Github地址:https://github.com/zhaogaojian/JGUI

    效果

    觉得好的给个star,谢谢!

    源码未压缩,请右键查看网页源码,相关文件有accordion.js,accordion.css,index.html

    隐藏滚动条可以通过设置margin隐藏滚动条方式实现,css3支持直接隐藏滚动条,这两种方式实现简单,网上也有很多文章

    本文使用监听鼠标滚动事件滚动方式。

    下面是实现过程和思路,大家可以一起来学习下使用到的技术。

    前端html结构如下

    <div class="jgui-accordion"
                style="100%;overflow:hidden;position: absolute;top:60px;left:0px;right: 0px;bottom:0px;">
                <div class="jgui-accordion-list">
                    <ul>
                        <dl>
                            <dt class="jgui-accordion-navitem">
                                <a>
                                    <i class="anticon  icon-home"></i>
                                    <span>目录1</span>
                                    <i class="jgui-accordion-navitem-more"></i>
                                </a>
                            </dt>
    .......

    方法一:使用jquery animate实现(只处理垂直方向上滚动)

    //电脑端中键滚动事件
    mousewheel = getBrowserInfo() == "Firefox" ? "DOMMouseScroll" : "mousewheel";
    $('.jgui-accordion').on(mousewheel, function (event) {
        var delta = 0;
        if (!event) /* For IE. */
            event = window.event;
        if (event.originalEvent.wheelDelta) { /* IE/Opera. */
            delta = event.originalEvent.wheelDelta / 120;
        } else if (event.originalEvent.detail) {
            delta = -event.originalEvent.detail / 3;
        }
        console.log(delta);
        if (delta)
            handle(delta);
        if (event.preventDefault)
            event.preventDefault();
        event.returnValue = false;
    });
    var handle = function (delta) {
        var step = Math.floor($('.jgui-accordion').height()/10);            //可视区高度
        var cur_top = $('.jgui-accordion').scrollTop();    //当前滚过的高度
        var direction = delta > 0 ? -1 : 1;
        $(".jgui-accordion").stop().animate({ scrollTop: direction * step + cur_top }, 50);
    }
    //手机端鼠标滑动事件
    $(".jgui-accordion").on("touchstart", function (e) {
        startY = e.originalEvent.changedTouches[0].pageY;
    });
    
    $(".jgui-accordion").on("touchmove", function (e) {
    
        e.preventDefault();
        moveEndY = e.originalEvent.changedTouches[0].pageY,
        Y = (moveEndY - startY);
        startY = moveEndY;
        var cur_top = $('.jgui-accordion').scrollTop();    //当前滚过的高度
        $(".jgui-accordion").stop().animate({ scrollTop: -Y + cur_top }, 0);
    
    });

    方法二:使用css3 tansform实现,以手机端滑动为例

    //手机端鼠标滑动事件
    $(".jgui-accordion-list").on("touchstart", function (e) {
        startY = e.originalEvent.changedTouches[0].pageY;
        console.log("aa");
    });
    curY=0;
    $(".jgui-accordion-list").on("touchmove", function (e) {
      e.preventDefault();
        moveEndY = e.originalEvent.changedTouches[0].pageY,
        Y = (moveEndY - startY) ;
        curY+=Y;
        startY = moveEndY;
        $(".jgui-accordion-list").css('-webkit-transform','translate3d(0px,'+curY+'px,0px)')
        $(".jgui-accordion-list").css('-moz-transform','translate3d(0px,'+curY+'px,0px)')
    });

    在本页面中,两种方式性能基本上差不多,第二种需要手动计算滚动区域,防止过高或过低。

    PC端模拟手机滑动效果如下

    滚动时,会发现缺少了一点惯性,比如鼠标中键一次拨动几个和拨动一个应该移动距离不一样,为了解决这个问题改进代码如下

    //电脑端中键滚动事件
    var sumdelta=0;
    var mousewheel = getBrowserInfo() == "Firefox" ? "DOMMouseScroll" : "mousewheel";
    $('.jgui-accordion').on(mousewheel, function (event) {
        var delta = 0;
        if (!event) /* For IE. */
            event = window.event;
        if (event.originalEvent.wheelDelta) { /* IE/Opera. */
            delta = event.originalEvent.wheelDelta / 120;
        } else if (event.originalEvent.detail) {
            delta = -event.originalEvent.detail / 3;
        }
        if (delta)
        {
            sumdelta+=(delta> 0 ? -1 : 1);
            setTimeout("handle()",80);
        } 
        stopPropagation(event);
    });
    var handle = function () {
        isanimate=true;
        var step = Math.floor($('.jgui-accordion').height()/5);//可视区高度
        var cur_top = $('.jgui-accordion').scrollTop();    //当前滚过的高度
        var direction = sumdelta ;//> 0 ? -1 : 1;
        $(".jgui-accordion").stop().animate({ scrollTop: direction * step + cur_top }, 800,'swing',function(){sumdelta=0;});
        
    }

    上面通过setTimeout延时触发滚动事件,即可实现不同的滚动速度,因为鼠标中键滚动只有一个mousewheel不像左右键那样有按下,移动,松开事件,所以需要借助定时器。

    测试发现突然变向滑动时,会感觉有延迟,分析代码原因主要是因为sumdelta=0,这时候可能正在进行的滚动操作被重置了,另外部分变量使用的全局变量也不合适,因为界面上可能有多个accordion,

    下面增加一个Jquery对象变量,优化代码如下:

    //电脑端中键滚动事件
    var mousewheel = getBrowserInfo() == "Firefox" ? "DOMMouseScroll" : "mousewheel";
    $('.jgui-accordion').on(mousewheel, function (event) {
        var delta = 0;
        if (!event) /* For IE. */
            event = window.event;
        if (event.originalEvent.wheelDelta) { /* IE/Opera. */
            delta = event.originalEvent.wheelDelta / 120;
        } else if (event.originalEvent.detail) {
            delta = -event.originalEvent.detail / 3;
        }
        if (delta)
        {
            var datas=$(this).data('datas');
            datas.sumdelta+=(delta> 0 ? -1 : 1);
            var direction = datas.sumdelta ;
            var obj=$(this);
            var handle = function () {
                datas.sumdelta=0;
                var step = Math.floor(obj.height()/10);//可视区高度
                var cur_top = obj.scrollTop();    //当前滚过的高度
                obj.stop().animate({ scrollTop: direction * step + cur_top }, 400,'linear',function(){direction=0;});
                
            }
            setTimeout(handle,100);
        } 
        stopPropagation(event);
    });

    datas.sumdelta是自定义的一个Jquery对象变量,增加变量方法如下(return this.each是一个链式操作,返回的是this)。

    $.fn.jAccordion = function (p_options,p_datas, p_param) {
        return this.each(function () {
            var obj = $(this);
            var datas = $.extend({
                sumdelta:0
            },  p_datas);
            obj.data('datas', datas);
        });
    };
    $(".jgui-accordion").jAccordion();

    为了进一步提升滚轮加速效果和防止Timer重入再次修改代码如下

    //电脑端中键滚动事件
    var mousewheel = getBrowserInfo() == "Firefox" ? "DOMMouseScroll" : "mousewheel";
    $('.jgui-accordion').on(mousewheel, function (event) {
        var delta = 0;
        if (!event) /* For IE. */
            event = window.event;
        if (event.originalEvent.wheelDelta) { /* IE/Opera. */
            delta = event.originalEvent.wheelDelta / 120;
        } else if (event.originalEvent.detail) {
            delta = -event.originalEvent.detail / 3;
        }
        if (delta)
        {
            var datas=$(this).data('datas');
            datas.sumdelta+=(delta> 0 ? -1 : 1);
            var direction = datas.sumdelta ;
            var obj=$(this);
            var handle = function () {
                datas.isscrolling=true;
                datas.sumdelta=0;
                var step = Math.floor(obj.height()/30);//可视区高度
                var cur_top = obj.scrollTop();    //当前滚过的高度
                obj.stop().animate({ scrollTop: direction*Math.abs(direction) * step + cur_top }, 400,'linear',function(){direction=0;datas.isscrolling=false});
                
            }
            if(!datas.isscrolling)
            setTimeout(handle,100);
        } 
        stopPropagation(event);
    });
    $.fn.jAccordion = function (p_options,p_datas, p_param) {
        return this.each(function () {
            var obj = $(this);
            var datas = $.extend({
                sumdelta:0,isscrolling:false
            },  p_datas);
            obj.data('datas', datas);
        });
    };
    $(".jgui-accordion").jAccordion();

    这样在拨动一两格时,滚动条缓慢移动,当快速波动时,因为平方的效应,能引起加速滚动,可以快速的回到顶部或者底部。如果不想使用这个滚动条代码,将mousewheel事件注释掉即可。

    现在鼠标上下滚动很平滑了,也可以快慢滚动了,同理,手机端touch事件也可以根据这个原理改造,需要考虑滑动时间和滑动距离,根据这个来计算滑动偏移距离,手机端效果将后续实现。大家如果有空深入完善下,应该也是可以媲美IScroll的。后续将扩展一些JS防范方便大家使用。

    后续:继续优化中键滚动 

    https://www.cnblogs.com/zhaogaojian/p/10436234.html

  • 相关阅读:
    STM32—LAN8720学习
    STM32F4以太网MAC接口
    分治思想应用题
    网易笔试编程题
    python正则表达式
    【论文笔记】CenterNet: Keypoint Triplets for Object Detection
    【论文笔记】Guided Anchor:Region Proposal by Guided Anchoring
    【论文笔记】SNIP:An Analysis of Scale Invariance in Object Detection
    【论文笔记】FCOS:Fully Convolutional One-Stage Object Detection
    【论文笔记】CenterNet:Objects as Points
  • 原文地址:https://www.cnblogs.com/zhaogaojian/p/10421950.html
Copyright © 2011-2022 走看看