Страницы

Поиск по вопросам

вторник, 26 ноября 2019 г.

Как сделать адаптивный svg?


Необходимо сделать адаптивный 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. Всё, что мы делаем – это изменяем только размеры изображения и ничего более.

Комментариев нет:

Отправить комментарий