Поиск по метке: JS
Размеры SVG-элементов в реальных пикселах
При использовании динамической SVG-графики, может возникнуть ситуация, когда удобно работать с каким-нибудь конкретным viewBox-ом, указав ту координатную сетку, с координатами и размерами которой будет удобно работать. Однако не все векторные примитивы вам может захотеться рисовать в масштабе этой сетки. Какие-то из них вы пожелаете сохранить в пикселном представлении. Что же делать?
- Можно поменять viewBox таким образом, что бы 1-ца сетки в нём соответсвовала 1px на канве. Что далеко не всегда бывает удобным вариантом.
- Можно подсчитать кол-во реальных px-й на 1 сетки viewBox-а и исходить из них.
В этом посту я остановлюсь на 2-ом варианте. Итак, с чего начнём? Начнём с того, что для границ-рамок-как-угодно-называйте, в общем для stroke, есть уже готовый механизм: vector-effect: non-scaling-stroke. Указав это свойство ваши stroke-width будут задаваться в реальных пикселах, а не в масштабе SVG.
А что делать, скажем, с радиусом для circle? Положим мы хотим нарисовать точку, но хотим чтобы её размер в px-ах не зависел от размеров канвы и масштаба на ней. Ну для начала посчитаем кол-во пикселей на 1-цу сетки:
const { width: wpx, height: hpx } = svg.getBoundingClientRect();
const kx = wpx / wi;
const ky = hpx / hi;
Где wi и hi это координатные width и height для viewBox. Если kx === 10, то на 1-цу сетки у вас 10 пикселей.
Ок, что дальше? Можно использовать эти коэффициенты на стороне JS, а можно отдать почти всё на откуп CSS, воспользовавшись CSS-variables. Например так:
<svg viewBox="" style={{ '--var-kx': kx }}/>
а в CSS используем calc:
circle { r: calc(5 / var(--var-kx)); }
UPD: Firefox не умеет r в css :(
Хотелось бы, конечно, чего-то вроде vector-effect: non-scaling и для других полей. Но меня устроил и этот вариант.