html - 为笔画 dashoffset 设置动画时使用过多 CPU 资源使用 SVG 路径创建的边框

标签 html css performance svg

我有一个使用 SVG 路径创建的非常简单的边框。如果我尝试用它来制作动画,它是 stroke-dashoffset属性,Chrome 的 GPU 使用率高达 15%。鉴于我正在为单个笔画设置动画,这似乎有些过分。
为什么会这样?如果预期会使用此资源,是否有其他替代方法可以在保持较低资源使用率的同时创建相同的效果?
演示:将光标放在框的顶部以动画 svg 路径(并检查 chrome 的 GPU 使用情况)

.outer {
  border-radius: 5px;
  position: relative; 
  width: 300px;
  height: 300px;
  border: 1px solid gray;
}

.border-path {
  width: calc(100% + 10px);
  height: calc(100% + 10px);
  position: absolute;
  top: -5px;
  left: -5px;
  stroke-width: 5;
  stroke-dasharray: 8;
  stroke-dashoffset: 1000;
  stroke-opacity: 0;
  fill: transparent;
}

.outer:hover > .border-path {
  stroke: red;
  stroke-opacity: 1;
  animation: draw 30s linear infinite forwards;
}

@keyframes draw {
  to {
    stroke-dashoffset: 0;
  }
}
<div class="outer">
  <svg class="border-path">
    <rect x="0" y="0" width="100%" height="100%" />
  </svg>
</div>

最佳答案

一个 CSS only 解决方案,我将只为不透明度和转换设置动画。应该使用更少的资源。不如 SVG 完美,但作为替代品已经足够好了:

.outer {
  border-radius: 5px;
  position: relative;
  width: 300px;
  height: 300px;
  border: 1px solid gray;
  margin:15px;
  clip-path:inset(-5px);
}
.outer::before,
.outer::after,
.outer span::before,
.outer span::after {
  content:"";
  position: absolute;
  opacity:0;
  transition:1s;
  animation: 1s linear infinite;
}
.outer::before,
.outer::after {
  height: 2px;
  left: -5px;
  width: calc(100% + 20px);
  background: repeating-linear-gradient(to right, red 0 5px, transparent 0 10px);
  animation-name:drawX;
}

.outer span::before,
.outer span::after {
  width: 2px;
  top: -5px;
  height: calc(100% + 20px);
  background: repeating-linear-gradient(to bottom, red 0 5px, transparent 0 10px);
  animation-name:drawY;
}

.outer::before {top: -5px; animation-direction:reverse;}
.outer span::before {right: -5px; animation-direction:reverse;}

.outer::after { bottom: -5px;}
.outer span::after { left: -5px;}

.outer:hover::before,
.outer:hover::after,
.outer:hover span::before,
.outer:hover span::after {
  opacity:1;
}

@keyframes drawX {
  to {
    transform: translateX(-10px);
  }
}
@keyframes drawY {
  to {
    transform: translateY(-10px);
  }
}
<div class="outer">
  <span></span>
</div>

使用一些 CSS 变量来控制一切:

.outer {
  --th:2px; /* border thickness */
  --w:5px; /* width of the color*/
  --s:5px; /* the space between color*/
  --o:5px; /* the offset */
  --c:red;
  --g: var(--c) 0 var(--w), transparent 0 calc(var(--w) + var(--s));
  
  border-radius: 5px;
  position: relative;
  width: 200px;
  height: 200px;
  display:inline-block;
  border: 1px solid gray;
  margin:15px;
  clip-path:inset(calc(-1*var(--o)));
}
.outer::before,
.outer::after,
.outer span::before,
.outer span::after {
  content:"";
  position: absolute;
  opacity:0;
  transition:1s;
  animation: 1s linear infinite;
}
.outer::before,
.outer::after {
  height: var(--th);
  left: calc(-1*var(--o));
  width: calc(100% + var(--w) + var(--s) + 2*var(--o));
  background: repeating-linear-gradient(to right, var(--g));
  animation-name:drawX;
}

.outer span::before,
.outer span::after {
  width: var(--th);
  top: calc(-1*var(--o));
  height: calc(100% + var(--w) + var(--s) + 2*var(--o));
  background: repeating-linear-gradient(to bottom, var(--g));
  animation-name:drawY;
}

.outer::before {top: calc(-1*var(--o)); animation-direction:reverse;}
.outer span::before {right: calc(-1*var(--o)); animation-direction:reverse;}

.outer::after { bottom: calc(-1*var(--o));}
.outer span::after { left: calc(-1*var(--o));}

.outer:hover::before,
.outer:hover::after,
.outer:hover span::before,
.outer:hover span::after {
  opacity:1;
}

@keyframes drawX {
  to {
    transform: translateX(calc(-1*(var(--w) + var(--s))));
  }
}
@keyframes drawY {
  to {
    transform: translateY(calc(-1*(var(--w) + var(--s))));
  }
}
<div class="outer">
  <span></span>
</div>

<div class="outer" style="--th:4px;--o:8px;--s:8px;--w:8px;--c:blue;">
  <span></span>
</div>

关于html - 为笔画 dashoffset 设置动画时使用过多 CPU 资源使用 SVG 路径创建的边框,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65601161/

相关文章:

带有阴影背景的 HTML 电子邮件表

css - 如何将 DIV 滚动条放入固定宽度的 DIV 中(溢出 :auto, float:left)

html - 如何关闭 div 的样式,或设置为仅使用一个 css 文件?

html - 如何让文字更接近图像?

css - 将 CSS transition-timing-function 转换为滑动

sql - 为什么这个 DISTINCT/INNER JOIN/ORDER BY postgresql 查询这么慢?

performance - 非规范化数字 - IEEE 754 float

c++ - 加速人员检测程序,使用 OpenCV 3.0 编写

html - 百分比宽度 Div 不适合

html - 保持页眉和页脚就位 - 仅滚动正文