I Я пытаюсь создать шкалу с радиальными линиями и числами в диапазоне 0-100.
Вот мой код:
<!DOCTYPE html>
<html>
<meta charset = "UTF-8">
<meta name = "viewport" content = "width=device-width, initial-scale=1.0">
<head>
<title>SVG Gauge</title>
</head>
<style>
#wrapper {
position: relative;
margin: auto;
}
#meter {
width: 100%;
height: 100%;
transform: rotateX(180deg);
}
.circle {
fill: none;
}
#mask {
stroke: #404040;
stroke-width: 60;
}
.blackie {
fill:none;
stroke: #000000;
stroke-width: 30;
}
.range {
stroke-width: 60;
}
.scale {
stroke: #cccccc;
}
#slider, #lbl {
position: absolute;
}
#slider {
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;
transform: rotate(270deg);
}
</style>
<body>
<div id = "wrapper">
<svg id = "meter">
<g class = "scale">
<defs>
<linearGradient id = "grad" x1 = "0%" y1 = "0%" x2 = "100%" y2 = "0%">
<stop offset = "0%" style = "stop-color:rgb(102, 102, 255);stop-opacity:1" />
<stop offset = "100%" style = "stop-color:rgb(204, 204, 255);stop-opacity:1" />
</linearGradient>
</defs>
<circle id = "high" class = "circle range" cx = "50%" cy = "50%" stroke = "url(#grad)">
</circle>
<circle id = "mask" class = "circle" cx = "50%" cy = "50%">
</circle>
<circle id = "low" class = "blackie" cx = "50%" cy = "50%" r = "360">
</circle>
<circle id = "outline_ends" class = "circle outline" cx = "50%" cy = "50%">
</circle>
</g>
</svg>
<img id = "meter_needle" src = "gauge-needle.svg" alt = "">
<input id = "slider" type = "range" min = "0" max = "100" value = "0" />
<label id = "lbl" id = "value" for = "">0%</label>
</div>
<script>
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);
}
var meter_dimension = (r * 2) + 100;
var wrapper = document.querySelector('#wrapper');
wrapper.style.width = meter_dimension + 'px';
wrapper.style.height = meter_dimension + 'px';
var cf = 2 * Math.PI * r;
var semi_cf = cf / 2;
var z = 40 * Math.PI;
document.querySelector('#outline_ends')
.setAttribute('stroke-dasharray', 2 + ',' + (semi_cf - 2));
document.querySelector('#high')
.setAttribute('stroke-dasharray', semi_cf + ',' + cf);
document.querySelector('#mask')
.setAttribute('stroke-dasharray', semi_cf + ',' + cf);
document.querySelector('#low')
.setAttribute('stroke-dasharray', semi_cf - z + ',' + cf);
var slider = document.querySelector('#slider');
var lbl = document.querySelector("#lbl");
var svg = document.querySelector('#meter');
var high = document.querySelector('#high');
var mask = document.querySelector('#mask');
var low = document.querySelector('#low');
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(' + (270 + ((percent * 180) / 100)) + 'deg)';
lbl.textContent = percent + '%';
}
slider.addEventListener('input', range_change_event);
</script>
</body>
</html>
Я нашел в сети множество хороших примеров с HTML Canvas и D3js, но ничего, основанного на SVG .. Я думаю создать элемент «линию» и добавить его по черной дуге. Как проще всего создать числовую шкалу?



What is the simplest way to create the numeric scale?
Самый простой способ анимировать масштабирование круга svg - это анимировать его радиус
<svg version = "1.1" xmlns = "http://www.w3.org/2000/svg"
xmlns:xlink = "http://www.w3.org/1999/xlink"
width = "400" height = "400" viewBox = "0 0 400 400" >
<circle cx = "200" cy = "200" r = "10" fill = "none" stroke-width = "2" stroke = "purple" >
<animate attributeName = "r" values = "1;100;1" dur = "4s" repeatCount = "indefinite" />
</circle>
</svg> @Giannis Tsamandouras Для лучшего понимания проблемы, можете ли вы нарисовать изображение промежуточной и конечной позиции анимации?
Это хорошая идея - использовать радиус от круга вместо transform scale. Обязательно попробую использовать!
Ну вот:
<svg xmlns = "http://www.w3.org/2000/svg" viewBox = "-250 -250 500 500" width = "500" height = "500" id = "svg">
<defs>
<style>
line {
stroke: black;
stroke-width: 1px;
}
text {
fill: red;
text-anchor: middle;
font-size: 16px;
font-family: sans-serif;
}
rect {
fill: transparent;
}
#id {
display: none;
}
.origin {
fill: green;
}
.outer {
fill: none;
stroke: black;
}
</style>
</defs>
<circle r = "5" cx = "0" cy = "0" class = "origin"/>
<path d = "M-180,0 a1,1 0 0,1 360,0" class = "outer"/>
<g id = "gauge" transform = "rotate(-90)">
<g id = "noon">
<rect x = "-10" y = "-220" width = "20" height = "100"/>
<line x1 = "0" y1 = "-190" x2 = "0" y2 = "-180"/>
<text x = "0" y = "-200"></text>
</g>
</g>
</svg>
<script>
for (i=0; i<=180; i = i + 18) {
var new_tick = noon.cloneNode(true);
new_tick.getElementsByTagName('text')[0].textContent = i/180 * 100;
new_tick.removeAttribute("id");
new_tick.setAttribute("transform", "rotate(" + i + " 0 0)");
gauge.appendChild(new_tick);
}
</script>
Я думаю, это не требует пояснений. (Например, RECT - это просто руководство, которое вы можете включить, изменив заливку, если хотите лучше визуализировать, что происходит внутри каждого G.)
Дайте мне знать, если у вас возникнут какие-либо вопросы.
Вот Codepen, если это поможет: https://codepen.io/MSCAU/pen/OoQMdV
Я читал эту статью (veerasundar.com/blog/2017/06/…), но ваш ответ - лучшее, что я видел до сих пор. Большое тебе спасибо.
Рад помочь :)
Спасибо за пример, но я не спрашиваю о масштабировании SVG. Я хочу сделать числовую шкалу с радиальными линиями по черной внутренней дуге ... как спидометр ... Я пробовал теги svg <line> и <text>, но мне это не нравится, потому что мне нужно найти точные координаты ... Я также пробовали свойство "stroke-dasharray" для создания белых промежутков, но мне это не нравится, потому что белые линии должны быть расширены за пределы дуги.