Hus*_*sna 4 javascript css jquery meter
我正在研究一个 SVG 仪表,当范围滑块在带有渐变颜色的活动笔划填充上移动时,我想将半圆分成几部分。并想在表针移动时再添加一条黑色运行轨迹。我曾尝试使用stroke-dasharray
,但添加此后,所有颜色都会在时间计无法正常工作时出现。
我的代码在这里
/* 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);
Run Code Online (Sandbox Code Playgroud)
#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;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)
谁能向我建议如何实现这个输出。任何帮助将不胜感激。
<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>
Run Code Online (Sandbox Code Playgroud)
我这里的方法是纯 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)"
});
Run Code Online (Sandbox Code Playgroud)
* {
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%);
}
Run Code Online (Sandbox Code Playgroud)
<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">
Run Code Online (Sandbox Code Playgroud)
这是一个有效的 SVG 示例,带有一点 JavaScript。
从您的问题中不清楚您到底希望彩色分区是什么样子。现在我只是把它们变成纯红色。但是您可以通过更改 的 来使它们看起来像您想要的fill
那样<rect id="meter-colours" .../>
。
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);
Run Code Online (Sandbox Code Playgroud)
#wrapper {
width: 600px;
}
#slider {
width: 100%;
}
#needle {
stroke-linecap: round;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)
更新新的针图像
首先让我们简化你的针图像:
<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>
Run Code Online (Sandbox Code Playgroud)
要在仪表中使用它,我们需要找到一个准确的旋转中心(圆圈中的点),并重新调整它的方向,使其角度为零。我们可能还需要调整其比例以适应仪表。
经分析和实验,旋转中心为(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>
Run Code Online (Sandbox Code Playgroud)
针现在是水平的,并且位于 (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);
Run Code Online (Sandbox Code Playgroud)
#wrapper {
width: 600px;
}
#slider {
width: 100%;
}
#needle {
stroke-linecap: round;
}
Run Code Online (Sandbox Code Playgroud)
<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>
Run Code Online (Sandbox Code Playgroud)