解決iSlider的一些問題(滑動組件)

一:先解決一下該插件在PC端(針對數據內容是html)滑動性能的問題,反正就是在PC端滑動體驗很差。javascript

針對這個問題我先去監測了組件裏滑動時evt.pageX , this.startX(鼠標按下去的)這兩個的值變化,結果發現那個evt.pageX滑動到必定的距離後跟實際鼠標位置的值不匹配,在進一步才發現他提早執行了endHandler以致this.onMoving 設置成了false,而後後面就不會滑動了。html

仔細看了下代碼,組件給PC端執行了以下代碼前端

 !device.hasTouch && outer.addEventListener('mouseout', this);//組件本來的mouseout事件代碼

注:這裏的this是該組件引用類型的實例,也就是該組件對象,這裏傳這個的用意請看,這裏不在陳述java

http://www.kuqin.com/shuoit/20131123/336495.htmlnode

其實仔細想一想,就是綁定mouseout事件處理程序的緣由,由於元素內部的html元素會觸發mouseout將其冒泡到給事件綁定事件處理程序的容器。web

而後我嘗試阻止事件冒泡或採用事件捕獲,(阻止事件捕獲也沒用),發現其實都沒什麼用,而後就查找資料看到了這篇文章瀏覽器

http://blog.csdn.net/ltx851201/article/details/6800553app

而後我將其組件添加了以下代碼dom

    /****對iSlider插件的PC版html滑動性能問題修復,主要是mouseout觸發的endHandler事件處理程序的影響*
    *解決方法在觸發mouseout事件處理程序是:先監測目標對象是不是綁定此事件處理程序對象自己(由於鼠標在目標對象的內部的元素移動時觸發的mouseout會冒泡到目標對象)*
    ***輔助函數START********/
    iSliderPrototype.contains = function (parentNode, childNode) {
        if (parentNode.contains) {
            return parentNode != childNode && parentNode.contains(childNode);
        } else {
            return !!(parentNode.compareDocumentPosition(childNode) & 16);
        }
    }


    //這個函數用於檢查一個對象是否被包含在咱們的觸發對象裏面。
    //下面就是咱們的重點了,我封裝了一個用於檢查鼠標是否真正從外部移入或者移出對象的函數checkHover(e,target),這個函數須要傳入當前的事件對象和目標對象。
    iSliderPrototype.checkHover = function (e, target) {
        var e = e || window.event;
        if (e.type == "mouseover") {
            return !this.contains(target, e.relatedTarget || e.fromElement) && !((e.relatedTarget || e.fromElement) === target);
        } else {
            return !this.contains(target, e.relatedTarget || e.toElement) && !((e.relatedTarget || e.toElement) === target);
        }
    }
    /********對iSliderJS的PC版html滑動性能問題修復***輔助函數END******/

  

而後將以前綁定mouseout事件處理程序的代碼改寫成了這樣ide

            if (!device.hasTouch) {
                var that = this;
                outer.addEventListener('mouseout', function (e) {                    
                    that.checkHover(e, outer) &&that.endHandler(e); 
                },false);
            }

至此該組件在PC端滑動體驗好多了

 

二:解決滑動屏幕裏的每一個小容器點擊問題

該組件在滑動的時候會觸發click事件,影響交互。

解決方法

1.先給該組件添加一個回調函數,在實例化的時候傳參進去,而後在原組件綁定事件以前先執行此回調函數,前端調用的時候這樣調用,以下

參數裏的beforeBindHandler就是咱們傳入的回調函數,此函數的做用是綁定mousedown和mouseup事件處理程序,
若是鼠標按下和放開間隔事件小於300毫秒則執行點擊程序,不然不執行。
var isGoDetail = true;
			    var _iSliderWrapper = document.getElementById('iSlider-wrapper');

			    S = new iSlider({
			        dom: _iSliderWrapper,
			        data: list,
			        isLooping: 1,
			        isOverspread: 1,
			        onslide: function () {
			            isGoDetail = false;
			        },
			        onslidechanged: function (index) {
			            isGoDetail = true;
			            updateRange(itemWidth * index, index);
			        },
			        beforeBindHandler: function () {
			            var startTime;
			            var up = function (ev) {
			                if ((new Date().getTime() - startTime <= 300) && isGoDetail) {
			                    var ev = ev || window.event;
			                    var target = ev.target || ev.srcElement;

			                    //closest裏面的選擇器元素就是須要點擊觸發的每個容器,能夠事先在裏面附加一些咱們須要的信息
			                    var item = target.closest("div.div_newsWidthImg,.div_news_item");

			                    if (item.getAttribute("data-screenNum")) {
			                        var screenNum = item.getAttribute("data-screenNum");
			                        var order = item.getAttribute("data-newsOrder");
			                        window.location.href = "newsDetail.html?pScreenNum=" + screenNum + "&pNewsOrder=" + order+"&newsType=" + $(".div_nav_more>p").text();;
			                    }
			                } else {
			                    isGoDetail = true;
			                }
			            }

			            var down = function (e) {
			                startTime = new Date().getTime();
			            }

			            _iSliderWrapper.addEventListener("mousedown", down);
			            _iSliderWrapper.addEventListener("mouseup", up);
			        },
			        oninitialized: function () {
			            args["pScreenNum"] && this.slideTo(Number(args["pScreenNum"]) - 1);
			        }
			    });

  



注意closest方法用原生JavaScript替代jQuery的closest方法,目前只有現代瀏覽器自己就支持。若是須要兼容ie9(目前我測試至少在ie9及以上是OK的),則加入如下代碼
//原文出處1:http://www.codesec.net/view/206139.html 2:https://plainjs.com/javascript/traversing/match-element-selector-52/
/*******匹配DOM上級元素,實現closest()方法,因爲在現代瀏覽器中內置支持了這些元素,所以咱們爲了得到更好的性能,
咱們建議在原生對象上進行拓展,就能夠像下面這樣直接使用:*********/
this.Element && function (ElementPrototype) {
    ElementPrototype.matches = ElementPrototype.matches ||
    ElementPrototype.matchesSelector ||
    ElementPrototype.webkitMatchesSelector ||
    ElementPrototype.msMatchesSelector ||
    function (selector) {
        var node = this, nodes = (node.parentNode || node.document).querySelectorAll(selector), i = -1;
        while (nodes[++i] && nodes[i] != node);
        return !!nodes[i];
    }
}(Element.prototype);

this.Element && function (ElementPrototype) { ElementPrototype.closest = ElementPrototype.closest || function (selector) { var el = this; while (el.matches && !el.matches(selector)) el = el.parentNode; return el.matches ? el : null; 
} }(Element.prototype);

  

三.ie9滑動兼容性問題和樣式問題

將_animateFuncs方法改寫以下

  iSlider._animateFuncs = {
        normal: (function () {
            function normal(dom, axis, scale, i, offset) {
                // iSlider.setStyle(dom, 'transform', 'translateZ(0) translate' + axis + '(' + (offset + scale * (i - 1)) + 'px)');
                if (iSlider.TRANSITION_END_EVENT) {
                    iSlider.setStyle(dom, 'transform', 'translateZ(0) translate' + axis + '(' + (offset + scale * (i - 1)) + 'px)');
                } else {
                    dom.style.left = (offset + scale * (i - 1)) + 'px';
                }
            }

            normal.effect = iSlider.styleProp('transform');
            return normal;
        })()
    };

  改寫後的組件代碼連接:http://files.cnblogs.com/files/qiny-easyui/iSlider.js

相關文章
相關標籤/搜索