От автора: в большей степени пользователи легко разбираются в элементах интерфейса с численной системой измерения, но графический интерфейс может «направлять» пользователя и повышает ассоциативную составляющую, особенно при работе с большими диапазонами значений. Как и в предыдущем примере с кольцом, тут также используется SVG, JavaScript и input типа range.
Как и раньше svg помещается в label:
1 2 3 4 5 6 7 8 9 10 11 12 |
<label for="scale"> <svg xmlns="//www.w3.org/2000/svg" viewBox="0 0 100 33"> <title>Scale</title> <defs> <clipPath id="triangle"> <polygon points="0 33, 100 33, 100 0" /> </clipPath> </defs> <polygon points="0 33, 100 33, 100 0" /> <rect x="0" y="0" height="50" width="50" clip-path="url(#triangle)" fill="yellow" /> </svg> </label> |
Главным элементом в SVG является rect — он обрезается треугольным полигоном polygon. input изменяется в диапазоне от 0 до 100: обратите внимание на то, что по ширине он равен polygon; значение инпута совпадает с шириной элемента rect.
1 |
<input id="scale" type="range" name="scale" min="0" max="100" value="50" oninput="scaleChange()" onchange="scaleChange()"> |
На все элементы хватает всего пары строк CSS:
1 2 3 4 5 6 7 8 |
label, input { display: block; width: 25%; margin: 0 auto; } #scale { margin-top: 2rem; } |
За треугольным SVG полигоном расположен еще один треугольник без стилей; этот треугольник не обрезается, но имеет те же размеры, что и желтый – он выступает как рамка или задний фон.
На инпут повешены оба события onchange и oninput, которые вызывают одну функцию, работающую во всех браузерах. Функция с кодом JS:
1 2 3 4 5 6 7 8 |
var scale = document.getElementById("scale"), svg = document.querySelector("label[for='scale'] svg"), svgns = "//www.w3.org/2000/svg", triangle = svg.getElementsByTagNameNS(svgns, "rect")[0]; function scaleChange() { triangle.setAttribute("width",scale.value); } |
Экспоненциальный ползунок
О понятности графических линейных элементов интерфейса можно спорить и спорить, но данная техника будет особенно полезна при работе с нелинейными значениями, такими как экспоненциальные функции. Обычно эти функции сложны для понимания обычного пользователя. Пример экспоненциального ползунка представлен в демо Codepen.
Первый линейный пример работает только при условии, что ширина SVG бокса равна максимальному значению слайдера. В реальной жизни это неприменимо. В этом демо я с помощью JS считываю и сравниваю ширину viewbox’а и значение слайдера. Разметка остается почти та же, но для ясности я сменил значения name и id:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<label for="exponentialslider"> Population Growth Over Time <svg xmlns="//www.w3.org/2000/svg" viewBox="0 0 627 350"> <title>Exponential Growth</title> <defs> <clipPath id="exp"> <path d="M0,350c370-10,521.7,31.7,626.7-350c0,78.3,0,350,0,350S275,350,0,350z"/> </clipPath> </defs> <path d="M0,350c370-10,521.7,31.7,626.7-350c0,78.3,0,350,0,350S275,350,0,350z"/> <rect height="350" width="627" clip-path="url(#exp)" fill="yellow" /> </svg> </label> <input id="exponentialslider" type="range" name="exponentialslider" min="0" max="10" value="8" step=".1" oninput="expChange()" onchange="expChange()"> </div> |
Так как путь повторяется, то намного лучше ссылаться на оба режима через один <symbol>, но эту задачу я оставлю читателям. Скрипт стал немного больше:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var exponentialslider = document.getElementById("exponentialslider"), expsvg = document.querySelector("label[for='exponentialslider'] svg"), expsvgns = "//www.w3.org/2000/svg", mask = expsvg.getElementsByTagNameNS(expsvgns, "rect")[0], box = expsvg.getAttribute('viewBox'), viewBoxCords = box.split(/\s+|,/), viewBoxWidth = viewBoxCords[2] - viewBoxCords[0], sliderMax = exponentialslider.max; function expChange() { mask.setAttribute("width",exponentialslider.value * (viewBoxWidth / sliderMax)); } expChange(); |
Напрямую через DOM мы пока что не может получить точные значения высоты и ширины viewbox’а, но мы можем взять строку со значением из viewbox’а, разбить ее в массив, вычесть из третьего значения первое и получить ширину. Чтобы все получилось, необходимо соблюсти несколько условий:
Viewbox должен измеряться в пикселях
Нельзя вставлять ничего лишнего между viewBox и элементами в SVG
SVG должен занимать всю ширину viewbox’а
В самом конце вызывается функция expChange и задает исходную позицию экспоненциального графа. Данную технику можно использовать и по-другому: в теории с помощью JS можно создавать всю SVG структуру и автоматизировать весь процесс.
Источник: //thenewcode.com/
Редакция: Команда webformyself.