SVG 图标动画留下一个像素间隙

Posted

技术标签:

【中文标题】SVG 图标动画留下一个像素间隙【英文标题】:SVG icon animation leaves a pixel gap 【发布时间】:2017-01-22 17:05:18 【问题描述】:

我正在使用 CSS 制作 SVG 动画,我注意到在我的线条绘制动画中,任何 SVG 矩形(#clipboard-border 和 #clipboard-clip-border)笔划总是会排除左上角的一部分角,这使它成为一个不完整的矩形。

我尝试在 CSS 中调整 stroke-dasharray 和 stroke-dashoffset 测量值,以及调整 SVG 代码中协调的大小和像素,但看起来都不是问题。帮忙?

html,
body 
  width: 100%;
  height: 100%;
  background-color: #CECECE;

div 
  text-align: center;

svg 
  display: inline-block;
  width: 120px;
  margin: 3% auto;
  padding: 0px 100px;

/* --------------------- 
SVG RULES
--------------------- */

/* All grey strokes */

#clipboard-border,
.clipboard-content,
.clipboard-borders,
.mech-pencil-borders 
  fill: none;
  stroke: #4D5152;
  stroke-width: 6;
  stroke-miterlimit: 10;

/* All things white */

#clipboard-paper-fill,
#mech-pencil-eraser-fill 
  fill: #F3F7F6;

/* All things green */

#mech-pencil-point-fill,
#mech-pencil-top-fill 
  fill: #25B686;

/* All things blue */

#clipboard-fill 
  fill: #85D0D3;

/* All things yellow */

#clipboard-clip-fill,
#mech-pencil-grip 
  fill: #FBFBCE;

#clipboard-knob-1,
#clipboard-knob-2,
#clipboard-knob-3,
#mech-pencil-bottom-btn,
#mech-pencil-top-btn 
  stroke-dasharray: 8px;
  stroke-dashoffset: 8px;
  animation: trace .5s ease-out forwards;

/* ---------------------
ANIMATION KEYFRAMES 
--------------------- */

@keyframes trace 
  100% 
    stroke-dashoffset: 0px;
  

@keyframes fill-it 
  100% 
    opacity: 1;
  

@keyframes grow 
  0% 
    transform: scale(0);
  
  30% 
    transform: scale(1.1);
  
  60% 
    transform: scale(.9);
  

/* --------------------- 
SVG ANIMATION: INSIGHT & PLANNING ICON 
--------------------- */

#clipboard-clip-border 
  stroke-dasharray: 180px;
  stroke-dashoffset: 180px;
  animation: trace .2s ease-out forwards;

#clipboard-clip-fill 
  opacity: 0;
  animation: fill-it .2s .2s ease-in-out forwards;

#clipboard-border 
  stroke-dasharray: 640px;
  stroke-dashoffset: 640px;
  animation: trace 1.25s ease-in-out forwards;

#clipboard-fill,
#mech-pencil-point-fill,
#mech-pencil-top-fill 
  opacity: 0;
  animation: fill-it .25s 1.25s ease-in-out forwards;

#clipboard-paper-border 
  stroke-dasharray: 400px;
  stroke-dashoffset: 400px;
  animation: trace 1s ease-out forwards;

#clipboard-paper-fill,
#mech-pencil-eraser-fill,
#mech-pencil-grip 
  opacity: 0;
  animation: fill-it .75s 1s ease-in-out forwards;

#clipboard-content-line-1 
  stroke-dasharray: 30px;
  stroke-dashoffset: 30px;
  animation: trace .5s ease-out forwards;

#clipboard-content-line-7,
#clipboard-clip-detail 
  stroke-dasharray: 52px;
  stroke-dashoffset: 52px;
  animation: trace .5s ease-out forwards;

#clipboard-content-line,
#clipboard-content-line-even,
#mech-pencil-eraser-border 
  stroke-dasharray: 80px;
  stroke-dashoffset: 80px;
  animation: trace .75s ease-out forwards;

#mech-pencil-border-left,
#mech-pencil-border-right 
  stroke-dasharray: 115px;
  stroke-dashoffset: 115px;
  animation: trace .75s ease-out forwards;

#mech-pencil-point-border 
  stroke-dasharray: 60px;
  stroke-dashoffset: 60px;
  animation: trace .5s ease-out forwards;

#mech-pencil-tip,
#mech-pencil-top 
  stroke-dasharray: 10px;
  stroke-dashoffset: 10px;
  animation: trace .4s ease-out forwards;

/* --------------------- 
ANIMATION DELAYS
--------------------- */

#clipboard-knob-1,
#clipboard-knob-2 
  animation-delay: .25s;

#clipboard-clip-detail,
#clipboard-content-line,
#clipboard-content-line-7,
#clipboard-knob-2 
  animation-delay: .5s;

#mech-pencil-bottom-btn,
#mech-pencil-top-btn 
  animation-delay: 1.25s;
<div class="wrapper">

  <!-- INSIGHT & PLANNING ICON -->

  <svg id="insight-planning" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px"   viewBox="0 0 200 200">
    <g class="clipboard">
      <rect id="clipboard-fill" x="15.015" y="11.44"   />
      <rect id="clipboard-paper-fill" x="30.753" y="11.44"   />
      <g class="clipboard-content">
        <line id="clipboard-content-line-even" x1="46.491" y1="68.096" x2="115.738" y2="68.096" />
        <line id="clipboard-content-line" x1="46.491" y1="80.687" x2="115.738" y2="80.687" />
        <line id="clipboard-content-line-even" x1="46.491" y1="93.277" x2="115.738" y2="93.277" />
        <line id="clipboard-content-line" x1="46.491" y1="105.867" x2="115.738" y2="105.867" />
        <line id="clipboard-content-line-even" x1="46.491" y1="118.458" x2="115.738" y2="118.458" />
        <line id="clipboard-content-line-7" x1="46.491" y1="131.048" x2="96.852" y2="131.048" />
        <line id="clipboard-content-line-1" x1="115.738" y1="49.211" x2="90.557" y2="49.211" />
      </g>
      <rect id="clipboard-border" x="15.015" y="11.44"   />
    </g>
    <g class="mech-pencil-fills">
      <rect id="mech-pencil-grip" x="166.099" y="96.425"   />
      <rect id="mech-pencil-top-fill" x="166.099" y="30.325"   />
      <rect id="mech-pencil-eraser-fill" x="166.099" y="11.44"   />
      <polygon id="mech-pencil-point-fill" points="184.985,143.639 184.985,159.376 175.542,168.819 166.099,159.376 166.099,143.639" />
    </g>
    <g class="mech-pencil-borders">
      <line id="mech-pencil-border-left" x1="166.099" y1="143.639" x2="166.099" y2="30.325" />
      <line id="mech-pencil-border-right" x1="184.985" y1="30.325" x2="184.985" y2="145" />
      <rect id="mech-pencil-eraser-border" x="166.099" y="11.44"   />
      <polygon id="mech-pencil-point-border" points="184.985,143.639 184.985,159.376 175.542,168.819 166.099,159.376 166.099,143.639" />
      <line id="mech-pencil-top" x1="175.542" y1="11.44" x2="175.542" y2="1.997" />
      <line id="mech-pencil-tip" x1="175.542" y1="168.819" x2="175.542" y2="175.114" />
      <line id="mech-pencil-bottom-btn" x1="175.542" y1="127.901" x2="175.542" y2="121.605" />
      <line id="mech-pencil-top-btn" x1="175.542" y1="115.31" x2="175.542" y2="109.015" />
    </g>
    <g class="clipboard-clip">
      <rect id="clipboard-clip-fill" x="49.639" y="5.144"   />
    </g>
    <g class="clipboard-borders">
      <polyline id="clipboard-paper-border" points="131.476,11.44 131.476,162.524 30.753,162.524 30.753,11.44" />
      <rect id="clipboard-clip-border" x="49.639" y="5.144"   />
      <line id="clipboard-clip-detail" x1="59.081" y1="17.735" x2="103.148" y2="17.735" />
      <line id="clipboard-knob-1" x1="65.376" y1="178.262" x2="71.672" y2="178.262" />
      <line id="clipboard-knob-2" x1="77.967" y1="178.262" x2="84.262" y2="178.262" />
      <line id="clipboard-knob-3" x1="90.557" y1="178.262" x2="96.852" y2="178.262" />
    </g>
  </svg>
</div>

也发布在Codepen。

【问题讨论】:

【参考方案1】:

只需在 SVG 对象的 CSS 声明中添加 stroke-linecap: square;

svg 
  display: inline-block;
  width: 120px;
  margin: 3% auto;
  padding: 0px 100px;
  stroke-linecap: square;  /* <-- Add this */

示例:

这是一个带有两条路径(打开,未关闭)的 SVG。以“对接”线结尾绘制的路径在上角有一点缺失,但另一条路径(以“方形”线结尾绘制)没有这个问题。

<svg   viewBox="0 0 250 100">
  <path d="M10 10h80v80h-80v-80" style="stroke:#000; stroke-width:10px; fill:none; stroke-linecap: square;"/>
  <text x="50" y="70" text-anchor="middle">Square</text>
  <path d="M160 10h80v80h-80v-80" style="stroke:#000; stroke-width:10px; fill:none; stroke-linecap: butt;"/>
  <text x="200" y="70" text-anchor="middle">Butt</text>
 </svg>

附注我喜欢你的工作,但下次请考虑制作minimal, complete and verifiable example 来说明问题。这样人们就不必费力地阅读大量代码来发现问题所在:-)

【讨论】:

非常感谢您的工作!啊,我下次肯定会这样做,仍然习惯这种事情。

以上是关于SVG 图标动画留下一个像素间隙的主要内容,如果未能解决你的问题,请参考以下文章

具有剪辑路径的元素中的水平(子)像素间隙

svg 图标在高 DPI 上出现像素化

SVG 图像未与周围元素对齐/像素完美(尤其是动画时不和谐!)

汉堡图标:尽管像素对齐,但面包+汉堡的大小相同?

SVG 中相邻的 rect 元素会留下一个微小的间隙

CSS:悬停在 SVG 组区域而不是渲染像素上,指针事件:边界框不能跨浏览器工作。如何解决