css 如何用焦点做一个渐变的非整圆笔画?

w6lpcovy  于 2023-05-19  发布在  其他
关注(0)|答案(2)|浏览(92)

我试图使元素显示在下面的图像:

它基于Apple Watch的空气质量小部件。
该圆不是完全圆的,并且渐变在该线上发生变化。除此之外,还有一个“点”,显示实际值是什么(我想用JavaScript设置这个)。
我试着用dasharraydashoffset来做半圆。但是梯度不能穿过整条线。如果不对对象使用transform: rotate,我也无法获得底部圆差距。

#Layer_1 {
   transform: rotate(135deg);
}
.ring {
   stroke-dasharray:314;
   stroke-dashoffset: 78;
   stroke-linecap: round;
}
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="500px" height="500px" viewBox="0 0 120 120" enable-background="new 0 0 120 120" xml:space="preserve">

   <circle class="ring" fill="none" stroke="url(#linear)" stroke-width="10" stroke-miterlimit="10" cx="50%" cy="50%" r="50"/>

   <defs>
       <linearGradient id="linear" x1="0%" y1="0%" x2="100%" y2="0%">
           <stop offset="0%" stop-color="#05a"></stop>
           <stop offset="50%" stop-color="#a55"></stop>
           <stop offset="100%" stop-color="#0a5"></stop>
       </linearGradient>
   </defs>
</svg>
f2uvfpb9

f2uvfpb91#

你是在正确的轨道上,当谈到中风破折号阵列。在该示例中,使用掩模来制作圆和焦点。遮罩将应用于包含四条不同线的组,这四条线构成了圆形渐变。我知道,这个问题与渐变无关,但它现在变得很重要,因为SVG只有线性和径向渐变。

document.forms.form01.range.addEventListener('change', e => {
  document.getElementById('point').setAttribute('transform', `rotate(${e.target.value})`);
});
body{
  background-color: #303030;
}
<form name="form01">
  <input type="range" step="10" name="range" min="0" max="270" value="30">
</form>
<svg xmlns="http://www.w3.org/2000/svg" width="200" viewBox="0 0 100 100">
  <defs>
    <linearGradient id="lg1" x1="0" x2="0" y1="55" y2="0" gradientUnits="userSpaceOnUse">
      <stop offset="20%" stop-color="Gold"/>
      <stop offset="90%" stop-color="SpringGreen"/>
    </linearGradient>
    <linearGradient id="lg2" x1="0" x2="0" y1="55" y2="0" gradientUnits="userSpaceOnUse">
      <stop offset="20%" stop-color="DarkOrange"/>
      <stop offset="90%" stop-color="Gold"/>
    </linearGradient>
    <linearGradient id="lg3" x1="0" x2="0" y1="55" y2="0" gradientUnits="userSpaceOnUse">
      <stop offset="20%" stop-color="red"/>
      <stop offset="90%" stop-color="DarkOrange"/>
    </linearGradient>
    <linearGradient id="lg4" x1="0" x2="0" y1="55" y2="0" gradientUnits="userSpaceOnUse">
      <stop offset="20%" stop-color="DarkOrchid"/>
      <stop offset="90%" stop-color="red"/>
    </linearGradient>
    <mask id="m1">
      <circle r="45" stroke="white" stroke-width="10" stroke-linecap="round" stroke-dasharray="270 360" pathLength="360" />
      <g id="point" transform="rotate(30)">
        <circle transform="translate(45 0)" r="6" stroke="black" fill="white" stroke-width="3"/>
      </g>
    </mask>
  </defs>
  <g transform="translate(50 50) rotate(135)" stroke-linecap="round" stroke-width="25" mask="url(#m1)">
    <line transform="translate(50 0) rotate(30)" stroke="url(#lg1)" y2="55" />
    <line transform="rotate(70) translate(50 0) rotate(30)" stroke="url(#lg2)" y2="55" />
    <line transform="rotate(140) translate(50 0) rotate(30)" stroke="url(#lg3)" y2="55" />
    <line transform="rotate(210) translate(50 0) rotate(30)" stroke="url(#lg4)" y2="55" />
  </g>
</svg>
9fkzdhlc

9fkzdhlc2#

虽然SVG内容不直接支持锥形渐变,但您可以将HTML元素与background-image: conic-gradient()和SVG定义的遮罩组合在一起,以剪切弧和位置标记。
对于圆弧,您可以使用圆和stroke-dasharray的技术。我发现用适当的弧线画一条路径更容易。pathLength属性将有助于沿着其长度进行定位,但对于我的解决方案来说并不是严格需要的。
有多种方法来实现一个进度标记,在这里,我将使用一个fake <animateMotion>沿着路径动画一个环,并没有真正移动。位置被设置为keyPoints="x;x"属性,x是一个0到1之间的数字,可以用Javascript设置。

const marker = document.querySelector('#progress animateMotion');

function position (x) {
  marker.setAttribute('keyPoints', `${x};${x}`);
}

position(0.2);
#progress #arc {
  fill: none;
  stroke: white;
  stroke-width: 10;
  stroke-linecap: round;
}
#progress circle {
  fill: none;
  stroke: black;
  stroke-width: 4;
}

#meter {
  position: relative;
  width: 100px;
  height: 100px;
  background-image: conic-gradient(yellow, green, blue, red, orange, yellow);
  mask: url(#progress);
}
<svg width="0" height="0">
  <mask id="progress" width="100" height="100">
    <path id="arc" d="M 25,85 A 40 40 0 1 1 75,85" pathLength="100" />
    <circle r="7">
      <animateMotion path="M 25,85 A 40 40 0 1 1 75,85"
                     keyTimes="0;1" begin="0s" fill="freeze"
                     keyPoints="0;0" />
    </circle>
  </mask>
</svg>
<div id="meter"></div>

相关问题