Необходимо сделать адаптивный SVG.
Как сделать так, чтобы при изменении размеров изображения (или viewport-а), дочерние элементы SVG перемещались и перестраивались (как в адаптивной вёрстке HTML).
Как сделать такой SVG?
Ответы
Ответ 1
Можно создать "адаптивное" svg-изображение. Для этого нужно прописать внутри него css-медиазапросы и двигать элементы через transform.
Пример изображения:
Далее вставляем его на страницу(использовал data:url т.к. SO не хочет принимать svg картинки и ссылки без https, но это тот же самый svg):
$('input').on('input',function(){
$('img').width(this.value);
})
*{
box-sizing:border-box;
vertical-align:top;
}
img{
max-width:100%;
border:1px solid;
}
Ответ 2
Набросал пример кода на чистом svg и разумеется здесь мы не увидим как меняется расположени
svg объектов то привожу пример в: https://codepen.io/topicstarter/pen/oPBzvw?editors=1000 в котором изменение положения объектов произойдёт при разрешении меньше 600px.
что бы увидеть здесь адаптивность svg надо открыть пример кода на всю страниц
а сжать сам браузер до менее 600px
img preview :
Ответ 3
Вариант на JS (подобно flex-wrap в CSS):
const $d = document;
let rects = $d.getElementsByTagName('rect');
const arrangement = e => {
let windowWidth = $d.documentElement.clientWidth;
let offset_x = 20;
let offset_y = 20;
let next_offset_y = offset_y;
let offset = 20;
let maxH = 0;
let maxW = 0;
for (let i = 0, len = e.length; i < len; i++) {
let w = parseInt(getComputedStyle(e[i]).width);
let h = parseInt(getComputedStyle(e[i]).height);
if (h > maxH) {
maxH = h;
}
if (w > maxW) {
maxW = w;
}
if (maxW + w + offset_x + offset + offset + offset > windowWidth) {
set(e, i, offset_x, offset_y);
offset_y += offset + next_offset_y;
offset_x = 20;
maxH = h;
} else {
set(e, i, offset_x, offset_y);
offset_x += w + offset;
next_offset_y = maxH;
}
}
};
const set = (e, i, offset_x, offset_y) => {
e[i].setAttribute('x', offset_x);
e[i].setAttribute('y', offset_y);
}
arrangement(rects);
window.onresize = function(e) {
arrangement(rects);
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
overflow: hidden;
}
html {
font-size: 62.5%;
}
html,
body {
height: 100%;
}
.wrapper {
width: 100%;
height: 100%;
}
.wrapper svg {
width: inherit;
height: inherit;
background-color: hsl(10, 0%, 70%);
}
.wrapper svg .main-area rect {
width: 25px;
height: 25px;
stroke: #000;
stroke-width: 0.125rem;
}
.wrapper svg .main-area rect.rect1 {
width: 70px;
height: 25px;
}
.wrapper svg .main-area rect.rect2 {
width: 25px;
height: 70px;
}
.wrapper svg .main-area rect.rect3 {
width: 70px;
height: 50px;
}
Ответ 4
Это можно сделать, используя любую js библиотеку для работы с SVG.
К примеру я взял SVG.js:
Сразу предоставлю рабочий пример, а ниже код примера:
var draw = SVG('banner');
var bg = draw
.rect('100%', '100%')
.attr({ fill: '#ffeb3b' });
var elem1 = draw
.ellipse(100, 100)
.attr({ fill: '#f06' });
var elem2 = draw
.rect(150, 100)
.attr({ fill: '#f06' });
bunnerUpdate();
window.onresize = bunnerUpdate;
function bunnerUpdate() {
if (window.innerWidth > 400) {
draw.size(400, 200);
elem1.move(50, 50);
elem2.move(200, 50);
}
else {
draw.size('100%', 350);
elem1.move(window.innerWidth / 2 - 50, 50);
elem2.move(window.innerWidth / 2 - 75, 200);
}
}
body {
margin: 0;
padding: 0;
}
Ответ 5
Удивительно, что все ответы, написанные до меня, не соответствуют условию поставленной задачи. Обратите внимание на то, что нужно отслеживать именно размеры изображения:
Как сделать так, чтобы при изменении размеров изображения (или viewport-а)
А все 4 ответа, написанные до меня, это вообще не принимают во внимание и отслеживаю
как один изменение размеров окна. Непонятно также почему спустя 4 месяца на это никто не обратил внимания?! Напомнило мне смешную старую шутку про разработчиков.
Но если кому-то всё же нужно откликаться на изменение окна, то изучайте первые
ответа и статью по ссылке (она про CSS медиа-запросы такие как @media (max-width:600px)).
Правильное решение
Если переводить слово «адаптивный» на русский язык, то мы получим два слова «приспосабливающийся
и «приспосабливаемый». Окончание «-ийся» всегда подразумевает, что предмет действи
сам себя(сокращение -ся в конце) приспособит. А вот «приспосабливаемый» означает что предмет действия будет кем-то(чем-то) приспособлен. К примеру, его приспособит вышестоящее окно - то есть кто-то(что-то), но не он сам.
Случай, когда это «приспосабливающийся»
В данном случае этот приспосабливающийся будет наш SVG объект, который будет отслеживат
изменения в себе и приспосабливать себя. Для этого мы в самом SVG объекте (хотя можн
и снаружи) через JavaScript при помощи функции window.setTimeout каждые 50 милисекун
отслеживаем изменения размеров изображения посредством сравнения значения свойства ширины svg.getAttribute('width'). И если это значение меняется, то мы меняем расположение прямоугольника, изменяя значения его свойств (или т.н. атрибутов) x и y при помощи функции rect.setAttribute();. Мы также вместо этого можем изменить CSS свойство transform:translate(...px, ...px);, обращение к которому в JavaScript выглядит так:
rect.style.transform = 'translate(...px, ...px)';
Но приводить пример с transform нет смысла, т.к. это уже сделали в двух первых примерах.
Также важно заметить, что изменяя размер изображения посредством svg.setAttribute('width'
...); мы также должны изменить и размер его viewBox-а, ибо иначе будет несоответствие и изображение исказится.
Итак, первый пример / случай:
var svg = document.querySelector('#svg');
function changeWidth(obj)
{
var width = +obj.options[obj.selectedIndex].text;
svg.setAttribute('width', width);
svg.setAttribute('viewBox', '0,0,' + width + ',320');
}
body{background:#000}
Ширина окна SVG изображения:
px.
Случай, когда это «приспосабливаемый»
Этот случай более сложный для данной задачи, т.к. SVG – это векторное изображени
и в нём для каждой точки уже должны быть определённые координаты. И хотя решение, когда свойства прямоугольника изменяются извне, можно было бы с натяжкой назвать «приспосабливаемый», но это всё же неправильно, т.к. мы изменяем его свойства местоположения.
Итак, смотрите что я имею ввиду под «приспосабливаемый» SVG (пример, который также решает поставленную задачу):
var svg = document.querySelector('#svg');
function changeWidth(obj)
{
var size = obj.options[obj.selectedIndex].text.split(' x ');
svg.setAttribute('width', size[0]);
svg.setAttribute('height', size[1]);
svg.setAttribute('viewBox', '0,0,' + size[0] + ','+size[1]);
}
body{background:#000}
Размер SVG изображения:
px.
Обратите внимание на то, как во внутренних SVG изображениях выставлены свойства preserveAspectRatio
которые и способствуют тому, чтобы расположить наши изображения таким образом. Такж
здесь важны свойства ширины и высоты, которые во втором внутреннем SVG установлены в 100%. И используемые вместе они действуют таким образом, что наш второй внутренний SVG выстраивается либо крайне справа, либо крайне снизу.
Вот что я называю здесь «приспосабливаемый» SVG, т.к. нигде в коде ничего не меняетс
(не указывается) в зависимости от размера изображения как в случае с «приспосабливающийся» SVG. Всё, что мы делаем – это изменяем только размеры изображения и ничего более.
Комментариев нет:
Отправить комментарий