【问题标题】:Divide semi circle with stroke-dasharray and on active color fill用 stroke-dasharray 和活动颜色填充划分半圆
【发布时间】:2021-02-17 02:10:01
【问题描述】:

我正在研究一个 SVG 仪表,当范围滑块移动到带有渐变颜色的活动笔触填充时,我想将半圆分成几部分。并且想在计针移动时再增加一条黑色运行轨迹。我曾尝试使用stroke-dasharray,但添加此之后,所有颜色都出现在一个时间计无法正常工作。

  1. 当范围滑块在使用渐变颜色的活动笔触填充上移动时,我想将半圆分成几部分
  2. 我想在仪表指针移动时再添加一条黑色跑道。

我的代码在这里

/* set radius for all circles */
var r = 400;
var circles = document.querySelectorAll('.circle');
var total_circles = circles.length;
for (var i = 0; i < total_circles; i++) {
  circles[i].setAttribute('r', r);
}
/* set meter's wrapper dimension */
var meter_dimension = (r * 2) + 100;
var wrapper = document.querySelector('#wrapper');
wrapper.style.width = meter_dimension + 'px';
wrapper.style.height = meter_dimension + 'px';
/* add strokes to circles  */
var cf = 2 * Math.PI * r;
var semi_cf = cf / 2;
var semi_cf_1by3 = semi_cf / 3;
var semi_cf_2by3 = semi_cf_1by3 * 2;

document.querySelector('#outline_curves').setAttribute('stroke-dasharray', semi_cf + ',' + cf);
document.querySelector('#high').setAttribute('stroke-dasharray', semi_cf + ',' + cf);
document.querySelector('#avg').setAttribute('stroke-dasharray', semi_cf_2by3 + ',' + cf);
document.querySelector('#low').setAttribute('stroke-dasharray', semi_cf_1by3 + ',' + cf);
document.querySelector('#outline_ends').setAttribute('stroke-dasharray', 2 + ',' + (semi_cf - 2));
document.querySelector('#mask').setAttribute('stroke-dasharray', semi_cf + ',' + cf);
/*bind range slider event*/
var slider = document.querySelector('#slider');
var lbl = document.querySelector("#lbl");
var mask = document.querySelector('#mask');
var meter_needle = document.querySelector('#meter_needle');

function range_change_event() {
  var percent = slider.value
  var meter_value = semi_cf - ((percent * semi_cf) / 100);
  mask.setAttribute('stroke-dasharray', meter_value + ',' + cf);
  meter_needle.style.transform = 'rotate(' + (450 - ((percent * 180) / 100)) + 'deg)';
  lbl.textContent = percent + '%';
}
slider.addEventListener('input', range_change_event);
#wrapper {
  position: relative;
  margin: auto;
}

#meter {
  width: 100%;
  height: 100%;
  transform: rotate(180deg);
}

.circle {
  fill: none;
}

.outline,
#mask {
  stroke: #F1F1F1;
  stroke-width: 65;
}

.range {
  stroke-width: 60;
}

#slider,
#lbl {
  position: absolute;
}

#slider {
  position: absolute;
  transform: rotate(180deg);
  cursor: pointer;
  left: 0;
  margin: auto;
  right: 0;
  top: 58%;
  width: 94%;
}

#lbl {
  background-color: #4B4C51;
  border-radius: 2px;
  color: white;
  font-family: 'courier new';
  font-size: 15pt;
  font-weight: bold;
  padding: 4px 4px 2px 4px;
  right: -48px;
  top: 57%;
}

#meter_needle {
  height: 40%;
  left: 0;
  margin: auto;
  position: absolute;
  right: 0;
  top: 10%;
  transform-origin: bottom center;
  /*orientation fix*/
  transform: rotate(450deg);
  width: 5px;
  background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<body>
  <div id="wrapper">
    <svg id="meter">
        <circle id="outline_curves" class="circle outline"  cx="50%" cy="50%">
        </circle>
        <circle id="high" class="circle range" cx="50%" cy="50%" stroke="#FDE47F">
        </circle>
        <circle id="avg" class="circle range" cx="50%" cy="50%" stroke="#7CCCE5">
        </circle>
        <circle id="low" class="circle range" cx="50%" cy="50%" stroke="#E04644">
        </circle>
    
        <circle id="mask" class="circle" cx="50%" cy="50%" >
        </circle>
        <circle id="outline_ends" class="circle outline" cx="50%" cy="50%">
        </circle>
    </svg>
    <svg version="1.1" id="meter_needle" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16.721px" height="93.834px" viewBox="0 0 16.721 93.834" enable-background="new 0 0 16.721 93.834" xml:space="preserve">
            <path fill="#464646" d="M13.886,84.243L2.83,83.875c0,0,3.648-70.77,3.956-74.981C7.104,4.562,7.832,0,8.528,0
                c0.695,0,1.752,4.268,2.053,8.894C10.883,13.521,13.886,84.243,13.886,84.243z"/>
            <path fill="#464646" d="M16.721,85.475c0,4.615-3.743,8.359-8.36,8.359S0,90.09,0,85.475c0-4.62,3.743-8.363,8.36-8.363
                S16.721,80.855,16.721,85.475z"/>
            <circle fill="#EEEEEE" cx="8.426" cy="85.471" r="2.691"/>
</svg>
    <input id="slider" type="range" min="25" max="100" step="25" value="0" />
    <label id="lbl" id="value" for="">0%</label>
  </div>
  <script src="script.js"></script>
</body>

任何人都可以向我建议如何实现此输出。任何帮助将不胜感激。

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>

<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="65px" height="51.333px" viewBox="0 0 65 51.333" enable-background="new 0 0 65 51.333" xml:space="preserve">
<g>
    <defs>
        <rect id="SVGID_1_" x="-157.417" y="-176.417" width="648" height="864"/>
    </defs>
    <clipPath id="SVGID_2_">
        <use xlink:href="#SVGID_1_"  overflow="visible"/>
    </clipPath>
    <g clip-path="url(#SVGID_2_)">
        <defs>
            <rect id="SVGID_3_" x="-157.417" y="-176.417" width="648" height="864"/>
        </defs>
        <clipPath id="SVGID_4_">
            <use xlink:href="#SVGID_3_"  overflow="visible"/>
        </clipPath>
    </g>
    <g clip-path="url(#SVGID_2_)">
        <defs>
            <rect id="SVGID_5_" x="-157.417" y="-176.417" width="648" height="864"/>
        </defs>
        <clipPath id="SVGID_6_">
            <use xlink:href="#SVGID_5_"  overflow="visible"/>
        </clipPath>
    </g>
    <g clip-path="url(#SVGID_2_)">
        <defs>
            <rect id="SVGID_7_" x="-157.417" y="-176.417" width="648" height="864"/>
        </defs>
        <clipPath id="SVGID_8_">
            <use xlink:href="#SVGID_7_"  overflow="visible"/>
        </clipPath>
        <path clip-path="url(#SVGID_8_)" fill="#FFFFFF" d="M19.527,44.274c-1.653,5.015-7.059,7.738-12.071,6.085
            c-5.015-1.654-7.739-7.058-6.087-12.071c1.652-5.015,7.058-7.739,12.072-6.084C18.456,33.855,21.179,39.26,19.527,44.274"/>
        <path clip-path="url(#SVGID_8_)" fill="#58595B" d="M19.514,44.289c-1.652,5.013-7.056,7.736-12.066,6.083
            c-5.014-1.653-7.736-7.056-6.084-12.067c1.652-5.013,7.055-7.736,12.068-6.083C18.443,33.875,21.166,39.277,19.514,44.289"/>
        <path clip-path="url(#SVGID_8_)" fill="#FFFFFF" d="M17.318,43.564c-1.253,3.801-5.35,5.865-9.15,4.612
            c-3.797-1.253-5.863-5.35-4.609-9.148c1.254-3.8,5.349-5.865,9.148-4.612C16.506,35.67,18.57,39.766,17.318,43.564"/>
        <path clip-path="url(#SVGID_8_)" fill="#58595B" d="M19.266,34.944c2.242,3.113,2.33,7.115,0.57,10.255l45.249-43.24L9.721,31.148
            C13.256,30.475,17.023,31.828,19.266,34.944"/>
        <defs>
            <filter id="Adobe_OpacityMaskFilter" filterUnits="userSpaceOnUse" x="6.52" y="-11.184" width="62.369" height="60.661">
                <feFlood  style="flood-color:white;flood-opacity:1" result="back"/>
                <feBlend  in="SourceGraphic" in2="back" mode="normal"/>
            </filter>
        </defs>
        <mask maskUnits="userSpaceOnUse" x="6.52" y="-11.184" width="62.369" height="60.661" id="SVGID_9_">
            <g filter="url(#Adobe_OpacityMaskFilter)">
                <g enable-background="new    ">
                    <g enable-background="new    ">
                        <g>
                            <defs>
                                <path id="SVGID_10_" d="M17.516,29.352c2.243,0.335,3.028,2.134,3.028,2.134L57.891,6.807L17.516,29.352z"/>
                            </defs>
                            <clipPath id="SVGID_11_" clip-path="url(#SVGID_8_)">
                                <use xlink:href="#SVGID_10_"  overflow="visible"/>
                            </clipPath>
                            <defs>
                                
                                    <filter id="Adobe_OpacityMaskFilter_1_" filterUnits="userSpaceOnUse" x="6.52" y="-11.184" width="62.369" height="60.661">
                                    <feFlood  style="flood-color:white;flood-opacity:1" result="back"/>
                                    <feBlend  in="SourceGraphic" in2="back" mode="normal"/>
                                </filter>
                            </defs>
                            <mask maskUnits="userSpaceOnUse" x="6.52" y="-11.184" width="62.369" height="60.661" id="SVGID_9_">
                                <g filter="url(#Adobe_OpacityMaskFilter_1_)">
                                    <g enable-background="new    ">
                                    </g>
                                </g>
                            </mask>
                            
                                <linearGradient id="SVGID_12_" gradientUnits="userSpaceOnUse" x1="-236.1787" y1="699.8169" x2="-235.1792" y2="699.8169" gradientTransform="matrix(36.5072 -22.3825 22.3825 36.5072 -7021.3823 -30804.627)">
                                <stop  offset="0" style="stop-color:#FFFFFF"/>
                                <stop  offset="0.0466" style="stop-color:#D5D7D8"/>
                                <stop  offset="0.0983" style="stop-color:#B1B3B6"/>
                                <stop  offset="0.1557" style="stop-color:#929497"/>
                                <stop  offset="0.2174" style="stop-color:#797A7D"/>
                                <stop  offset="0.2847" style="stop-color:#626366"/>
                                <stop  offset="0.3595" style="stop-color:#4E4E50"/>
                                <stop  offset="0.445" style="stop-color:#3B3B3C"/>
                                <stop  offset="0.5476" style="stop-color:#202021"/>
                                <stop  offset="0.6848" style="stop-color:#080809"/>
                                <stop  offset="1" style="stop-color:#000000"/>
                            </linearGradient>
                            <polygon clip-path="url(#SVGID_11_)" mask="url(#SVGID_9_)" fill="url(#SVGID_12_)" points="28.547,49.477 68.889,24.744 
                                46.861,-11.184 6.52,13.549                          "/>
                        </g>
                    </g>
                </g>
            </g>
        </mask>
        <g opacity="0.8" clip-path="url(#SVGID_8_)">
            <g>
                <defs>
                    <rect id="SVGID_13_" x="6.52" y="-11.184" width="62.369" height="60.661"/>
                </defs>
                <clipPath id="SVGID_14_">
                    <use xlink:href="#SVGID_13_"  overflow="visible"/>
                </clipPath>
                <g clip-path="url(#SVGID_14_)">
                    <defs>
                        <path id="SVGID_15_" d="M17.516,29.352c2.243,0.335,3.028,2.134,3.028,2.134L57.891,6.807L17.516,29.352z"/>
                    </defs>
                    <clipPath id="SVGID_16_">
                        <use xlink:href="#SVGID_15_"  overflow="visible"/>
                    </clipPath>
                    
                        <linearGradient id="SVGID_17_" gradientUnits="userSpaceOnUse" x1="-236.1787" y1="699.8169" x2="-235.1792" y2="699.8169" gradientTransform="matrix(36.5072 -22.3825 22.3825 36.5072 -7021.3823 -30804.627)">
                        <stop  offset="0" style="stop-color:#FFFFFF"/>
                        <stop  offset="0.1467" style="stop-color:#FFFFFF"/>
                        <stop  offset="1" style="stop-color:#FFFFFF"/>
                    </linearGradient>
                    <polygon clip-path="url(#SVGID_16_)" fill="url(#SVGID_17_)" points="28.547,49.477 68.889,24.744 46.861,-11.184 6.52,13.549 
                                            "/>
                </g>
            </g>
        </g>
        <path clip-path="url(#SVGID_8_)" fill="#58595B" d="M12.709,42.044c-0.412,1.254-1.765,1.936-3.02,1.523
            c-1.253-0.414-1.934-1.765-1.52-3.019c0.412-1.253,1.764-1.936,3.017-1.521C12.44,39.441,13.121,40.792,12.709,42.044"/>
    </g>
</g>
</svg>

【问题讨论】:

    标签: javascript jquery css meter


    【解决方案1】:

    这是一个有效的 SVG 示例,带有一点 javascript。

    从您的问题中不清楚您到底想要什么颜色的分区 看起来像。现在我刚刚把它们变成了纯红色。但是您可以通过更改fill 的&lt;rect id="meter-colours" .../&gt; 来使它们看起来像您想要的那样。

    let METER_DIVISIONS = 10;
    let METER_DIVISIONS_GAP = 4;
    
    // Initialise meter
    let meterDivisionsElem = document.getElementById("meter-divisions");
    // Calculate size of each meter division
    let totalLen = meterDivisionsElem.getAttribute("r") * Math.PI;
    let numGaps = METER_DIVISIONS - 1;
    let divLen = (totalLen - METER_DIVISIONS_GAP * numGaps) / METER_DIVISIONS;
    // Set meter divisions dash pattern
    let pat = divLen + ' ' + METER_DIVISIONS_GAP + ' ';
    meterDivisionsElem.setAttribute("stroke-dasharray", pat.repeat(numGaps) + ' ' + divLen + ' ' + totalLen);
    
    // The slider form element
    let sliderElem = document.getElementById("slider");
    // The slider label element
    let sliderLabelElem = document.getElementById("lbl");
    // The needle element
    let needleElem = document.getElementById("needle");
    // The black bar element
    let blackBarElem = document.getElementById("black-bar");
    let blackBarLen = blackBarElem.getAttribute("r") * Math.PI;
    // The meter colours element
    let meterColoursElem = document.getElementById("meter-colours");
    
    function setMeterTo(value)
    {
      // Update slider label
      sliderLabelElem.textContent = value + '%';
    
      // Update needle position
      let rotation = value * 180 / 100;
      needleElem.setAttribute("transform", "rotate(" + rotation + ")");
    
      // Update black bar length
      let barLen = value * blackBarLen / 100;
      blackBarElem.setAttribute("stroke-dasharray", barLen + ' ' + (2 * blackBarLen));
    
      // Update coloured division section of the meter
      meterColoursElem.setAttribute("transform", "rotate(" + rotation + ")");
    }
    
    // Add an input change handler to the slider
    sliderElem.addEventListener("input", function(evt) {
      setMeterTo(evt.target.value);
    });
    
    // Initialise meter to start value
    setMeterTo(25);
    #wrapper {
      width: 600px;
    }
    
    #slider {
      width: 100%;
    }
    
    #needle {
      stroke-linecap: round;
    }
    <div id="wrapper">
      <svg id="meter" viewBox="0 0 200 110">
        <defs>
          <circle id="meter-divisions" r="90" stroke-width="20" stroke-dasharray="282.7"/>
          
          <mask id="meter-divisions-mask">
            <use xlink:href="#meter-divisions" stroke="white"/>
          </mask>
        </defs>
        <g transform="translate(100,100) scale(1,-1)" fill="none">
          <!-- The grey meter divisions -->
          <use xlink:href="#meter-divisions" stroke="lightgrey"/>
          <!-- The inner semicircular black bar -->
          <circle id="black-bar" r="74" stroke="black" stroke-width="4" stroke-dasharray="232.5"/>
          <!-- the needle -->
          <line id="needle" x2="70" y2="0" stroke="black" stroke-width="2" stroke-dasharray="282.7"/>
          <!-- The coloured form of the ,meter divisions that gets rotated into view with the needle.
               It is initially off screen but gets revealed as it rotates. It is masked by using
               a shape matching the gray divisions -->
          <g mask="url(#meter-divisions-mask">
            <rect id="meter-colours" x="-100" y="-100" width="200" height="100" fill="red"/>
          </g>
        </g>
      </svg>
    
      <input id="slider" type="range" min="25" max="100" step="25" value="25" />
      <label id="lbl" id="value" for="">0%</label>
    </div>

    更新新针头图片

    首先让我们简化一下你的针头图像:

    <svg width="650px" viewBox="0 0 65 51.333">
    <g>
      <path fill="#58595B" fill-rule="evenodd" d="M19.514,44.289c-1.652,5.013-7.056,7.736-12.066,6.083c-5.014-1.653-7.736-7.056-6.084-12.067c1.652-5.013,7.055-7.736,12.068-6.083C18.443,33.875,21.166,39.277,19.514,44.289 M17.318,43.564c-1.253,3.801-5.35,5.865-9.15,4.612c-3.797-1.253-5.863-5.35-4.609-9.148c1.254-3.8,5.349-5.865,9.148-4.612C16.506,35.67,18.57,39.766,17.318,43.564 M12.709,42.044c-0.412,1.254-1.765,1.936-3.02,1.523c-1.253-0.414-1.934-1.765-1.52-3.019c0.412-1.253,1.764-1.936,3.017-1.521C12.44,39.441,13.121,40.792,12.709,42.044"/>
      <path fill="#58595B" d="M19.266,34.944c2.242,3.113,2.33,7.115,0.57,10.255l45.249-43.24L9.721,31.148C13.256,30.475,17.023,31.828,19.266,34.944"/>
      <path fill="#FFFFFF" fill-opacity="0.8" d="M17.516,29.352c2.243,0.335,3.028,2.134,3.028,2.134L57.891,6.807L17.516,29.352z"/>
    </g>
    </svg>

    要在您的仪表中使用它,我们需要找到一个准确的旋转中心(圆圈中的点),并重新调整它的方向,使其角度为零。我们可能还需要调整其刻度以适应仪表。

    通过分析和实验,旋转中心在(10.44, 41.3),将旋转归零所需的旋转是35.8 deg。

    由于仪表以(0,0) 为中心,我们需要先将新指针移动并旋转这些量。

    <svg width="650px" viewBox="0 0 65 51.333">
    <g transform="rotate(35.8) translate(-10.44, -41.3)">
      <path fill="#58595B" fill-rule="evenodd" d="M19.514,44.289c-1.652,5.013-7.056,7.736-12.066,6.083c-5.014-1.653-7.736-7.056-6.084-12.067c1.652-5.013,7.055-7.736,12.068-6.083C18.443,33.875,21.166,39.277,19.514,44.289 M17.318,43.564c-1.253,3.801-5.35,5.865-9.15,4.612c-3.797-1.253-5.863-5.35-4.609-9.148c1.254-3.8,5.349-5.865,9.148-4.612C16.506,35.67,18.57,39.766,17.318,43.564 M12.709,42.044c-0.412,1.254-1.765,1.936-3.02,1.523c-1.253-0.414-1.934-1.765-1.52-3.019c0.412-1.253,1.764-1.936,3.017-1.521C12.44,39.441,13.121,40.792,12.709,42.044"/>
      <path fill="#58595B" d="M19.266,34.944c2.242,3.113,2.33,7.115,0.57,10.255l45.249-43.24L9.721,31.148C13.256,30.475,17.023,31.828,19.266,34.944"/>
      <path fill="#FFFFFF" fill-opacity="0.8" d="M17.516,29.352c2.243,0.335,3.028,2.134,3.028,2.134L57.891,6.807L17.516,29.352z"/>
    </g>
    </svg>

    指针现在是水平的,位于 (0,0)。

    我们现在可以将它集成到之前的解决方案中:

    let METER_DIVISIONS = 10;
    let METER_DIVISIONS_GAP = 4;
    
    // Initialise meter
    let meterDivisionsElem = document.getElementById("meter-divisions");
    // Calculate size of each meter division
    let totalLen = meterDivisionsElem.getAttribute("r") * Math.PI;
    let numGaps = METER_DIVISIONS - 1;
    let divLen = (totalLen - METER_DIVISIONS_GAP * numGaps) / METER_DIVISIONS;
    // Set meter divisions dash pattern
    let pat = divLen + ' ' + METER_DIVISIONS_GAP + ' ';
    meterDivisionsElem.setAttribute("stroke-dasharray", pat.repeat(numGaps) + ' ' + divLen + ' ' + totalLen);
    
    // The slider form element
    let sliderElem = document.getElementById("slider");
    // The slider label element
    let sliderLabelElem = document.getElementById("lbl");
    // The needle element
    let needleElem = document.getElementById("needle");
    // The black bar element
    let blackBarElem = document.getElementById("black-bar");
    let blackBarLen = blackBarElem.getAttribute("r") * Math.PI;
    // The meter colours element
    let meterColoursElem = document.getElementById("meter-colours");
    
    function setMeterTo(value)
    {
      // Update slider label
      sliderLabelElem.textContent = value + '%';
    
      // Update needle position
      let rotation = value * 180 / 100;
      needleElem.setAttribute("transform", "rotate(" + (-rotation) + ")");
    
      // Update black bar length
      let barLen = value * blackBarLen / 100;
      blackBarElem.setAttribute("stroke-dasharray", barLen + ' ' + (2 * blackBarLen));
    
      // Update coloured division section of the meter
      meterColoursElem.setAttribute("transform", "rotate(" + rotation + ")");
    }
    
    // Add an input change handler to the slider
    sliderElem.addEventListener("input", function(evt) {
      setMeterTo(evt.target.value);
    });
    
    // Initialise meter to start value
    setMeterTo(25);
    #wrapper {
      width: 600px;
    }
    
    #slider {
      width: 100%;
    }
    
    #needle {
      stroke-linecap: round;
    }
    <div id="wrapper">
      <svg id="meter" viewBox="0 0 200 110">
        <defs>
          <circle id="meter-divisions" r="90" stroke-width="20" stroke-dasharray="282.7"/>
          
          <mask id="meter-divisions-mask">
            <use xlink:href="#meter-divisions" stroke="white"/>
          </mask>
        </defs>
        <g transform="translate(100,100)">
          <g transform="scale(1,-1)" fill="none">
            <!-- The grey meter divisions -->
            <use xlink:href="#meter-divisions" stroke="lightgrey"/>
            <!-- The inner semicircular black bar -->
            <circle id="black-bar" r="74" stroke="black" stroke-width="4" stroke-dasharray="232.5"/>
            <!-- The coloured form of the ,meter divisions that gets rotated into view with the needle.
                 It is initially off screen but gets revealed as it rotates. It is masked by using
                 a shape matching the gray divisions -->
            <g mask="url(#meter-divisions-mask">
              <rect id="meter-colours" x="-100" y="-100" width="200" height="100" fill="red"/>
            </g>
          </g>
          
          <!-- the needle -->
          <g id="needle">
            <g transform="rotate(35.8) translate(-10.44, -41.3)">
              <path fill="#58595B" fill-rule="evenodd" d="M19.514,44.289c-1.652,5.013-7.056,7.736-12.066,6.083c-5.014-1.653-7.736-7.056-6.084-12.067c1.652-5.013,7.055-7.736,12.068-6.083C18.443,33.875,21.166,39.277,19.514,44.289 M17.318,43.564c-1.253,3.801-5.35,5.865-9.15,4.612c-3.797-1.253-5.863-5.35-4.609-9.148c1.254-3.8,5.349-5.865,9.148-4.612C16.506,35.67,18.57,39.766,17.318,43.564 M12.709,42.044c-0.412,1.254-1.765,1.936-3.02,1.523c-1.253-0.414-1.934-1.765-1.52-3.019c0.412-1.253,1.764-1.936,3.017-1.521C12.44,39.441,13.121,40.792,12.709,42.044"/>
              <path fill="#58595B" d="M19.266,34.944c2.242,3.113,2.33,7.115,0.57,10.255l45.249-43.24L9.721,31.148C13.256,30.475,17.023,31.828,19.266,34.944"/>
              <path fill="#FFFFFF" fill-opacity="0.8" d="M17.516,29.352c2.243,0.335,3.028,2.134,3.028,2.134L57.891,6.807L17.516,29.352z"/>
            </g>
          </g>
    
        </g>
        
      </svg>
    
      <input id="slider" type="range" min="25" max="100" step="25" value="25" />
      <label id="lbl" id="value" for="">0%</label>
    </div>

    【讨论】:

    • 哇,这正是我想要实现的目标,我非常感谢您的努力。我在这里有一个小查询默认值是 0 我想要 25 min="25" max="100" step="25" value="25" 我写了值 25 但仍然针在 0 只有我想要默认值是 25
    • 我已经更新了我的答案。这是你想要的吗?还是您希望针从底部开始,而不是部分向上?
    • 是的,这就是我想要的,感谢您付出的时间。
    • 嗨,保罗,我用 SVG 替换了米针,然后针的方向不正确,我试过像这样needleElem.setAttribute("transform", "rotate(" + (357 - ((value * 180) / 100)) + ")"); 仍然不来。你能建议我吗?我在上面更新了针 SVG。
    • 惊叹您的解释和您为实现所需输出所做的努力。
    【解决方案2】:

    我这里的方法是纯 CSS 的,我没有使用 SVG,在这种情况下实现 JS 代码要容易得多。

    输出

    var black = document.getElementsByClassName('black')[0];
    var gradient = document.getElementsByClassName('gradient')[0]
    var tick = document.getElementsByClassName('tick')[0];
    var m = document.getElementById('m');
    m.addEventListener('input', function() {
      black.style.transform = gradient.style.transform = tick.style.transform = "translate(-50%,-50%)rotateZ(-" + (180 / 100) * m.value + "deg)"
    });
    * {
      margin: 0px;
      padding: 0px;
      font-family: "arial";
    }
    
    .gauge_main,
    .white,
    .black,
    .tick,
    .gradient,
    .chamber,
    .meter {
      position: absolute;
      top: 50%;
      left: 50%;
      height: 280px;
      width: 280px;
      transform: translate(-50%, -50%);
      transition: 0.4s;
    }
    
    .meter {
      background-color: white;
      height: 281px;
      width: 281px;
      border-radius: 50%;
      clip-path: polygon(0 50%, 100% 50%, 100% 100%, 0 100%);
      z-index: 1000;
    }
    
    .tick,
    .chamber {
      width: 160px;
      height: 5px;
      background: linear-gradient(to right, white 50%, black 50%);
      z-index: 110;
      transform-origin: 50%;
    }
    
    .tick {
      z-index: 1001;
    }
    
    .chamber {
      left: 50%;
      background: white;
      width: 280px;
      height: 5px;
      transform-origin: 50%;
      transform: translate(-50%, -50%)rotateZ(calc(var(--i)*-20deg));
      z-index: 20;
    }
    
    .white,
    .black,
    .gradient {
      position: absolute;
      background-color: black;
      border-radius: 50%;
    }
    
    .white {
      height: 180px;
      width: 180px;
      background-color: white;
      z-index: 30;
    }
    
    .gradient {
      height: 280px;
      width: 280px;
      background: linear-gradient(0deg, rgba(29, 216, 255, 1) 0%, rgba(4, 106, 255, 1) 50%, rgba(208, 212, 255, 1) 50%);
    }
    
    .black {
      height: 200px;
      width: 200px;
      background: linear-gradient(to top, black 50%, rgba(208, 212, 255, 1) 50%);
      box-shadow: 0px 0px 0px 5px white;
      z-index: 25;
    }
    
    @keyframes load {
      from {
        transform: translate(-50%, -50%)rotateZ(0deg);
      }
      to {
        transform: translate(-50%, -50%)rotateZ(-180deg);
      }
    }
    
    input {
      position: absolute;
      top: 50%;
      left: 50%;
      width: 280px;
      transform: translate(-50%, 50%);
    }
    <div class="gauge_main">
      <div class="gradient"></div>
      <div class="white"></div>
      <div class="black"></div>
      <div class="tick"></div>
      <div style="--i:1" class="chamber"></div>
      <div style="--i:2" class="chamber"></div>
      <div style="--i:3" class="chamber"></div>
      <div style="--i:4" class="chamber"></div>
      <div style="--i:5" class="chamber"></div>
      <div style="--i:6" class="chamber"></div>
      <div style="--i:7" class="chamber"></div>
      <div style="--i:8" class="chamber"></div>
      <div style="--i:9" class="chamber"></div>
      <div class="meter"></div>
    
    </div>
    <input type="range" id="m" name="meter" min="0" max="100" value="0">

    【讨论】:

    • 默认情况下,圆点是灰色的,然后用颜色填充,当我尝试增加 guage 主宽度时,其他东西都是混搭。
    • 感谢您的努力。正如你在上面看到的圆圈默认颜色是灰色的。并且完整的米宽、高,如果我改变,不会与输出冲突。我无法制作视频。
    • @Husna 没问题
    • 使用我之前的代码很好,因为我使用stroke-dasharray 来填充圆圈,因此您可以想到任何其他替代方法,然后对于圆圈划分,我们可以在 css 中使用 stroke-dasharray。 The main point is that in js how can we remove stroke-dasharray and use other alternative to fill circle
    • @Husna 我使用了渐变,并将每种颜色的渐变颜色组合设为 50%,使其变成一个半圆形,并为相同的颜色旋转 180 度
    猜你喜欢
    • 2021-01-01
    • 1970-01-01
    • 2022-07-06
    • 1970-01-01
    • 2019-03-13
    • 1970-01-01
    • 2014-08-03
    • 2014-06-16
    • 2011-03-17
    相关资源
    最近更新 更多