JavaScript进阶--拉勾网鼠标移入移出效果

Lorene8383 8年前
   <h3><strong>JavaScript进阶</strong></h3>    <p>1024丝毫不减少我敲写代码的激情,因为我闻到了代码的味道。</p>    <p><strong>先上效果图(gif自己录制的,有点难看抱歉,工具licecap)</strong></p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/1881c88969ea64b359fb074a8d55d52a.gif"></p>    <p>其实也是个偶然的机会,让我想去研究一下这个效果。主要是由于有个群里的人发了个讲解这个效果的链接,当时也没怎么在意,然后过两天,突然就想起这件事,便去拉勾网一看,哎呦效果不错,就想去找找那个链接看一下。没想到找了半天没找到了,没办法只能自己研究了。(自己独立思考的意识还是不够啊,惭愧!)</p>    <p><strong>思路</strong></p>    <div contenteditable="false" tabindex="-1">     <pre data-widget="codeSnippet">  <code class="language-javascript hljs">------------        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>     <img src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==">    <span style="background:url(http://www.open-open.com/lib/ckeditor/plugins/widget/images/handle.png) rgba(220, 220, 220, 0.498039); display:block; left:0px; top:-15px"><img height="15" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15"></span>   </div>    <p><strong>鼠标坐标的相关知识</strong></p>    <div contenteditable="false" tabindex="-1">     <pre data-widget="codeSnippet">  <code class="language-javascript hljs">------------------        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>     <img src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==">    <span style="background:url(http://www.open-open.com/lib/ckeditor/plugins/widget/images/handle.png) rgba(220, 220, 220, 0.498039); display:block; left:0px; top:-15px"><img height="15" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15"></span>   </div>    <p><strong>简单的封装一下CSS3 transition动画</strong></p>    <div contenteditable="false" tabindex="-1">     <pre data-widget="codeSnippet">  <code class="language-javascript hljs"><span class="hljs-comment">/* options参数: obj: 运动的对象 speed: 运动的持续时间(可选) changeStyle: 改变的属性,这里可能多个,所以采用函数的方式(可选) callback: 回调函数(可选) */</span>      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">animation</span><span class="hljs-params">(options)</span>{</span>          <span class="hljs-keyword">if</span>(!options.obj) {              <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;          }          <span class="hljs-comment">//设置默认持续时间</span>          options.speed = options.speed || <span class="hljs-string">'.5s'</span>;          options.obj.style.transition = <span class="hljs-string">"all "</span> + options.speed + <span class="hljs-string">" ease-in-out"</span>;            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>     <img src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==">    <span style="background:url(http://www.open-open.com/lib/ckeditor/plugins/widget/images/handle.png) rgba(220, 220, 220, 0.498039); display:block; left:0px; top:-15px"><img height="15" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15"></span>   </div>    <p><strong>如何确定方向</strong></p>    <p>这里要用到数学中的正切相关的概念,我自己画了一张图,不知道你们能不能看特明白:(奇丑。。。)</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/c0b7484a5ef7c46c114d535374fa4856.jpg"></p>    <div contenteditable="false" tabindex="-1">     <pre data-widget="codeSnippet">  <code class="language-javascript hljs">--------------------        得到元素的运动方向      --------------------        <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>     <img src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==">    <span style="background:url(http://www.open-open.com/lib/ckeditor/plugins/widget/images/handle.png) rgba(220, 220, 220, 0.498039); display:block; left:0px; top:-15px"><img height="15" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15"></span>   </div>    <p><strong>启动事件的代码,有注释</strong></p>    <div contenteditable="false" tabindex="-1">     <pre data-widget="codeSnippet">  <code class="language-javascript hljs"><span class="hljs-comment">/* options中的参数: 触发事件的载体: targetElement 执行动画的载体: animationElement */</span>      <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">HoverAction</span><span class="hljs-params">(options)</span> {</span>          <span class="hljs-keyword">if</span>(!options.targetElement || !options.animationElement) {              <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;          }          <span class="hljs-keyword">this</span>.targetElement = options.targetElement;          <span class="hljs-keyword">this</span>.animationElement = options.animationElement;          <span class="hljs-keyword">this</span>.timeId = <span class="hljs-literal">null</span>;          <span class="hljs-keyword">this</span>.speed = <span class="hljs-string">"0.3s"</span>;      }      HoverAction.prototype.addEvent = <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span> {</span>          <span class="hljs-comment">//保存this的指向</span>          <span class="hljs-keyword">var</span> _this = <span class="hljs-keyword">this</span>;          _this.targetElement.addEventListener(<span class="hljs-string">'mouseenter'</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(e)</span>{</span>              <span class="hljs-comment">//得到鼠标的坐标</span>              <span class="hljs-keyword">var</span> point = {                  x: e.pageX,                  y: e.pageY              }              console.log(point);              <span class="hljs-comment">//获得方向</span>              <span class="hljs-keyword">var</span> dir = getDirection(_this.targetElement,startPoint(_this.targetElement),point);              clearTimeout(_this.timeId);              <span class="hljs-comment">//取消过渡动画(防止重置动画载体位置时触发过渡效果)</span>              _this.animationElement.style.transition = <span class="hljs-string">""</span>;              <span class="hljs-comment">//得到运动的方向,要确定动画载体的开始位置</span>              <span class="hljs-keyword">switch</span>(dir){                  <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:                      _this.animationElement.style.top = <span class="hljs-string">"-100%"</span>;                      _this.animationElement.style.left = <span class="hljs-string">"0"</span>;                      <span class="hljs-keyword">break</span>;                  <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:                      _this.animationElement.style.top = <span class="hljs-string">"100%"</span>;                      _this.animationElement.style.left = <span class="hljs-string">"0"</span>;                      <span class="hljs-keyword">break</span>;                  <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:                      _this.animationElement.style.top = <span class="hljs-string">"0"</span>;                      _this.animationElement.style.left = <span class="hljs-string">"-100%"</span>;                      <span class="hljs-keyword">break</span>;                  <span class="hljs-keyword">case</span> <span class="hljs-number">4</span>:                      _this.animationElement.style.top = <span class="hljs-string">"0"</span>;                      _this.animationElement.style.left = <span class="hljs-string">"100%"</span>;                      <span class="hljs-keyword">break</span>;              }              <span class="hljs-comment">//异步执行</span>              _this.timeId = setTimeout(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span>{</span>                  animation({                      obj: _this.animationElement,                      speed: _this.speed,                      changeStyle: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span>{</span>                          <span class="hljs-keyword">this</span>.style.top = <span class="hljs-string">"0"</span>;                          <span class="hljs-keyword">this</span>.style.left = <span class="hljs-string">"0"</span>;                      }                  });              },<span class="hljs-number">20</span>);          },<span class="hljs-literal">false</span>);          _this.targetElement.addEventListener(<span class="hljs-string">'mouseleave'</span>,<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">(e)</span>{</span>              <span class="hljs-keyword">var</span> left,top;              <span class="hljs-keyword">var</span> point = {                  x: e.pageX,                  y: e.pageY              }              clearTimeout(_this.timeId);              _this.animationElement.style.transition = <span class="hljs-string">""</span>;              <span class="hljs-keyword">var</span> dir = getDirection(_this.targetElement,startPoint(_this.targetElement),point);              <span class="hljs-keyword">switch</span>(dir) {                  <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:                      top = <span class="hljs-string">'-100%'</span>;                      left = <span class="hljs-string">'0'</span>;                      <span class="hljs-keyword">break</span>;                  <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:                      top = <span class="hljs-string">'100%'</span>;                      left = <span class="hljs-string">"0"</span>;                      <span class="hljs-keyword">break</span>;                  <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:                      left = <span class="hljs-string">"-100%"</span>;                      top = <span class="hljs-string">"0"</span>;                      <span class="hljs-keyword">break</span>;                  <span class="hljs-keyword">case</span> <span class="hljs-number">4</span>:                      left = <span class="hljs-string">"100%"</span>;                      top = <span class="hljs-string">"0"</span>;                      <span class="hljs-keyword">break</span>;              }              _this.timeId = setTimeout(<span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span>{</span>                  animation({                      obj: _this.animationElement,                      speed: _this.speed,                      changeStyle: <span class="hljs-function"><span class="hljs-keyword">function</span><span class="hljs-params">()</span>{</span>                          <span class="hljs-keyword">this</span>.style.top = top;                          <span class="hljs-keyword">this</span>.style.left = left;                      }                  });              },<span class="hljs-number">20</span>);          },<span class="hljs-literal">false</span>);        }</code></pre>     <img src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==">    <span style="background:url(http://www.open-open.com/lib/ckeditor/plugins/widget/images/handle.png) rgba(220, 220, 220, 0.498039); display:block; left:0px; top:-15px"><img height="15" src="data:image/gif;base64,R0lGODlhAQABAPABAP///wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==" title="点击并拖拽以移动" width="15"></span>   </div>    <p> </p>    <p> </p>    <p>来自:https://github.com/15751165579/ThinkInCoding/blob/master/文章/JavaScript进阶--拉勾网鼠标移入移出效果.md</p>    <p> </p>