Я пытался создать датчик с диапазоном от 0 до 100. Я создал этот элемент SVG в Sketch, и теперь я пытаюсь заставить вращение работать для черной иглы.
Чтобы сделать это, я попытался поиграть с transform-origin и transform: rotate(), но я не могу заставить его вращаться, как показано в .gif, так как он всегда кажется обрезанным. Я добавил ползунок диапазона JS для вашего удобства, чтобы продемонстрировать проблему. Здесь также является кодовой ручкой для экспериментов.
Не могли бы вы помочь мне добиться желаемого результата, как показано на гифке?
$('#percent').on('change', function() {
$('#needle').css('transform', 'translate(175px, 19px) rotate(' + percentToDegrees($(this).val()) + 'deg)')
})
function percentToDegrees(percent) {
var degrees = -90;
var inc = 1.8;
return degrees += (percent * inc);
}#needle {
transform-origin: 0% bottom;
transform: translate(175px, 19px) rotate(0);
}
input {
display: block;
margin: 50px auto;
}<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg width = "100%" height = "177px" viewBox = "0 0 385 177" version = "1.1" xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink">
<g id = "Page-1" stroke = "none" stroke-width = "1" fill = "none" fill-rule = "evenodd">
<g id = "Artboard" transform = "translate(-15.000000, -224.000000)">
<g id = "Group" transform = "translate(15.000000, 220.000000)">
<g id = "guage">
<path d = "M84.8041871,178.856781 L84.8041871,179.169281 L25,179.169281 L25,178.669281 C25,119.519295 57.1931907,67.8894771 105.011512,40.3501901 L135,92.2989954 C105.009619,109.483749 84.8041871,141.810321 84.8041871,178.856781 Z" id = "red" fill = "#BD3632"></path>
<path d = "M235.050803,92.4864742 C205.21439,75.1028089 167.169843,73.7652453 135.133157,92.2884751 L134.862916,92.4447251 L105,40.6455806 L105.432385,40.3955806 C156.58355,10.8205878 217.307001,12.8896752 265,40.5376689 L235.050803,92.4864742 L235.050803,92.4864742 Z" id = "yellow" fill = "#EEAF30"></path>
<path d = "M235,92.2989954 L264.988488,40.3501901 C312.806809,67.8894771 345,119.519295 345,178.669281 L345,179.169281 L285.195813,179.169281 L285.195813,178.856781 C285.195813,141.810321 264.990381,109.483749 235,92.2989954 L235,92.2989954 Z" id = "green" fill = "#008542"></path>
<text id = "100%" font-family = "Omnes-Regular, Omnes" font-size = "15" font-weight = "normal" line-spacing = "15" fill = "#000000">
<tspan x = "350" y = "180">100%</tspan>
</text>
<text id = "50%" font-family = "Omnes-Regular, Omnes" font-size = "15" font-weight = "normal" fill = "#000000">
<tspan x = "171" y = "14">50%</tspan>
</text>
<text id = "0%" font-family = "Omnes-Regular, Omnes" font-size = "15" font-weight = "normal" fill = "#000000">
<tspan x = "0" y = "178">0%</tspan>
</text>
</g>
<g id = "needle" transform = "translate(175.000000, 19.000000)">
<polygon id = "Triangle" fill = "#3C3C3B" points = "10 0 15 162 5 162"></polygon>
</g>
</g>
</g>
</g>
</svg>
<input type = "range" id = "percent" value = "50" min = "0" max = "100">Еще одна демонстрация здесь
хотя довольно круто






Подумайте transform-box:fill-box;, затем сделайте исходную точку bottom center и немного увеличьте окно просмотра, чтобы избежать разреза. Я также переместил вращение на полигон и сохранил перевод элемента g.
$('#percent').on('change', function() {
$('#triangle').css('transform', 'rotate(' + percentToDegrees($(this).val()) + 'deg)')
})
function percentToDegrees(percent) {
var degrees = -90;
var inc = 1.8;
return degrees += (percent * inc);
}#triangle {
transform-origin:center bottom;
transform-box:fill-box;
}
input {
display: block;
margin: 50px auto;
}<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg width = "100%" height = "177px" viewBox = "0 0 385 185" version = "1.1" xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink">
<g id = "Page-1" stroke = "none" stroke-width = "1" fill = "none" fill-rule = "evenodd">
<g id = "Artboard" transform = "translate(-15.000000, -224.000000)">
<g id = "Group" transform = "translate(15.000000, 220.000000)">
<g id = "guage">
<path d = "M84.8041871,178.856781 L84.8041871,179.169281 L25,179.169281 L25,178.669281 C25,119.519295 57.1931907,67.8894771 105.011512,40.3501901 L135,92.2989954 C105.009619,109.483749 84.8041871,141.810321 84.8041871,178.856781 Z" id = "red" fill = "#BD3632"></path>
<path d = "M235.050803,92.4864742 C205.21439,75.1028089 167.169843,73.7652453 135.133157,92.2884751 L134.862916,92.4447251 L105,40.6455806 L105.432385,40.3955806 C156.58355,10.8205878 217.307001,12.8896752 265,40.5376689 L235.050803,92.4864742 L235.050803,92.4864742 Z" id = "yellow" fill = "#EEAF30"></path>
<path d = "M235,92.2989954 L264.988488,40.3501901 C312.806809,67.8894771 345,119.519295 345,178.669281 L345,179.169281 L285.195813,179.169281 L285.195813,178.856781 C285.195813,141.810321 264.990381,109.483749 235,92.2989954 L235,92.2989954 Z" id = "green" fill = "#008542"></path>
<text id = "100%" font-family = "Omnes-Regular, Omnes" font-size = "15" font-weight = "normal" line-spacing = "15" fill = "#000000">
<tspan x = "350" y = "180">100%</tspan>
</text>
<text id = "50%" font-family = "Omnes-Regular, Omnes" font-size = "15" font-weight = "normal" fill = "#000000">
<tspan x = "171" y = "14">50%</tspan>
</text>
<text id = "0%" font-family = "Omnes-Regular, Omnes" font-size = "15" font-weight = "normal" fill = "#000000">
<tspan x = "0" y = "178">0%</tspan>
</text>
</g>
<g id = "needle" transform = "translate(175.000000, 18.000000)">
<polygon id = "triangle" fill = "#3C3C3B" points = "10 0 15 162 5 162"></polygon>
</g>
</g>
</g>
</g>
</svg>
<input type = "range" id = "percent" value = "50" min = "0" max = "100">Просто имейте в виду, что transform-box работает только в последних версиях некоторых браузеров. Если вам нужно более совместимое решение, вы можете рассмотреть решение @Kaiido, которое использует абсолютные координаты в transform-origin.
Проще всего, вероятно, сделать все это с помощью SVG, просто установив transform атрибут вашего элемента вместо его css style.
Все, что вам нужно, это установить второе и третье значения метода преобразования rotate(angle, origin_x, origin_y) SVG.
$('#percent').on('input', function() {
$('#needle').attr('transform', 'translate(175, 19) ' +
'rotate(' + percentToDegrees($(this).val()) + ', 10, 162)')
})
function percentToDegrees(percent) {
var degrees = -90;
var inc = 1.8;
return degrees += (percent * inc);
}input {
display: block;
margin: 50px auto;
}<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg width = "100%" height = "177px" viewBox = "0 0 385 177" version = "1.1" xmlns = "http://www.w3.org/2000/svg" xmlns:xlink = "http://www.w3.org/1999/xlink">
<g id = "Page-1" stroke = "none" stroke-width = "1" fill = "none" fill-rule = "evenodd">
<g id = "Artboard" transform = "translate(-15.000000, -224.000000)">
<g id = "Group" transform = "translate(15.000000, 220.000000)">
<g id = "guage">
<path d = "M84.8041871,178.856781 L84.8041871,179.169281 L25,179.169281 L25,178.669281 C25,119.519295 57.1931907,67.8894771 105.011512,40.3501901 L135,92.2989954 C105.009619,109.483749 84.8041871,141.810321 84.8041871,178.856781 Z" id = "red" fill = "#BD3632"></path>
<path d = "M235.050803,92.4864742 C205.21439,75.1028089 167.169843,73.7652453 135.133157,92.2884751 L134.862916,92.4447251 L105,40.6455806 L105.432385,40.3955806 C156.58355,10.8205878 217.307001,12.8896752 265,40.5376689 L235.050803,92.4864742 L235.050803,92.4864742 Z" id = "yellow" fill = "#EEAF30"></path>
<path d = "M235,92.2989954 L264.988488,40.3501901 C312.806809,67.8894771 345,119.519295 345,178.669281 L345,179.169281 L285.195813,179.169281 L285.195813,178.856781 C285.195813,141.810321 264.990381,109.483749 235,92.2989954 L235,92.2989954 Z" id = "green" fill = "#008542"></path>
<text id = "100%" font-family = "Omnes-Regular, Omnes" font-size = "15" font-weight = "normal" line-spacing = "15" fill = "#000000">
<tspan x = "350" y = "180">100%</tspan>
</text>
<text id = "50%" font-family = "Omnes-Regular, Omnes" font-size = "15" font-weight = "normal" fill = "#000000">
<tspan x = "171" y = "14">50%</tspan>
</text>
<text id = "0%" font-family = "Omnes-Regular, Omnes" font-size = "15" font-weight = "normal" fill = "#000000">
<tspan x = "0" y = "178">0%</tspan>
</text>
</g>
<g id = "needle" transform = "translate(175.000000, 19.000000)">
<polygon id = "Triangle" fill = "#3C3C3B" points = "10 0 15 162 5 162"></polygon>
</g>
</g>
</g>
</g>
</svg>
<input type = "range" id = "percent" value = "50" min = "0" max = "100">Вы даже выиграете в браузерной совместимости ;-)
И обратите внимание, что все это можно упростить до:
$('#percent').on('input', function() {
$('#Triangle')
.attr('transform', 'rotate(' + percentToDegrees($(this).val()) + ', 10, 162)')
})
function percentToDegrees(percent) {
var degrees = -90;
var inc = 1.8;
return degrees += (percent * inc);
}input {
display: block;
margin: 50px auto;
}
#Page-1 text {
font-family: Omnes-Regular, Omnes;
font-size: 15px;
font-weight: normal;
fill: #000;
}<script src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<svg width = "100%" height = "177px" viewBox = "0 0 385 177" version = "1.1">
<g id = "Page-1" stroke = "none" fill = "none" transform = "translate(0, -4)">
<g id = "guage">
<path d = "M84.8041871,178.856781 L84.8041871,179.169281 L25,179.169281 L25,178.669281 C25,119.519295 57.1931907,67.8894771 105.011512,40.3501901 L135,92.2989954 C105.009619,109.483749 84.8041871,141.810321 84.8041871,178.856781 Z" id = "red" fill = "#BD3632"></path>
<path d = "M235.050803,92.4864742 C205.21439,75.1028089 167.169843,73.7652453 135.133157,92.2884751 L134.862916,92.4447251 L105,40.6455806 L105.432385,40.3955806 C156.58355,10.8205878 217.307001,12.8896752 265,40.5376689 L235.050803,92.4864742 L235.050803,92.4864742 Z" id = "yellow" fill = "#EEAF30"></path>
<path d = "M235,92.2989954 L264.988488,40.3501901 C312.806809,67.8894771 345,119.519295 345,178.669281 L345,179.169281 L285.195813,179.169281 L285.195813,178.856781 C285.195813,141.810321 264.990381,109.483749 235,92.2989954 L235,92.2989954 Z" id = "green" fill = "#008542"></path>
<text id = "100%" line-spacing = "15">
<tspan x = "350" y = "180">100%</tspan>
</text>
<text id = "50%">
<tspan x = "171" y = "14">50%</tspan>
</text>
<text id = "0%">
<tspan x = "0" y = "178">0%</tspan>
</text>
</g>
<g id = "needle" transform = "translate(175.000000, 19.000000)">
<polygon id = "Triangle" fill = "#3C3C3B" points = "10 0 15 162 5 162"></polygon>
</g>
</g>
</svg>
<input type = "range" id = "percent" value = "50" min = "0" max = "100">Вы можете упростить вещи, просто делая $('#Triangle').attr('transform', 'rotate(' + percentToDegrees($(this).val()) + ', 10, 162)');
@PaulLeBeau, конечно, OP применил преобразование к <g>, поэтому я подумал, что они хотели, чтобы оно было преобразовано, может быть, там есть что-то еще. Но вы абсолютно правы в том, что в текущем коде это излишне сложно (как и все эти вложенные <g> кстати).
@Kaiido, это то, что выводит для меня мой редактор Sketch. Если у вас есть лучшее предложение по разметке, не стесняйтесь обновить свой ответ чем-то более упрощенным.
Единственная проблема в том, что игла обрезается при 0 или 180 градусах.
@GBWDev, потому что так сделан твой рисунок. Вы можете захотеть сделать viewBox немного больше или изменить свой рисунок так, чтобы он соответствовал текущему, даже когда стрелка вращается.
это это, чего вы пытаетесь достичь?