angularJs自定义实现侧滑指令

老样纸,先上图:


先上代码:

html模板代码:

<div class="slide-item-wrapper">
    <div class="slide-item" ref="slide">
        <div class="content"
             ref="content">
            <div ng-transclude="content"></div>
        </div>
        <div class="side" ref="side">
            <div ng-transclude="side"></div>
        </div>
    </div>
</div>

指令代码:

/*
*   created by  weishengjian
*   date        20180319
*/

/*示例代码*/

/*

<slide-item>
            <slide-content>
                <ons-list-item>dlasdjalkj</ons-list-item>
            </slide-content>
            <slide-side>
                <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label>
                <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label>
                <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label>
            </slide-side>
        </slide-item>
        <slide-item>
            <slide-content>
                <ons-list-item>dlasdjalkj</ons-list-item>
            </slide-content>
            <slide-side>
                <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label>
                <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label>
                <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label>
            </slide-side>
        </slide-item>
        <slide-item>
            <slide-content>
                <ons-list-item>dlasdjalkj</ons-list-item>
            </slide-content>
            <slide-side>
                <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label>
                <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label>
            </slide-side>
        </slide-item>
        <slide-item>
            <slide-content>
                <ons-list-item>dlasdjalkj</ons-list-item>
            </slide-content>
            <slide-side>
                <label class='side-item' style="background-color: #ff534d"><ons-icon icon="ion-ios-trash" style="color: white"></ons-icon></label>
            </slide-side>
        </slide-item>

*/

app.directive('slideItem', function ($rootScope) {
    return {
        restrict: 'E',
        replace: false,
        templateUrl: 'js/directives/slide-item/slide.item.template.html',
        scope: false,
        transclude: {
            'side': '?slideSide',
            'content': '?slideContent',
        },
        controller: function () {
            !$rootScope.closeAllSlideItem && ($rootScope.closeAllSlideItem = function () {
                var slides = document.getElementsByClassName("slide-item");
                for (var i = 0; i < slides.length; i++) {
                    var slide = slides[i];
                    slide.style.left = 0 + 'px';
                    slide.style['transition'] = 'all 0.4s';
                    slide.currentShow = false;
                }
            });
        },
        link: {
            post: function (scope, element, attrs) {

                var refs = getRefs(element);
                var side = refs.side;
                var slide = refs.slide;
                var content = refs.content;
                var slideWidth = side.offsetWidth;
                side.style.right = -slideWidth + 'px';

                slide._touch = {};
                slide.currentShow = false;

                var touchstart = function (e) {
                    refs = getRefs(element);
                    side = refs.side;
                    slide = refs.slide;
                    content = refs.content;
                    slideWidth = side.offsetWidth;

                    slide._touch.initialized = true;
                    var touch = e.touches[0];
                    slide._touch.startX = touch.pageX;
                    slide._touch.startY = touch.pageY;

                };
                var touchmove = function (e) {

                    if (!slide._touch.initialized) return;
                    var touch = e.touches[0];
                    var deltaX = touch.pageX - slide._touch.startX;
                    var deltaY = touch.pageY - slide._touch.startY;

                    /*如果在纵轴上得偏差大于在横轴上得偏差,则不应该左右滑动*/
                    if (Math.abs(deltaY) > Math.abs(deltaX)) return;

                    var left = slide.currentShow ? -slideWidth : 0;
                    var offsetWidth = Math.max(Math.min(0, left + deltaX), -slideWidth);
                    slide._touch.percent = 1 - Math.abs(offsetWidth) / slideWidth;

                    slide.style['transition'] = 'all 0.2s';
                    slide.style.left = offsetWidth + 'px';
                };
                var touchend = function (e) {
                    $rootScope.closeAllSlideItem();
                    if (!slide._touch.initialized) return;

                    var touch = e.changedTouches[0];
                    var deltaX = touch.pageX - slide._touch.startX;
                    var deltaY = touch.pageY - slide._touch.startY;
                    /*如果在纵轴上得偏差大于在横轴上得偏差,则不应该左右滑动*/
                    if (Math.abs(deltaY) > Math.abs(deltaX)) return;

                    var percent = Math.abs(deltaX) / slideWidth;    //滑动幅度

                    var offsetWidth;

                    if (deltaX > 0) {               //右滑
                        if (percent > 0.2) {       //消失
                            offsetWidth = 0;
                            slide.currentShow = false;
                        } else {
                            offsetWidth = -slideWidth;
                            slide.currentShow = true;
                        }
                    } else {                     //左滑
                        if (percent > 0.2) {       //消失
                            offsetWidth = -slideWidth;
                            slide.currentShow = true;
                        } else {
                            offsetWidth = 0;
                            slide.currentShow = false;
                        }
                    }
                    slide.style.left = offsetWidth + 'px';
                    slide.style['transition'] = 'all 0.4s';
                };

                content.addEventListener('touchstart', touchstart);
                content.addEventListener('touchmove', touchmove);
                content.addEventListener('touchend', touchend);

            }
        }
    }
});


refs函数:

/*
*   在指令中,获取作用域范围内的所有用了ref属性标记的节点,如果ref值相同,通过  getRefs(element).别名   结果是一个数组,如果ref值只有一个,测获取的就是一个对象
*   element:在指令中,$element对象,也就是指令本身对象
*/
function getRefs(element) {
    var refs = ($(element).find("[ref]"));
    var result = {};
    for (var i = 0; i < refs.length; i++) {
        var item = $(refs[i]);
        var refName = item.attr('ref');
        if (!(refName in result)) result[refName] = [];
        result[refName].push(item[0]);
    }
    for (var key in result) {
        if (result[key].length == 1) result[key] = result[key][0];
    }
    return result;
}

这里面是用了jquery的,在使用这个指令之前,记得先引入jquery。

这个指令的核心在于两点,一点是使用了transclude,还有一点是,将一些状态信息保存在dom节点中。

首先是transclude,有slide-side(存放侧滑内容)以及slide-content(主体内容),有一个div.slide-item包裹着这两个div,在滑动的时候,是整个slide-item滑动,如果同学们只想slide-side滑动的话,需要调整一下代码。

还有一个核心点是,将状态信息存到dom节点,我这里信息就是存到dom节点中的,这里最主要的_touch对象就是存在slide-item这个dom对象,因为侧滑的时候是有状态的,当然你在声明指令的时候可以建立一个自己的作用域,scope为true或者一个对象,但是这样的话,slide-content以及slide-side中获取的数据就有可能会不正常,我这里为了完全不影响作用域,就将一些数据存在了dom对象中。


……漏了样式代码:

.slide-item-wrapper {
  width: 100%;
  .slide-item {
    position: relative;
    .side {
      height: 100%;
      position: absolute;
      top: 0px;
      div, slide-side {
        display: inline-block;
        height: 100%;
        .side-item {
          height: 100%;
          display: inline-flex;
          align-items: center;
          justify-content: center;
          width: 64px;
          float: left;
          ons-icon {
            font-size: 32px;
          }
        }
      }
    }
  }
}
这个less代码,可以拿到less在线编译工具编译一下,或者自行转译一下也可以,不是很多
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值