JavaScript進階--拉勾網鼠標移入移出效果

Lorene8383 8年前發布 | 9K 次閱讀 JavaScript開發 JavaScript

JavaScript進階

1024絲毫不減少我敲寫代碼的激情,因為我聞到了代碼的味道。

先上效果圖(gif自己錄制的,有點難看抱歉,工具licecap)

其實也是個偶然的機會,讓我想去研究一下這個效果。主要是由于有個群里的人發了個講解這個效果的鏈接,當時也沒怎么在意,然后過兩天,突然就想起這件事,便去拉勾網一看,哎呦效果不錯,就想去找找那個鏈接看一下。沒想到找了半天沒找到了,沒辦法只能自己研究了。(自己獨立思考的意識還是不夠啊,慚愧!)

思路

------------

  HTML結構
------------
<ul>
    <li>
        <div class="bg">
            <p>JS</p>
        </div>
    </li>
    .....
</ul>

li作為鼠標移入(mouseenter)和鼠標移出(mouseleave)的載體。
div作為動畫執行的載體。

------------
  CSS
------------
div采用absolute定位,通過top、left改變它的位置。
由于div的top、left可能會超出li的大小,所以要設置li的overflow:hidden;

-----------
  JS
-----------
1、采用JS操縱CSS3 transition動畫
2、如何判斷鼠標移入移除的方向</code></pre> 

</div>

鼠標坐標的相關知識

------------------

  MouseEvent對象
------------------
下面介紹幾個MouseEvent中坐標的相關知識:
(clientX, clientY): 以可視區域為參考系的坐標。
(pageX, pageY): 以整個頁面(包括滾動條卷出的區域)為參考系的坐標。
(screenX, screenY): 以你的電腦屏幕為參考系的坐標。

獲取某個元素內部的坐標
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">pointTo</span><span class="hljs-params">(element, e)</span> {</span>
    <span class="hljs-keyword">var</span> elementBox = element.getBoundingClientRect();
    <span class="hljs-keyword">return</span> {
        x: e.clientX - elementBox.left,
        y: e.clientY - elementBox.top
    };
}

計算元素左上角的坐標
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">startPoint</span><span class="hljs-params">(element)</span>{</span>
    <span class="hljs-keyword">var</span> x = <span class="hljs-number">0</span>,y = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">while</span>(element != <span class="hljs-literal">null</span>) {
        x += element.offsetLeft;
        y += element.offsetTop;
        element = element.offsetParent;
    }
    <span class="hljs-keyword">return</span> {
        x: x,
        y: y
    }
}

獲取元素的寬度和高度(不要認為是width和height 新手特別容易犯錯)
offsetHeight與offsetWidth</code></pre> 

</div>

簡單的封裝一下CSS3 transition動畫

/* options參數: obj: 運動的對象 speed: 運動的持續時間(可選) changeStyle: 改變的屬性,這里可能多個,所以采用函數的方式(可選) callback: 回調函數(可選) */
    function animation(options){</span>
        if(!options.obj) {
            return false;
        }
        //設置默認持續時間
        options.speed = options.speed || '.5s';
        options.obj.style.transition = "all " + options.speed + " ease-in-out";

    options.changeStyle.call(options.obj);

    <span class="hljs-keyword">var</span> flag = <span class="hljs-literal">false</span>;
    options.obj.addEventListener(<span class="hljs-string">'transitionend'</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span>{</span>
        <span class="hljs-comment">//這里主要由于transitionend在每個屬性的動畫執行完多會走一遍,所以我們要讓它只執行一次。</span>
        <span class="hljs-keyword">if</span>(!flag) {

            options.callback && options.callback();
        }
    },<span class="hljs-literal">false</span>);
}</code></pre> 

</div>

如何確定方向

這里要用到數學中的正切相關的概念,我自己畫了一張圖,不知道你們能不能看特明白:(奇丑。。。)

--------------------

  得到元素的運動方向
--------------------

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getDirection</span><span class="hljs-params">(element,startPoint,pagePoint)</span>{</span>
    <span class="hljs-keyword">var</span> halfWidth = element.offsetWidth / <span class="hljs-number">2</span>,halfHeight = element.offsetHeight / <span class="hljs-number">2</span>;
    <span class="hljs-comment">//得到中心點</span>
    <span class="hljs-keyword">var</span> center = {
        x: startPoint.x + halfWidth,
        y: startPoint.y + halfHeight
    }
    <span class="hljs-comment">//得到鼠標偏離中心點的距離</span>
    <span class="hljs-keyword">var</span> disX = pagePoint.x - center.x;
    <span class="hljs-keyword">var</span> disY = pagePoint.y - center.y;
    <span class="hljs-keyword">if</span>(disY < <span class="hljs-number">0</span> && <span class="hljs-built_in">Math</span>.abs(disY / disX) >= <span class="hljs-number">1</span>) {
        <span class="hljs-comment">//上方</span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(disY > <span class="hljs-number">0</span> && <span class="hljs-built_in">Math</span>.abs(disY / disX) >= <span class="hljs-number">1</span>) {
        <span class="hljs-comment">//下</span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">2</span>;
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(disX < <span class="hljs-number">0</span> && <span class="hljs-built_in">Math</span>.abs(disY / disX) < <span class="hljs-number">1</span>) {
        <span class="hljs-comment">//左</span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">3</span>;
    }
    <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">//右</span>
        <span class="hljs-keyword">return</span> <span class="hljs-number">4</span>;
    }
}</code></pre> 

</div>

啟動事件的代碼,有注釋

/* options中的參數: 觸發事件的載體: targetElement 執行動畫的載體: animationElement */
    function HoverAction(options) {</span>
        if(!options.targetElement || !options.animationElement) {
            return false;
        }
        this.targetElement = options.targetElement;
        this.animationElement = options.animationElement;
        this.timeId = null;
        this.speed = "0.3s";
    }
    HoverAction.prototype.addEvent = function() {</span>
        //保存this的指向
        var _this = this;
        _this.targetElement.addEventListener('mouseenter',function(e){</span>
            //得到鼠標的坐標
            var point = {
                x: e.pageX,
                y: e.pageY
            }
            console.log(point);
            //獲得方向
            var dir = getDirection(_this.targetElement,startPoint(_this.targetElement),point);
            clearTimeout(_this.timeId);
            //取消過渡動畫(防止重置動畫載體位置時觸發過渡效果)
            _this.animationElement.style.transition = "";
            //得到運動的方向,要確定動畫載體的開始位置
            switch(dir){
                case 1:
                    _this.animationElement.style.top = "-100%";
                    _this.animationElement.style.left = "0";
                    break;
                case 2:
                    _this.animationElement.style.top = "100%";
                    _this.animationElement.style.left = "0";
                    break;
                case 3:
                    _this.animationElement.style.top = "0";
                    _this.animationElement.style.left = "-100%";
                    break;
                case 4:
                    _this.animationElement.style.top = "0";
                    _this.animationElement.style.left = "100%";
                    break;
            }
            //異步執行
            _this.timeId = setTimeout(function(){</span>
                animation({
                    obj: _this.animationElement,
                    speed: _this.speed,
                    changeStyle: function(){</span>
                        this.style.top = "0";
                        this.style.left = "0";
                    }
                });
            },20);
        },false);
        _this.targetElement.addEventListener('mouseleave',function(e){</span>
            var left,top;
            var point = {
                x: e.pageX,
                y: e.pageY
            }
            clearTimeout(_this.timeId);
            _this.animationElement.style.transition = "";
            var dir = getDirection(_this.targetElement,startPoint(_this.targetElement),point);
            switch(dir) {
                case 1:
                    top = '-100%';
                    left = '0';
                    break;
                case 2:
                    top = '100%';
                    left = "0";
                    break;
                case 3:
                    left = "-100%";
                    top = "0";
                    break;
                case 4:
                    left = "100%";
                    top = "0";
                    break;
            }
            _this.timeId = setTimeout(function(){</span>
                animation({
                    obj: _this.animationElement,
                    speed: _this.speed,
                    changeStyle: function(){</span>
                        this.style.top = top;
                        this.style.left = left;
                    }
                });
            },20);
        },false);

}</code></pre> 

</div>

 

 

來自:https://github.com/15751165579/ThinkInCoding/blob/master/文章/JavaScript進階--拉勾網鼠標移入移出效果.md

 

 本文由用戶 Lorene8383 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!