<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>You found Nikaple!</title>
  
  <subtitle>(๑╹◡╹๑)</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://nikaple.com/"/>
  <updated>2018-03-12T06:56:25.438Z</updated>
  <id>http://nikaple.com/</id>
  
  <author>
    <name>Nikaple</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>刺er的作品集</title>
    <link href="http://nikaple.com/20180312/sprspikeup/"/>
    <id>http://nikaple.com/20180312/sprspikeup/</id>
    <published>2018-03-12T04:08:07.000Z</published>
    <updated>2018-03-12T06:56:25.438Z</updated>
    
    <content type="html"><![CDATA[<p>由于众所周知的原因，<a href="https://www.strikinglycom/" title="strikingly" target="_blank" rel="noopener">strikingly</a>服务在国内并不可用，取而代之的是的本地化版<a href="https://www.sxl.cn/" title="上线了" target="_blank" rel="noopener">上线了</a>。这里暂时搬运了一个静态版的网页过来（无法留言/分享，只能看hhh，等有时间了再把请求转发写了吧）</p><ul><li>源地址：<a href="http://sprspikeup.strikingly.com" target="_blank" rel="noopener">http://sprspikeup.strikingly.com</a></li><li>托管地址：<a href="https://nikaple.com/sprspikeup">https://nikaple.com/sprspikeup</a></li></ul><p>大家快去下载刺er的游戏好好享受（<del>被虐</del>）吧！</p>]]></content>
    
    <summary type="html">
    
      
      
        &lt;p&gt;由于众所周知的原因，&lt;a href=&quot;https://www.strikinglycom/&quot; title=&quot;strikingly&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;strikingly&lt;/a&gt;服务在国内并不可用，取而代之的是的本地化版&lt;a hr
      
    
    </summary>
    
    
      <category term="sprspikeup" scheme="http://nikaple.com/tags/sprspikeup/"/>
    
  </entry>
  
  <entry>
    <title>原生JS实现一个Chrome DevTools取色板（下）</title>
    <link href="http://nikaple.com/20171007/color-picker-with-vallina-js-2/"/>
    <id>http://nikaple.com/20171007/color-picker-with-vallina-js-2/</id>
    <published>2017-10-07T12:24:17.000Z</published>
    <updated>2018-03-12T15:34:47.808Z</updated>
    
    <content type="html"><![CDATA[<h3 id="拖拽功能"><a href="#拖拽功能" class="headerlink" title="拖拽功能"></a>拖拽功能</h3><p>上回我们已经构建了基本界面：</p><iframe width="100%" height="400" src="//jsfiddle.net/Nikaple/zhh8qv7x/8/embedded/html,css,result/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><p>终于到<code>JavaScript</code>出场的时候了！首先观察一下我们的组件，滑块的交互方式其实可以看为仅在<code>x</code>轴方向上运动的色盘交互方式。于是我们首先建立一个可拖动对象的类<code>DragContext</code>：<br><a id="more"></a><br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DragContext</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(&#123;</span><br><span class="line">    $context, <span class="comment">// 可以拖动的范围，即色盘以及滑块槽</span></span><br><span class="line">    $dragger, <span class="comment">// 可拖动对象，色盘游标以及滑块</span></span><br><span class="line">    name, <span class="comment">// 用来区分两个滑块</span></span><br><span class="line">    direction <span class="comment">// 用来区分仅x轴还是x,y轴均可拖动</span></span><br><span class="line">  &#125;) &#123;</span><br><span class="line">   <span class="keyword">this</span>.$context = $context;</span><br><span class="line">    <span class="keyword">this</span>.$dragger = $dragger;</span><br><span class="line">    <span class="keyword">this</span>.name = name;</span><br><span class="line">    <span class="keyword">this</span>.direction = direction;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p><p>考虑我们需要实现的效果，可以被拆分为两部分：</p><ul><li>单击父元素，子元素可以瞬间移动到单击的位置；</li><li>单击子元素，可以拖动子元素。</li></ul><p>很自然地，我们需要为父元素添加<code>mousedown</code>, <code>mousemove</code>, <code>mouseup</code>三个事件。在这里由于我们想当用户鼠标在区域外时，只要不松开左键还能继续拖动滑块，便可以将<code>mousemove</code>, <code>mouseup</code>这两个事件绑定在全局的<code>document</code>对象上。当按下鼠标时，将内部变量<code>_isDragging</code>设置为<code>true</code>；松开鼠标时，设置为<code>false</code>。这样便可通过<code>_isDragging</code>来确定元素是否被拖动。当对象正在被拖动时，则执行<code>_setStyles</code>函数为<code>$dragger</code>与<code>$context</code>设置样式。（<code>utils.addHandler(context, event, handler)</code>为<code>target</code>添加回调函数<code>handler</code>的<code>event</code>事件，关于<code>utils</code>对象，可看本文附录）。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DragContext</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(...)&#123;</span><br><span class="line">    ...;</span><br><span class="line">    <span class="keyword">this</span>._isDragging = <span class="literal">false</span>;</span><br><span class="line">    <span class="keyword">this</span>.init();</span><br><span class="line">  &#125;</span><br><span class="line">  init() &#123;</span><br><span class="line">    <span class="keyword">this</span>._addMousedown();</span><br><span class="line">    <span class="keyword">this</span>._addMousemove();</span><br><span class="line">    <span class="keyword">this</span>._addMouseup();</span><br><span class="line">  &#125;</span><br><span class="line">  getName() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">this</span>.name;</span><br><span class="line">  &#125;</span><br><span class="line">  _addMousedown() &#123;</span><br><span class="line">    utils.addHandler(<span class="keyword">this</span>.$context, <span class="string">'mousedown'</span>, (e) =&gt; &#123;</span><br><span class="line">      <span class="comment">// 初始化样式</span></span><br><span class="line">      <span class="keyword">this</span>._setStyles(e);</span><br><span class="line">      <span class="keyword">this</span>._isDragging = <span class="literal">true</span>;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">  _addMousemove() &#123;</span><br><span class="line">    utils.addHandler(<span class="built_in">document</span>, <span class="string">'mousemove'</span>, (e) =&gt; &#123;</span><br><span class="line">      <span class="keyword">if</span> (<span class="keyword">this</span>._isDragging) &#123;</span><br><span class="line">        <span class="keyword">this</span>._setStyles(e);</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line">  _addMouseup() &#123;</span><br><span class="line">    utils.addHandler(<span class="built_in">document</span>, <span class="string">'mouseup'</span>, (e) =&gt; &#123;</span><br><span class="line">      <span class="keyword">this</span>._isDragging = <span class="literal">false</span>;</span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  _setStyles(e) &#123;</span><br><span class="line">    <span class="keyword">this</span>._setDraggerStyles(e);</span><br><span class="line">    <span class="keyword">this</span>._setContextStyles(e);</span><br><span class="line">  &#125;</span><br><span class="line">  _setDraggerStyles(e) &#123;</span><br><span class="line">    <span class="comment">// 设置dragger样式</span></span><br><span class="line">  &#125;</span><br><span class="line">  _setContextStyles(e) &#123;</span><br><span class="line">    <span class="comment">// 设置context样式</span></span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>于是，如何确定当前可拖动元素的偏移量便成了一个很关键的问题，在这里我选择了获取基于当前视图的坐标，也就是<code>e.clientX, e.clientY</code>以及<code>element.getBoundingClientRect()</code>。为此我们需要新的“私有”变量：<code>this._x, this._y, this._rect</code>。为了将可拖动元素限制在一定的范围里，我们可以使用一个工具函数：<code>utils.clamp</code>，将小于最小值时设置为最小值，大于最大值时设置为最大值。</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DragContext</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(&#123;</span><br><span class="line">  ...,</span><br><span class="line">    initX, <span class="comment">// 可选，初始化x坐标</span></span><br><span class="line">    initY <span class="comment">// 可选，初始化y坐标</span></span><br><span class="line">  &#125;)&#123;</span><br><span class="line">    ...;</span><br><span class="line">    <span class="keyword">this</span>._x = initX || <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">this</span>._y = initY || <span class="number">0</span>;</span><br><span class="line">    <span class="keyword">this</span>._rect = <span class="keyword">this</span>.$context.getBoundingClientRect();</span><br><span class="line">  &#125;</span><br><span class="line">  _setDraggerStyles(e) &#123;</span><br><span class="line">    <span class="keyword">this</span>._x = utils.clamp(e.clientX - <span class="keyword">this</span>._rect.left, <span class="number">0</span>, <span class="keyword">this</span>._rect.width);</span><br><span class="line">    <span class="keyword">this</span>._y = utils.clamp(e.clientY - <span class="keyword">this</span>._rect.top, <span class="number">0</span>, <span class="keyword">this</span>._rect.height);</span><br><span class="line">    <span class="keyword">switch</span> (<span class="keyword">this</span>.direction) &#123;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">'horizontal'</span>:</span><br><span class="line">        <span class="keyword">this</span>.$dragger.style.transform = <span class="string">`translate(<span class="subst">$&#123;<span class="keyword">this</span>._x&#125;</span>px, 0)`</span>;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">'vertical'</span>:</span><br><span class="line">        <span class="keyword">this</span>.$dragger.style.transform = <span class="string">`translate(0, <span class="subst">$&#123;<span class="keyword">this</span>._y&#125;</span>px)`</span>;</span><br><span class="line">        <span class="keyword">break</span>;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">'both'</span>:</span><br><span class="line">        <span class="keyword">this</span>.$dragger.style.transform = <span class="string">`translate(<span class="subst">$&#123;<span class="keyword">this</span>._x&#125;</span>px, <span class="subst">$&#123;<span class="keyword">this</span>._y&#125;</span>px)`</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>至此我们可以对目前的组件进行简单的测试了，直接上代码（<code>jsFiddle</code>自动在<code>domready</code>时加载，不用自己套壳了）：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> $palletes = <span class="built_in">Array</span>.prototype.slice.call(<span class="built_in">document</span>.querySelectorAll(<span class="string">'.palette'</span>));</span><br><span class="line"><span class="keyword">const</span> $sliders = <span class="built_in">Array</span>.prototype.slice.call(<span class="built_in">document</span>.querySelectorAll(<span class="string">'.slider'</span>));</span><br><span class="line"><span class="keyword">const</span> $picker = <span class="built_in">document</span>.querySelector(<span class="string">'.color-picker'</span>);</span><br><span class="line"><span class="keyword">const</span> $indicator = <span class="built_in">document</span>.querySelector(<span class="string">'.color-indicator'</span>);</span><br><span class="line"><span class="keyword">const</span> contexts = $palletes.map(<span class="function">(<span class="params">$context</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> name = $context.getAttribute(<span class="string">'name'</span>);</span><br><span class="line">    <span class="keyword">const</span> $dragger = $sliders.filter(<span class="function"><span class="params">element</span> =&gt;</span> element.getAttribute(<span class="string">'name'</span>) === name)[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> DragContext(&#123;</span><br><span class="line">      $context,</span><br><span class="line">      $dragger,</span><br><span class="line">      name,</span><br><span class="line">      direction: <span class="string">'horizontal'</span>,</span><br><span class="line">      initX: <span class="number">120</span></span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> name = $picker.getAttribute(<span class="string">'name'</span>);</span><br><span class="line"><span class="keyword">const</span> context = <span class="keyword">new</span> DragContext(&#123;</span><br><span class="line">  $context: $picker,</span><br><span class="line">  $dragger: $indicator,</span><br><span class="line">  name,</span><br><span class="line">  direction: <span class="string">'both'</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><iframe width="100%" height="400" src="//jsfiddle.net/Nikaple/zhh8qv7x/10/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><h3 id="实现颜色预览"><a href="#实现颜色预览" class="headerlink" title="实现颜色预览"></a>实现颜色预览</h3><p>接下来我们需要通过当前游标的位置，确定当前各个变量的值。为此，我们重写valueOf()函数，为每一项都生成一个[0, 1]区间的值：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DragContext</span> </span>&#123;</span><br><span class="line">  ...</span><br><span class="line">  valueOf() &#123;</span><br><span class="line">    <span class="keyword">switch</span> (<span class="keyword">this</span>.direction) &#123;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">'horizontal'</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.name === <span class="string">'alpha'</span> ?</span><br><span class="line">          <span class="keyword">this</span>._x / <span class="keyword">this</span>._rect.width :</span><br><span class="line">          <span class="number">1</span> - <span class="keyword">this</span>._x / <span class="keyword">this</span>._rect.width;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">'vertical'</span>:</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>._y / <span class="keyword">this</span>._rect.height;</span><br><span class="line">      <span class="keyword">case</span> <span class="string">'both'</span>:</span><br><span class="line">        <span class="keyword">return</span> [<span class="keyword">this</span>._x / <span class="keyword">this</span>._rect.width, <span class="number">1</span> - <span class="keyword">this</span>._y / <span class="keyword">this</span>._rect.height];</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>由于<code>hue</code>的渐变是向左的，所以为了计算实际的<code>hue</code>值比例，应该使用<code>1 - this._x / this._rect.width</code>计算。</p><p>为了更方便地渲染<code>context</code>部分的样式，我们新建一个渲染类来完成这部分的工作：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">DragContext</span> </span>&#123;</span><br><span class="line">  _setContextStyles() &#123;</span><br><span class="line">    StyleRenderer.getInstance().evaluate();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StyleRenderer</span> </span>&#123;</span><br><span class="line">  <span class="keyword">constructor</span>(doms, contexts) &#123;</span><br><span class="line">    <span class="keyword">this</span>.doms = doms;</span><br><span class="line">    <span class="keyword">this</span>.doms.preview = <span class="built_in">document</span>.querySelector(<span class="string">'.preview'</span>);</span><br><span class="line">    <span class="keyword">this</span>.doms.result = &#123;</span><br><span class="line">      hex: <span class="built_in">document</span>.querySelector(<span class="string">'.hex'</span>),</span><br><span class="line">      rgb: <span class="built_in">document</span>.querySelector(<span class="string">'.rgb'</span>),</span><br><span class="line">      hsl: <span class="built_in">document</span>.querySelector(<span class="string">'.hsl'</span>),</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">this</span>.contexts = contexts;</span><br><span class="line">    <span class="keyword">this</span>.evaluate();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  evaluate() &#123;</span><br><span class="line">    <span class="comment">// calculate color values</span></span><br><span class="line">    <span class="built_in">console</span>.log(<span class="keyword">this</span>.doms, <span class="keyword">this</span>.contexts);</span><br><span class="line">    <span class="keyword">this</span>.setStyles();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  setStyles() &#123;</span><br><span class="line">    <span class="comment">// set context styles</span></span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="keyword">static</span> getInstance(doms, contexts) &#123;</span><br><span class="line">    <span class="keyword">if</span> (!<span class="keyword">this</span>.instance) &#123;</span><br><span class="line">      <span class="keyword">this</span>.instance = <span class="keyword">new</span> StyleRenderer(doms, contexts);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">this</span>.instance;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当我们用<code>querySelector</code>获取节点，创建<code>DragContext</code>对象时，就可以将获取到的节点与对象缓存，然后在创建渲染器时传入。<code>StyleRenderer</code>类以单例模式创建，并在构造函数中获取其他未缓存的节点。接着调用<code>evaluate</code>函数确认颜色的值，最后使用<code>setStyles</code>为界面着色。为了缓存<code>dom</code>与<code>DragContext</code>对象，我们需要重写调用代码：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> doms = &#123;&#125;;</span><br><span class="line"><span class="keyword">const</span> dragContexts = [];</span><br><span class="line">kickPicker();</span><br><span class="line">kickSliders();</span><br><span class="line">StyleRenderer.getInstance(doms, dragContexts);</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">kickPicker</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 获取色盘有关节点并缓存</span></span><br><span class="line">  <span class="keyword">const</span> $picker = <span class="built_in">document</span>.querySelector(<span class="string">'.color-picker'</span>);</span><br><span class="line">  <span class="keyword">const</span> $indicator = <span class="built_in">document</span>.querySelector(<span class="string">'.color-indicator'</span>);</span><br><span class="line">  doms.$picker = $picker;</span><br><span class="line">  doms.$indicator = $indicator;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 获取色盘有关对象并缓存</span></span><br><span class="line">  <span class="keyword">const</span> name = $picker.getAttribute(<span class="string">'name'</span>);</span><br><span class="line">  <span class="keyword">const</span> context = <span class="keyword">new</span> DragContext(&#123;</span><br><span class="line">    $context: $picker,</span><br><span class="line">    $dragger: $indicator,</span><br><span class="line">    name,</span><br><span class="line">    direction: <span class="string">'both'</span></span><br><span class="line">  &#125;);</span><br><span class="line">  dragContexts.push(context);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">kickSliders</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="comment">// 获取滑轮有关节点并缓存</span></span><br><span class="line">  <span class="keyword">const</span> $palletes = <span class="built_in">Array</span>.prototype.slice.call(<span class="built_in">document</span>.querySelectorAll(<span class="string">'.palette'</span>));</span><br><span class="line">  <span class="keyword">const</span> $sliders = <span class="built_in">Array</span>.prototype.slice.call(<span class="built_in">document</span>.querySelectorAll(<span class="string">'.slider'</span>));</span><br><span class="line">  doms.$palletes = $palletes;</span><br><span class="line">  doms.$sliders = $sliders;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 获取滑轮有关对象并缓存</span></span><br><span class="line">  <span class="keyword">const</span> contexts = $palletes.map(<span class="function">(<span class="params">$context</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="keyword">const</span> name = $context.getAttribute(<span class="string">'name'</span>);</span><br><span class="line">    <span class="keyword">const</span> $dragger = $sliders.filter(<span class="function"><span class="params">element</span> =&gt;</span> element.getAttribute(<span class="string">'name'</span>) === name)[<span class="number">0</span>];</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> DragContext(&#123;</span><br><span class="line">      $context,</span><br><span class="line">      $dragger,</span><br><span class="line">      name,</span><br><span class="line">      direction: <span class="string">'horizontal'</span>,</span><br><span class="line">      initX: <span class="number">120</span></span><br><span class="line">    &#125;);</span><br><span class="line">  &#125;);</span><br><span class="line">  dragContexts.push(...contexts);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这时，从刚刚的<code>console.log</code>中可以看出，我们获取的节点与创建的<code>DragContext</code>都被缓存并传入<code>StyleRenderer</code>的实例中了。接下来可以着手实现<code>evaluate</code>函数了：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StyleRenderer</span> </span>&#123;</span><br><span class="line">  ...</span><br><span class="line">  evaluate() &#123;</span><br><span class="line">    <span class="comment">// 色相滑块获取色相</span></span><br><span class="line">    <span class="keyword">this</span>.hue = <span class="number">360</span> * <span class="keyword">this</span>.contexts</span><br><span class="line">      .filter(<span class="function"><span class="params">context</span> =&gt;</span> context.getName() === <span class="string">'hue'</span>)[<span class="number">0</span>]</span><br><span class="line">      .valueOf();</span><br><span class="line">    <span class="comment">// 色盘横纵坐标获取饱和度与明度，注意的颜色是基于hsb而不是hsl的</span></span><br><span class="line">    [<span class="keyword">this</span>.saturation, <span class="keyword">this</span>.brightness] = <span class="keyword">this</span>.contexts</span><br><span class="line">      .filter(<span class="function"><span class="params">context</span> =&gt;</span> context.getName() === <span class="string">'color'</span>)[<span class="number">0</span>]</span><br><span class="line">      .valueOf();</span><br><span class="line">    <span class="comment">// 透明度滑块获取透明度</span></span><br><span class="line">    <span class="keyword">this</span>.alpha = <span class="keyword">this</span>.contexts</span><br><span class="line">      .filter(<span class="function"><span class="params">context</span> =&gt;</span> context.getName() === <span class="string">'alpha'</span>)[<span class="number">0</span>]</span><br><span class="line">      .valueOf();</span><br><span class="line">    <span class="comment">// 用三个工具函数分别计算出hsl, rgb, hex的值</span></span><br><span class="line">    <span class="keyword">this</span>.hsl = utils.color.hsb2hsl(<span class="keyword">this</span>.hue, <span class="keyword">this</span>.saturation, <span class="keyword">this</span>.brightness);</span><br><span class="line">    <span class="keyword">this</span>.rgb = utils.color.hsl2rgb(<span class="keyword">this</span>.hsl.h, <span class="keyword">this</span>.hsl.s, <span class="keyword">this</span>.hsl.l);</span><br><span class="line">    <span class="keyword">this</span>.hex = utils.color.rgb2hex(<span class="keyword">this</span>.rgb.r, <span class="keyword">this</span>.rgb.g, <span class="keyword">this</span>.rgb.b);</span><br><span class="line">    <span class="comment">// 当hex值可以简化时，将#66ccff简化为#6cf</span></span><br><span class="line">    <span class="keyword">const</span> simplifyHex = <span class="regexp">/^#(?:([da-f])1)&#123;3&#125;$/</span>.exec(<span class="keyword">this</span>.hex);</span><br><span class="line">    <span class="keyword">if</span> (simplifyHex !== <span class="literal">null</span>) &#123;</span><br><span class="line">      <span class="keyword">this</span>.hex = <span class="string">`#<span class="subst">$&#123;<span class="keyword">this</span>.hex[<span class="number">1</span>]&#125;</span><span class="subst">$&#123;<span class="keyword">this</span>.hex[<span class="number">3</span>]&#125;</span><span class="subst">$&#123;<span class="keyword">this</span>.hex[<span class="number">5</span>]&#125;</span>`</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">this</span>.setStyles();</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>当我们的<code>DragContext</code>类拥有了<code>valueOf</code>函数之后，获取颜色各个分量的值就是一个函数调用的事，接着就轮到<code>setStyles</code>了，有了它，我们就能完成<code>90%</code>了！</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StyleRenderer</span> </span>&#123;</span><br><span class="line">  ...</span><br><span class="line">  setStyles() &#123;</span><br><span class="line">    <span class="comment">// set context styles</span></span><br><span class="line">    <span class="keyword">const</span> round = <span class="built_in">Math</span>.round;</span><br><span class="line">    <span class="keyword">const</span> rgbValues = <span class="string">`<span class="subst">$&#123;round(<span class="keyword">this</span>.rgb.r * <span class="number">255</span>)&#125;</span>, <span class="subst">$&#123;round(<span class="keyword">this</span>.rgb.g * <span class="number">255</span>)&#125;</span>, <span class="subst">$&#123;round(<span class="keyword">this</span>.rgb.b * <span class="number">255</span>)&#125;</span>`</span>;</span><br><span class="line">    <span class="keyword">const</span> alphaValue = utils.trimZero(<span class="keyword">this</span>.alpha.toFixed(<span class="number">2</span>));</span><br><span class="line">    <span class="keyword">const</span> hslaColor = <span class="string">`hsla(<span class="subst">$&#123;round(<span class="keyword">this</span>.hsl.h % <span class="number">360</span>)&#125;</span>, <span class="subst">$&#123;round(<span class="keyword">this</span>.hsl.s * <span class="number">100</span>)&#125;</span>%, <span class="subst">$&#123;round(<span class="keyword">this</span>.hsl.l * <span class="number">100</span>)&#125;</span>%, <span class="subst">$&#123;alphaValue&#125;</span>)`</span>;</span><br><span class="line">    <span class="keyword">const</span> rgbColor = <span class="string">`rgb(<span class="subst">$&#123;rgbValues&#125;</span>)`</span>;</span><br><span class="line">    <span class="keyword">const</span> rgbaColor = <span class="string">`rgba(<span class="subst">$&#123;rgbValues&#125;</span>, <span class="subst">$&#123;alphaValue&#125;</span>)`</span></span><br><span class="line">    <span class="comment">// 如果用图片或者再加一个div来代替棋盘背景的话，这里的代码会好很多</span></span><br><span class="line">    <span class="keyword">this</span>.doms.preview.style.background =</span><br><span class="line">      <span class="string">`linear-gradient(<span class="subst">$&#123;hslaColor&#125;</span>, <span class="subst">$&#123;hslaColor&#125;</span>) 0 0 / cover,</span></span><br><span class="line"><span class="string">      linear-gradient(45deg, rgba(0,0,0,0.25) 25%, transparent 0, transparent 75%, rgba(0,0,0,0.25) 0) 0 0 / 12px 12px,</span></span><br><span class="line"><span class="string">      linear-gradient(45deg, rgba(0,0,0,0.25) 25%, transparent 0, transparent 75%, rgba(0,0,0,0.25) 0) 6px 6px / 12px 12px`</span>;</span><br><span class="line">    <span class="keyword">this</span>.doms.$palletes</span><br><span class="line">      .filter(<span class="function"><span class="params">element</span> =&gt;</span> element.getAttribute(<span class="string">'name'</span>) === <span class="string">'alpha'</span>)[<span class="number">0</span>]</span><br><span class="line">      .style.background =</span><br><span class="line">        <span class="string">`linear-gradient(to right, rgba(0,0,0,0), <span class="subst">$&#123;rgbColor&#125;</span>) 0 0 / cover,</span></span><br><span class="line"><span class="string">        linear-gradient(45deg, rgba(0,0,0,0.25) 25%, transparent 0, transparent 75%, rgba(0,0,0,0.25) 0) 0 0 / 12px 12px,</span></span><br><span class="line"><span class="string">        linear-gradient(45deg, rgba(0,0,0,0.25) 25%, transparent 0, transparent 75%, rgba(0,0,0,0.25) 0) 6px 6px / 12px 12px`</span>;</span><br><span class="line">    <span class="keyword">this</span>.doms.$picker.style.backgroundColor = <span class="string">`hsl(<span class="subst">$&#123;<span class="keyword">this</span>.hue&#125;</span>, 100%, 50%)`</span>;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// results</span></span><br><span class="line">    <span class="keyword">this</span>.doms.result.hex.innerHTML = <span class="keyword">this</span>.hex;</span><br><span class="line">    <span class="keyword">this</span>.doms.result.rgb.innerHTML = <span class="string">`rgba(<span class="subst">$&#123;round(<span class="keyword">this</span>.rgb.r * <span class="number">255</span>)&#125;</span>, <span class="subst">$&#123;round(<span class="keyword">this</span>.rgb.g * <span class="number">255</span>)&#125;</span>, <span class="subst">$&#123;round(<span class="keyword">this</span>.rgb.b * <span class="number">255</span>)&#125;</span>, <span class="subst">$&#123;utils.trimZero(<span class="keyword">this</span>.alpha.toFixed(<span class="number">2</span>))&#125;</span>)`</span>;</span><br><span class="line">    <span class="keyword">this</span>.doms.result.hsl.innerHTML = hslaColor;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>为了让我们的取色板更像取色板，当然要让它派上用场啦！不如就把那个白了一整个教程的<code>Change my color pls</code>的颜色改掉吧！为此，我们需要把<code>div.target</code>的节点也加入到我们<code>StyleRenderer</code>的实例中；更进一步，调色板一般是默认隐藏的，为此，我们可以修改<code>div.wrapper</code>的样式，并在鼠标点击时<code>toggle</code>它的<code>active</code>类：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.wrapper</span> &#123;</span><br><span class="line">  <span class="attribute">user-select</span>: none;</span><br><span class="line">  <span class="attribute">transition</span>: all ease-in-out <span class="number">0.2s</span>;</span><br><span class="line">  <span class="attribute">transform-origin</span>: <span class="number">50%</span> <span class="number">100%</span>;</span><br><span class="line">  <span class="attribute">transform</span>: <span class="built_in">scale</span>(0.8) <span class="built_in">rotate3d</span>(0, 1, 0, 90deg);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.wrapper</span><span class="selector-class">.active</span> &#123;</span><br><span class="line">  <span class="attribute">transform</span>: <span class="built_in">scale</span>(1) <span class="built_in">rotate3d</span>(0, 1, 0, 0);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> doms = &#123;&#125;;</span><br><span class="line"><span class="keyword">const</span> dragContexts = [];</span><br><span class="line">kickTarget();</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">kickTarget</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> $target = <span class="built_in">document</span>.querySelector(<span class="string">'.target'</span>);</span><br><span class="line">  doms.$target = $target;</span><br><span class="line">  <span class="keyword">const</span> $colorPickerComponent = <span class="built_in">document</span>.querySelector(<span class="string">'.wrapper'</span>);</span><br><span class="line">  utils.addHandler($target, <span class="string">'click'</span>, (e) =&gt; &#123;</span><br><span class="line">    $colorPickerComponent.classList.toggle(<span class="string">'active'</span>);</span><br><span class="line">  &#125;);</span><br><span class="line">  <span class="comment">// 在第一次点开取色板时再初始化</span></span><br><span class="line">  utils.addHandler($colorPickerComponent, <span class="string">'transitionend'</span>, <span class="function"><span class="keyword">function</span> <span class="title">handler</span>(<span class="params"></span>)</span>&#123;</span><br><span class="line">    kickPicker();</span><br><span class="line">    kickSliders();</span><br><span class="line">    StyleRenderer.getInstance(doms, dragContexts);</span><br><span class="line">    utils.removeHandler($colorPickerComponent, <span class="string">'transitionend'</span>, handler);</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">kickPicker</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  ...</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">kickSliders</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">  ...</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>接着，在<code>StyleRenderer</code>中渲染文字颜色：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">StyleRenderer</span> </span>&#123;</span><br><span class="line">  setStyles() &#123;</span><br><span class="line">    ...</span><br><span class="line">    <span class="comment">// target</span></span><br><span class="line">    <span class="keyword">this</span>.doms.$target.style.color = hslaColor;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>由于我们默认为字体颜色为白色，并且有<code>StyleRenderer</code>为我们设置背景，现在可以将<code>div.preview</code>中与<code>div.alpha</code>中的背景颜色改回来了：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.preview</span> &#123;</span><br><span class="line">  <span class="attribute">background</span>: white;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.alpha</span> &#123;</span><br><span class="line">   <span class="attribute">background</span>:</span><br><span class="line">     <span class="built_in">linear-gradient</span>(to right, rgba(0,0,0,0), <span class="built_in">rgba</span>(255,255,255,1)) <span class="number">0</span> <span class="number">0</span> / cover,</span><br><span class="line">     <span class="built_in">linear-gradient</span>(45deg, rgba(0,0,0,.25) <span class="number">25%</span>, transparent <span class="number">0</span>, transparent <span class="number">75%</span>, <span class="built_in">rgba</span>(0,0,0,.25) <span class="number">0</span>) <span class="number">0</span> <span class="number">0</span> / <span class="number">12px</span> <span class="number">12px</span>,</span><br><span class="line">     <span class="built_in">linear-gradient</span>(45deg, rgba(0,0,0,.25) <span class="number">25%</span>, transparent <span class="number">0</span>, transparent <span class="number">75%</span>, <span class="built_in">rgba</span>(0,0,0,.25) <span class="number">0</span>) <span class="number">6px</span> <span class="number">6px</span> / <span class="number">12px</span> <span class="number">12px</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><iframe width="100%" height="400" src="//jsfiddle.net/Nikaple/zhh8qv7x/12/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><h3 id="后记"><a href="#后记" class="headerlink" title="后记"></a>后记</h3><p>在<code>Firefox</code>里测试的时候才发现，<code>max-content</code>这个值的兼容性有点令人捉急… 于是还是加个<code>fallback</code>吧…</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.target</span> &#123;</span><br><span class="line">  <span class="attribute">width</span>: <span class="number">240px</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>（完）</p><h3 id="附录"><a href="#附录" class="headerlink" title="附录"></a>附录</h3><h5 id="Utils对象"><a href="#Utils对象" class="headerlink" title="Utils对象"></a>Utils对象</h5><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> utils = &#123;</span><br><span class="line">  <span class="comment">// 事件绑定</span></span><br><span class="line">  addHandler(target, event, handler) &#123;</span><br><span class="line">    <span class="keyword">if</span> (target.addEventListener) &#123;</span><br><span class="line">      target.addEventListener(event, handler, <span class="literal">false</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (target.attachEvent) &#123;</span><br><span class="line">      target.attachEvent(<span class="string">'on'</span> + event, handler);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      target[<span class="string">'on'</span> + event] = handler;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 事件解绑</span></span><br><span class="line">  removeHandler(target, event, handler) &#123;</span><br><span class="line">    <span class="keyword">if</span> (target.removeEventListener) &#123;</span><br><span class="line">      target.removeEventListener(event, handler, <span class="literal">false</span>);</span><br><span class="line">    &#125; <span class="keyword">else</span> <span class="keyword">if</span> (target.detachEvent) &#123;</span><br><span class="line">      target.detachEvent(<span class="string">'on'</span> + event, handler);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      target[<span class="string">'on'</span> + event] = <span class="literal">null</span>;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 坐标锁定</span></span><br><span class="line">  clamp(val, min, max) &#123;</span><br><span class="line">    <span class="keyword">return</span> val &lt; min ? min : (val &gt; max ? max : val);</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 判断是否为数组</span></span><br><span class="line">  isArray(arrayLike) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="built_in">Object</span>.prototype.toString.call(arrayLike) === <span class="string">'[object Array]'</span>;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="comment">// 数字末尾除0</span></span><br><span class="line">  trimZero(str) &#123;</span><br><span class="line">    <span class="keyword">return</span> str.replace(<span class="regexp">/.?0*$/</span>, <span class="string">''</span>);</span><br><span class="line">  &#125;,</span><br><span class="line">  color: &#123;</span><br><span class="line">    <span class="comment">// https://gist.github.com/NV/522734</span></span><br><span class="line">    <span class="comment">// hsb颜色转为hsl颜色</span></span><br><span class="line">    hsb2hsl(h, s, b) &#123;</span><br><span class="line">      <span class="keyword">var</span> hsl = &#123;</span><br><span class="line">        h: h</span><br><span class="line">      &#125;;</span><br><span class="line">      hsl.l = (<span class="number">2</span> - s) * b;</span><br><span class="line">      hsl.s = s * b;</span><br><span class="line">      <span class="keyword">if</span> (hsl.l &lt;= <span class="number">1</span> &amp;&amp; hsl.l &gt; <span class="number">0</span>) &#123;</span><br><span class="line">        hsl.s /= hsl.l;</span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        hsl.s = hsl.s / (<span class="number">2</span> - hsl.l) || <span class="number">0</span>;</span><br><span class="line">      &#125;</span><br><span class="line">      hsl.l /= <span class="number">2</span>;</span><br><span class="line">      <span class="keyword">if</span> (hsl.s &gt; <span class="number">1</span>) &#123;</span><br><span class="line">        hsl.s = <span class="number">1</span>;</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> hsl;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">/**</span></span><br><span class="line"><span class="comment">     * Converts an HSL color value to RGB. Conversion formula</span></span><br><span class="line"><span class="comment">     * adapted from http://en.wikipedia.org/wiki/HSL_color_space.</span></span><br><span class="line"><span class="comment">     * Assumes s and l are contained in the set [0, 1] and h is</span></span><br><span class="line"><span class="comment">     * contained in the set [0, 360], returns r, g, and b in the</span></span><br><span class="line"><span class="comment">     * set [0, 255].</span></span><br><span class="line"><span class="comment">     *</span></span><br><span class="line"><span class="comment">     * @param   &#123;number&#125;  h       The hue</span></span><br><span class="line"><span class="comment">     * @param   &#123;number&#125;  s       The saturation</span></span><br><span class="line"><span class="comment">     * @param   &#123;number&#125;  l       The lightness</span></span><br><span class="line"><span class="comment">     * @return  &#123;Array&#125;           The RGB representation</span></span><br><span class="line"><span class="comment">     */</span></span><br><span class="line">    <span class="comment">// hsl颜色转为rgb颜色</span></span><br><span class="line">    hsl2rgb(h, s, l) &#123;</span><br><span class="line">      h = h / <span class="number">360</span>;</span><br><span class="line">      <span class="keyword">var</span> r, g, b;</span><br><span class="line">      <span class="keyword">if</span> (s == <span class="number">0</span>) &#123;</span><br><span class="line">        r = g = b = l; <span class="comment">// achromatic</span></span><br><span class="line">      &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">        <span class="keyword">var</span> hue2rgb = <span class="function"><span class="keyword">function</span> <span class="title">hue2rgb</span>(<span class="params">p, q, t</span>) </span>&#123;</span><br><span class="line">          <span class="keyword">if</span> (t &lt; <span class="number">0</span>) t += <span class="number">1</span>;</span><br><span class="line">          <span class="keyword">if</span> (t &gt; <span class="number">1</span>) t -= <span class="number">1</span>;</span><br><span class="line">          <span class="keyword">if</span> (t &lt; <span class="number">1</span> / <span class="number">6</span>) <span class="keyword">return</span> p + (q - p) * <span class="number">6</span> * t;</span><br><span class="line">          <span class="keyword">if</span> (t &lt; <span class="number">1</span> / <span class="number">2</span>) <span class="keyword">return</span> q;</span><br><span class="line">          <span class="keyword">if</span> (t &lt; <span class="number">2</span> / <span class="number">3</span>) <span class="keyword">return</span> p + (q - p) * (<span class="number">2</span> / <span class="number">3</span> - t) * <span class="number">6</span>;</span><br><span class="line">          <span class="keyword">return</span> p;</span><br><span class="line">        &#125;</span><br><span class="line">        <span class="keyword">var</span> q = l &lt; <span class="number">0.5</span> ? l * (<span class="number">1</span> + s) : l + s - l * s;</span><br><span class="line">        <span class="keyword">var</span> p = <span class="number">2</span> * l - q;</span><br><span class="line">        r = hue2rgb(p, q, h + <span class="number">1</span> / <span class="number">3</span>);</span><br><span class="line">        g = hue2rgb(p, q, h);</span><br><span class="line">        b = hue2rgb(p, q, h - <span class="number">1</span> / <span class="number">3</span>);</span><br><span class="line">      &#125;</span><br><span class="line">      <span class="keyword">return</span> &#123;r, g, b&#125;;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="comment">// rgb颜色转为hex颜色</span></span><br><span class="line">    rgb2hex(r, g, b) &#123;</span><br><span class="line">      <span class="keyword">return</span> <span class="string">"#"</span> + (<span class="number">16777216</span> | (b * <span class="number">255</span>) | ((g * <span class="number">255</span>) &lt;&lt; <span class="number">8</span>) | ((r * <span class="number">255</span>) &lt;&lt; <span class="number">16</span>)).toString(<span class="number">16</span>).slice(<span class="number">1</span>);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;拖拽功能&quot;&gt;&lt;a href=&quot;#拖拽功能&quot; class=&quot;headerlink&quot; title=&quot;拖拽功能&quot;&gt;&lt;/a&gt;拖拽功能&lt;/h3&gt;&lt;p&gt;上回我们已经构建了基本界面：&lt;/p&gt;
&lt;iframe width=&quot;100%&quot; height=&quot;400&quot; src=&quot;//jsfiddle.net/Nikaple/zhh8qv7x/8/embedded/html,css,result/&quot; allowfullscreen=&quot;allowfullscreen&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;终于到&lt;code&gt;JavaScript&lt;/code&gt;出场的时候了！首先观察一下我们的组件，滑块的交互方式其实可以看为仅在&lt;code&gt;x&lt;/code&gt;轴方向上运动的色盘交互方式。于是我们首先建立一个可拖动对象的类&lt;code&gt;DragContext&lt;/code&gt;：&lt;br&gt;
    
    </summary>
    
    
      <category term="前端" scheme="http://nikaple.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
      <category term="JavaScript" scheme="http://nikaple.com/tags/JavaScript/"/>
    
      <category term="Color-picker" scheme="http://nikaple.com/tags/Color-picker/"/>
    
  </entry>
  
  <entry>
    <title>原生JS实现一个Chrome DevTools取色板（上）</title>
    <link href="http://nikaple.com/20171003/color-picker-with-vallina-js-1/"/>
    <id>http://nikaple.com/20171003/color-picker-with-vallina-js-1/</id>
    <published>2017-10-03T13:33:41.000Z</published>
    <updated>2021-03-22T13:07:08.751Z</updated>
    
    <content type="html"><![CDATA[<p>使用 Chrome DevTools 做开发的同学应该都知道，Chrome 开发工具中的取色板简直是网页设计时神一般的存在，不仅可以实时预览页面样式，配合插件还可以直接保存到本地，可谓 debug 一把手。今天就来试试用原生 JS 还原一个取色板吧！DevTools 取色板预览：</p><a id="more"></a><p><img src="//iwbte-nikaple-edition-1255674901.cos.ap-guangzhou.myqcloud.com/qiniu/17-7-27/16835144.jpg" alt="preview" style="display: block; margin: 0 auto;"></p><p>图中不仅包含了取色、调节色相、调节透明度、颜色预览等基本功能外，还可以使用三种方式：<code>HEX</code>, <code>RGBA</code>, <code>HSLA</code>输出颜色代码。此外，取色板还包括了一个屏幕取色器（JS 无法实现），以及一个下方的自定义色板的功能（暂未实现）。本文将会实现的效果如图：</p><p><img src="//iwbte-nikaple-edition-1255674901.cos.ap-guangzhou.myqcloud.com/qiniu/17-7-27/86474705.jpg" alt="preview" style="display: block; margin: 0 auto;"></p><h3 id="静态页面搭建"><a href="#静态页面搭建" class="headerlink" title="静态页面搭建"></a>静态页面搭建</h3><h4 id="原型实现"><a href="#原型实现" class="headerlink" title="原型实现"></a>原型实现</h4><p>这次我们采用基本的浮动布局，首先搭建基本的<code>HTML</code>骨架，这部分较为简单：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"wrapper"</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"color-picker"</span> <span class="attr">name</span>=<span class="string">"color"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"color-indicator"</span> <span class="attr">name</span>=<span class="string">"color"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"preview"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"hue palette"</span> <span class="attr">name</span>=<span class="string">"hue"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"slider"</span> <span class="attr">name</span>=<span class="string">"hue"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"alpha palette"</span> <span class="attr">name</span>=<span class="string">"alpha"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"slider"</span> <span class="attr">name</span>=<span class="string">"alpha"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h5</span> <span class="attr">class</span>=<span class="string">"hex result"</span>&gt;</span>#fff<span class="tag">&lt;/<span class="name">h5</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h5</span> <span class="attr">class</span>=<span class="string">"rgb result"</span>&gt;</span>rgba(255, 255, 255, 1)<span class="tag">&lt;/<span class="name">h5</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">h5</span> <span class="attr">class</span>=<span class="string">"hsl result"</span>&gt;</span>hsla(0, 0%, 100%, 1)<span class="tag">&lt;/<span class="name">h5</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"target"</span>&gt;</span>Change my color pls!<span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br></pre></td></tr></table></figure><p>其中，<code>div.color-indicator</code>为色盘上的游标，两个<code>div.slider</code>为色相、透明度控件上的滑块。为了布局方便，这里不考虑响应性全部采用<code>px</code>为单位布局，代码如下：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><span class="line">@<span class="keyword">import</span> url(https://fonts.googleapis.com/css?family=Quicksand);</span><br><span class="line"></span><br><span class="line"><span class="selector-tag">html</span>,</span><br><span class="line"><span class="selector-tag">body</span> &#123;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">box-sizing</span>: border-box;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-tag">body</span> &#123;</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="number">#333</span>;</span><br><span class="line">    <span class="attribute">font-family</span>: <span class="string">"Quicksand"</span>, sans-serif;</span><br><span class="line">    <span class="attribute">padding-top</span>: <span class="number">100px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.wrapper</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: white;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">0</span> auto;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">265px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">3px</span>;</span><br><span class="line">    <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#666</span>;</span><br><span class="line">    <span class="attribute">cursor</span>: default;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.color-picker</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">120px</span>;</span><br><span class="line">    <span class="attribute">margin-bottom</span>: <span class="number">15px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: inherit;</span><br><span class="line">    <span class="attribute">background</span>: darkred;</span><br><span class="line">    <span class="attribute">overflow</span>: hidden;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.preview</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: darkgreen;</span><br><span class="line">    <span class="attribute">float</span>: left;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">32px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">32px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">50%</span>;</span><br><span class="line">    <span class="attribute">margin-left</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">border</span>: <span class="number">1px</span> solid <span class="number">#eee</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.palette</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: darkblue;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">120px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">margin-left</span>: <span class="number">60px</span>;</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">1px</span>;</span><br><span class="line">    <span class="attribute">margin-bottom</span>: <span class="number">10px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.result</span> &#123;</span><br><span class="line">    <span class="attribute">color</span>: <span class="number">#aaa</span>;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">line-height</span>: <span class="number">2</span>;</span><br><span class="line">    <span class="attribute">text-align</span>: center;</span><br><span class="line">    <span class="attribute">cursor</span>: text;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.target</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: max-content;</span><br><span class="line">    <span class="attribute">margin</span>: <span class="number">0</span> auto;</span><br><span class="line">    <span class="attribute">padding-top</span>: <span class="number">10px</span>;</span><br><span class="line">    <span class="attribute">color</span>: white;</span><br><span class="line">    <span class="attribute">font-size</span>: <span class="number">24px</span>;</span><br><span class="line">    <span class="attribute">cursor</span>: pointer;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>由于等会要给<code>div.target</code>绑定点击事件触发取色板，这里将该元素的宽度设置为<del><code>max-content</code></del>（← 兼容性不好，使用时一定要加<code>fallback</code>），可以将宽度由<code>100%</code>缩减为文字部分的实际宽度。到这一步之后效果如下：</p><iframe width="100%" height="400" src="//jsfiddle.net/Nikaple/zhh8qv7x/6/embedded/html,css,result/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><h4 id="样式加工"><a href="#样式加工" class="headerlink" title="样式加工"></a>样式加工</h4><p>接下来便是将取色板上的 CSS 样式由易到难逐个击破的时间。</p><ol><li><p>色板底部小三角</p><p> 使用伪元素完成。为了使小三角能与父元素有相同的背景颜色与边框，这里并没有采用<code>border-radius</code>模拟三角形，而是使用<code>background: linear-gradient()</code>。另外，使用绝对定位时应该为父元素设置<code>position: relative</code>属性。</p> <figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.wrapper</span> &#123;</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.wrapper</span><span class="selector-pseudo">::after</span> &#123;</span><br><span class="line">    <span class="attribute">content</span>: <span class="string">""</span>;</span><br><span class="line">    <span class="attribute">position</span>: absolute;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">10px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">10px</span>;</span><br><span class="line">    <span class="attribute">top</span>: <span class="number">260px</span>;</span><br><span class="line">    <span class="attribute">left</span>: <span class="number">94px</span>;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(135deg, transparent 50%, white 50%);</span><br><span class="line">    <span class="attribute">border-width</span>: <span class="number">1px</span> <span class="number">1px</span> <span class="number">0</span> <span class="number">0</span> inherit solid;</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">rotate</span>(45deg);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>色相滑块</p><p> 也是使用<code>linear-gradient</code>，为了颜色的连贯性必须多加几个色标。</p> <figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.hue</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(</span><br><span class="line">        to left,</span><br><span class="line">        hsl(0, 100%, 50%) <span class="number">0%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(30, 100%, 50%) <span class="number">8.33%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(60, 100%, 50%) <span class="number">16.67%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(90, 100%, 50%) <span class="number">25%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(120, 100%, 50%) <span class="number">33.33%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(150, 100%, 50%) <span class="number">41.67%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(180, 100%, 50%) <span class="number">50%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(210, 100%, 50%) <span class="number">58.33%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(240, 100%, 50%) <span class="number">66.67%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(270, 100%, 50%) <span class="number">75%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(300, 100%, 50%) <span class="number">83.33%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(330, 100%, 50%) <span class="number">91.67%</span>,</span><br><span class="line">        <span class="built_in">hsl</span>(0, 100%, 50%) <span class="number">100%</span></span><br><span class="line">    );</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><p>取色板渐变</p><p> 取色板渐变由三个部分组成：</p><ul><li>明度渐变： <code>linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 1))</code></li><li>饱和度渐变：<code>linear-gradient(to left, rgba(0, 0, 0, 0), rgba(255, 255, 255, 1))</code></li><li><p>底色：<code>background-color</code></p><p>将这三个背景叠加在一起，便形成了我们的取色盘。当我们需要改变色盘的颜色时，只需改变<code>background-color</code>的色相即可。</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.color-picker</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(to bottom, rgba(0, 0, 0, 0), <span class="built_in">rgba</span>(0, 0, 0, 1)), <span class="built_in">linear-gradient</span>(to</span><br><span class="line">                left, rgba(0, 0, 0, 0), <span class="built_in">rgba</span>(255, 255, 255, 1));</span><br><span class="line">    <span class="attribute">background-color</span>: red;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li></ul></li><li><p>透明度滑块及预览颜色</p><p> 棋盘图现在已经成为了公认的表示透明区域的方法了。它也可以通过渐变来实现，只不过需要利用斜向 45° 的（0, 25, 75, 100）四个色标的渐变将矩形切割成两个三角形加上中间的六边形。棋盘图的画法在《CSS 揭秘》一书中有较为详细的解读，这里不做赘述：</p> <figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.alpha</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(to right, rgba(0, 0, 0, 0), <span class="built_in">rgba</span>(0, 0, 255, 1)) <span class="number">0</span> <span class="number">0</span> / cover, <span class="built_in">linear-gradient</span>(</span><br><span class="line">                45deg,</span><br><span class="line">                rgba(0, 0, 0, 0.25) <span class="number">25%</span>,</span><br><span class="line">                transparent <span class="number">0</span>,</span><br><span class="line">                transparent <span class="number">75%</span>,</span><br><span class="line">                <span class="built_in">rgba</span>(0, 0, 0, 0.25) <span class="number">0</span></span><br><span class="line">            ) <span class="number">0</span> <span class="number">0</span> / <span class="number">12px</span> <span class="number">12px</span>,</span><br><span class="line">        <span class="built_in">linear-gradient</span>(</span><br><span class="line">                45deg,</span><br><span class="line">                rgba(0, 0, 0, 0.25) <span class="number">25%</span>,</span><br><span class="line">                transparent <span class="number">0</span>,</span><br><span class="line">                transparent <span class="number">75%</span>,</span><br><span class="line">                <span class="built_in">rgba</span>(0, 0, 0, 0.25) <span class="number">0</span></span><br><span class="line">            ) <span class="number">6px</span> <span class="number">6px</span> / <span class="number">12px</span> <span class="number">12px</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="selector-class">.preview</span> &#123;</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">linear-gradient</span>(</span><br><span class="line">                45deg,</span><br><span class="line">                rgba(0, 0, 0, 0.25) <span class="number">25%</span>,</span><br><span class="line">                transparent <span class="number">0</span>,</span><br><span class="line">                transparent <span class="number">75%</span>,</span><br><span class="line">                <span class="built_in">rgba</span>(0, 0, 0, 0.25) <span class="number">0</span></span><br><span class="line">            ) <span class="number">0</span> <span class="number">0</span> / <span class="number">12px</span> <span class="number">12px</span>, <span class="built_in">linear-gradient</span>(</span><br><span class="line">                45deg,</span><br><span class="line">                rgba(0, 0, 0, 0.25) <span class="number">25%</span>,</span><br><span class="line">                transparent <span class="number">0</span>,</span><br><span class="line">                transparent <span class="number">75%</span>,</span><br><span class="line">                <span class="built_in">rgba</span>(0, 0, 0, 0.25) <span class="number">0</span></span><br><span class="line">            ) <span class="number">6px</span> <span class="number">6px</span> / <span class="number">12px</span> <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">background-color</span>: <span class="built_in">rgba</span>(255, 0, 0, 0.5);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p> 透明度滑块与预览颜色不同的地方在于，透明度滑块的棋盘图上面还需要加一层当前颜色的渐变，而预览颜色区域只需要加上一个背景即可。预览：</p></li></ol><iframe width="100%" height="400" src="//jsfiddle.net/Nikaple/zhh8qv7x/7/embedded/html,css,result/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><h4 id="交互设计"><a href="#交互设计" class="headerlink" title="交互设计"></a>交互设计</h4><p>由于省略了<code>HEX</code>, <code>RGB</code>, <code>HSL</code>的切换按钮，这里的交互一共只有 3 个：色盘、色相滑块、透明度滑块。</p><p>首先我们为色盘游标增加一点基本样式：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.color-indicator</span> &#123;</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">    <span class="attribute">left</span>: -<span class="number">6px</span>;</span><br><span class="line">    <span class="attribute">top</span>: -<span class="number">6px</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">12px</span>;</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">translate</span>(-6px, -6px);</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">50%</span>;</span><br><span class="line">    <span class="attribute">border</span>: <span class="number">1px</span> solid white;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>这里为了让色盘游标移动的中心位于圆心，加上了<code>relative</code>以及<code>left</code>、<code>top</code>属性，接着再用<code>translate</code>将它移至屏幕外；接着，定义滑块的公共样式：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.slider</span> &#123;</span><br><span class="line">    <span class="attribute">position</span>: relative;</span><br><span class="line">    <span class="attribute">left</span>: -<span class="number">8px</span>;</span><br><span class="line">    <span class="attribute">top</span>: -<span class="number">2px</span>;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">16px</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">16px</span>;</span><br><span class="line">    <span class="attribute">border-radius</span>: <span class="number">50%</span>;</span><br><span class="line">    <span class="attribute">transform</span>: <span class="built_in">translateX</span>(120px);</span><br><span class="line">    <span class="attribute">background</span>: <span class="built_in">rgb</span>(248, 248, 248);</span><br><span class="line">    <span class="attribute">filter</span>: <span class="built_in">drop-shadow</span>(2px 2px 3px rgba(0, 0, 0, 0.2));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>由于初始滑块位置在右侧，这里直接使用<code>translateX(120px)</code>将两个滑块均移动<code>120px</code>靠近右侧，并且也用<code>left</code>与<code>top</code>对槽内相对位置进行定位。这里利用<code>border-radius</code>将滑块变换为圆形之后，就不能使用<code>box-shadow</code>对其进行描边了（<code>box-shadow</code>产生的阴影只能为矩形）。这里使用了<code>filter</code>中的<code>drop-shadow</code>滤镜属性，目前仅<code>IE</code>不支持。</p><p>到这里界面部分就结束啦，交互逻辑请看下期！</p><iframe width="100%" height="400" src="//jsfiddle.net/Nikaple/zhh8qv7x/8/embedded/html,css,result/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;使用 Chrome DevTools 做开发的同学应该都知道，Chrome 开发工具中的取色板简直是网页设计时神一般的存在，不仅可以实时预览页面样式，配合插件还可以直接保存到本地，可谓 debug 一把手。今天就来试试用原生 JS 还原一个取色板吧！DevTools 取色板预览：&lt;/p&gt;
    
    </summary>
    
    
      <category term="前端" scheme="http://nikaple.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
      <category term="JavaScript" scheme="http://nikaple.com/tags/JavaScript/"/>
    
      <category term="Color-picker" scheme="http://nikaple.com/tags/Color-picker/"/>
    
  </entry>
  
  <entry>
    <title>纯CSS实现Youtube视频播放按钮动画</title>
    <link href="http://nikaple.com/20170618/youtube-play-icon-with-pure-css/"/>
    <id>http://nikaple.com/20170618/youtube-play-icon-with-pure-css/</id>
    <published>2017-06-18T11:28:02.000Z</published>
    <updated>2021-03-22T13:07:08.779Z</updated>
    
    <content type="html"><![CDATA[<p>前两天在 Youtube 上看视频时，无意间发现视频播放器的播放暂停切换按钮动画十分流畅，于是就想试着用 CSS 仿制一下，先上效果图：</p><p><img src="//iwbte-nikaple-edition-1255674901.cos.ap-guangzhou.myqcloud.com/qiniu/17-7-26/89316020.jpg" alt="preview" style="display: block; margin: 0 auto;"></p><p>等等，暂停按钮可以用<code>border-left</code>与<code>border-right</code>实现，播放的<a href="https://css-tricks.com/examples/ShapesOfCSS/" target="_blank" rel="noopener">三角形</a>也可以用边框实现，这岂不是骗小孩子的把戏？于是乎没几分钟，我们就可以写出这么一个实现：</p><a id="more"></a><iframe width="100%" height="300" src="//jsfiddle.net/Nikaple/3585q1dd/3/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><p>可是致命的缺陷是，由于暂停按钮中间缝隙的关系，我们必须对<code>width</code>元素进行动画处理，这直接导致<code>border-width</code>的动画无法按照我们设想的方式工作。于是乎，换个方向考虑，只能使用伪元素或者再添加一个<code>div</code>元素将两个边框分别实现了。</p><p>在这里为了布局方便，能够使用<code>flex</code>布局，使用两个<code>div</code>来实现，实际也可以只用一个<code>div</code>配合伪元素以及普通定位方式来获得更好的兼容性。</p><p>首先用两个<code>div</code>的边框模拟出暂停按钮的两个大长棍：</p><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">head</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">style</span>&gt;</span><span class="undefined"></span></span><br><span class="line"><span class="undefined">        body &#123;</span></span><br><span class="line"><span class="undefined">            background-color: #333;</span></span><br><span class="line"><span class="undefined">        &#125;</span></span><br><span class="line"><span class="undefined">        .wrapper &#123;</span></span><br><span class="line"><span class="undefined">            display: flex;</span></span><br><span class="line"><span class="undefined">            justify-content: space-between;</span></span><br><span class="line"><span class="undefined">            align-items: center;</span></span><br><span class="line"><span class="undefined">            margin: 32px;</span></span><br><span class="line"><span class="undefined">            width: 32px;</span></span><br><span class="line"><span class="undefined">            height: 32px;</span></span><br><span class="line"><span class="undefined">        &#125;</span></span><br><span class="line"><span class="undefined">        .box &#123;</span></span><br><span class="line"><span class="undefined">            width: 0;</span></span><br><span class="line"><span class="undefined">            height: 24px;</span></span><br><span class="line"><span class="undefined">            border-left: 8px solid white;</span></span><br><span class="line"><span class="undefined">        &#125;</span></span><br><span class="line"><span class="undefined">        .left &#123;</span></span><br><span class="line"><span class="undefined">            margin-left: 6px;</span></span><br><span class="line"><span class="undefined">        &#125;</span></span><br><span class="line"><span class="undefined"></span></span><br><span class="line"><span class="undefined">        .right &#123;</span></span><br><span class="line"><span class="undefined">            margin-right: 6px;</span></span><br><span class="line"><span class="undefined">        &#125;</span></span><br><span class="line"><span class="undefined">    </span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">head</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;<span class="name">body</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"wrapper"</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"box left"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">        <span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">"box right"</span>&gt;</span><span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span><br><span class="line"><span class="tag">&lt;/<span class="name">body</span>&gt;</span></span><br></pre></td></tr></table></figure><p>然后为外层<code>div</code>添加一个<code>click</code>事件，在<code>click</code>事件触发时<code>toggle</code>两个子<code>div</code>元素的<code>active</code>类：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">$div = <span class="built_in">document</span>.querySelector(<span class="string">".wrapper"</span>);</span><br><span class="line">$div.addEventListener(<span class="string">"click"</span>, () =&gt; &#123;</span><br><span class="line">    [...$div.children].forEach(<span class="function">(<span class="params">element</span>) =&gt;</span> &#123;</span><br><span class="line">        element.classList.toggle(<span class="string">"active"</span>);</span><br><span class="line">    &#125;);</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>接下来我们就得定义这两根大棒在<code>active</code>状态下的属性了：左边的大棒在<code>active</code>状态下变换为梯形，右边的大棒在<code>active</code>状态下变换为三角形，且梯形的腰与三角形的两条边要在同一条直线上。这就要求<code>border-left-width</code>与<code>border-top-width</code>的比值一定，即可以使用公共的<code>border-width</code>系列属性。在这里为了让上下边框也能受到<code>transition</code>属性的影响，在<code>.box</code>中也要定义初始值。</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.box</span> &#123;</span><br><span class="line">    <span class="attribute">width</span>: <span class="number">0</span>;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">24px</span>;</span><br><span class="line">    <span class="attribute">transition</span>: all <span class="number">0.2s</span>;</span><br><span class="line">    <span class="attribute">border-left</span>: <span class="number">8px</span> solid white;</span><br><span class="line">    <span class="attribute">border-top</span>: <span class="number">0</span> solid transparent;</span><br><span class="line">    <span class="attribute">border-bottom</span>: <span class="number">0</span> solid transparent;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.box</span><span class="selector-class">.active</span> &#123;</span><br><span class="line">    <span class="attribute">border-top</span>: <span class="number">6px</span> solid transparent;</span><br><span class="line">    <span class="attribute">border-bottom</span>: <span class="number">6px</span> solid transparent;</span><br><span class="line">    <span class="attribute">border-left</span>: <span class="number">10px</span> solid white;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>为了使右边的大棒在<code>active</code>状态下缩小为三角形，需要将其高度设置为<code>0</code>；为了使左边的大棒缩小为梯形，需要将其高度设置为短边的长度，即<code>24px/2 = 12px</code>：</p><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-class">.right</span><span class="selector-class">.active</span> &#123;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="selector-class">.left</span><span class="selector-class">.active</span> &#123;</span><br><span class="line">    <span class="attribute">height</span>: <span class="number">12px</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>到这里这个简单的 CSS 动画就完成啦，完成效果：</p><iframe width="100%" height="300" src="//jsfiddle.net/Nikaple/4dodckc5/3/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe><p>当然，如果要完全不使用<code>JavaScript</code>，则可以使用<code>input</code>复选框与<code>label</code>标签的<code>:active</code>伪类以及<code>::before</code>、<code>::after</code>伪元素来实现，只不过语义性会有一定的缺失。并且，由于没有<code>flexbox</code>黑科技的支持，居中定位会变得麻烦一点。</p><iframe width="100%" height="300" src="//jsfiddle.net/Nikaple/4dodckc5/4/embedded/" allowfullscreen="allowfullscreen" frameborder="0"></iframe>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;前两天在 Youtube 上看视频时，无意间发现视频播放器的播放暂停切换按钮动画十分流畅，于是就想试着用 CSS 仿制一下，先上效果图：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;//iwbte-nikaple-edition-1255674901.cos.ap-guangzhou.myqcloud.com/qiniu/17-7-26/89316020.jpg&quot; alt=&quot;preview&quot; style=&quot;display: block; margin: 0 auto;&quot;&gt;&lt;/p&gt;
&lt;p&gt;等等，暂停按钮可以用&lt;code&gt;border-left&lt;/code&gt;与&lt;code&gt;border-right&lt;/code&gt;实现，播放的&lt;a href=&quot;https://css-tricks.com/examples/ShapesOfCSS/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;三角形&lt;/a&gt;也可以用边框实现，这岂不是骗小孩子的把戏？于是乎没几分钟，我们就可以写出这么一个实现：&lt;/p&gt;
    
    </summary>
    
    
      <category term="前端" scheme="http://nikaple.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
      <category term="CSS" scheme="http://nikaple.com/tags/CSS/"/>
    
      <category term="Youtube" scheme="http://nikaple.com/tags/Youtube/"/>
    
      <category term="Animation" scheme="http://nikaple.com/tags/Animation/"/>
    
  </entry>
  
</feed>
