You need to make an adaptive SVG .
How to make it so that when the image is resized (or viewport ), the child elements of the SVG moved and rearranged (as in the adaptive HTML layout).
How to make such a SVG ?
You need to make an adaptive SVG .
How to make it so that when the image is resized (or viewport ), the child elements of the SVG moved and rearranged (as in the adaptive HTML layout).
How to make such a SVG ?
You can create a "adaptive" svg image. To do this, you need to register css-media queries inside it and move elements through transform . Sample image:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="200px" height="200px" preserveAspectRatio="none"> <style> circle, rect{ stroke-width:2px; fill:none; stroke:orange; } @media (max-width: 120px){ circle{ transform:translateX(50px); } rect{ transform:translate(-60px,80px); } } </style> <circle cx="40" cy="40" r="34" /> <rect x="100" y="10" width="80" height="60" /> </svg> Next, paste it into the page (used data: url because SO doesn't want to take svg pictures and links without https, but this is the same svg):
$('input').on('input',function(){ $('img').width(this.value); }) *{ box-sizing:border-box; vertical-align:top; } img{ max-width:100%; border:1px solid; } <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <img src="data:image/svg+xml;base64,+DQogIDxjaXJjbGUgY3g9IjQwIiBjeT0iNDAiIHI9IjM0IiAvPg0KICA8cmVjdCB4PSIxMDAiIHk9IjEwIiB3aWR0aD0iODAiIGhlaWdodD0iNjAiIC8+DQo8L3N2Zz4=" /> <label for="controller">Тут задавать ширину для картинки</label> <input id="controller" type="number" min="70" max="500" step="5" /> Sketched an example of code on pure svg and of course here we will not see how the location of svg objects changes, I give an example in: https://codepen.io/topicstarter/pen/oPBzvw?editors=1000 in which the object position changes at a resolution less than 600px.
to see the adaptability of svg here, open sample code for the whole page and compress the browser itself to less than 600px
img preview:
<meta name="viewport" content="width=device-width, height=device-height, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0"> <svg viewbox="0 250 200" id="svg"> <defs> <style> #svg{ width:210px; height:100px; } #rect{ width:50px; height:40px; fill:red; x:20px; y:30px; } #circle{ cx:150px; cy:50px; fill:blue; r:40px; } @media (max-width:600px){ #svg{ width:200px; height:140px; } #rect{ width:50px; height:40px; fill:red; x:70px; y:5px; fill:blue; } #circle{ cx:95px; cy:90px; fill:blue; r:40px; fill:red; } } </style> </defs> <rect id="rect"></rect> <circle id="circle"></circle> </svg> Option on JS (like flex-wrap in 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; } <div class="wrapper"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/2000/svg" version="1.1"> <g class="main-area" fill="hsl(50,100%,70%)"> <rect/> <rect/> <rect/> <rect/> <rect class='rect3'/> <rect class='rect3'/> <rect/> <rect/> <rect/> <rect/> <rect/> <rect/> <rect/> <rect/> <rect/> <rect/> <rect/> <rect/> <rect class='rect1'/> <rect/> <rect class='rect2'/> <rect/> <rect/> <rect/> <rect/> <rect class='rect2'/> <rect/> <rect/> <rect/> <rect/> <rect/> <rect/> </g> </svg> </div> width & height attributes - ArthurThis can be done using any js library for working with SVG.
For example, I took SVG.js :
Immediately provide a working example , and below is the code of the example:
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; } <script src="https://cdnjs.cloudflare.com/ajax/libs/svg.js/2.6.5/svg.min.js"></script> <div id="banner"></div> Uncaught ReferenceError: SVG is not defined - ThisManIt is surprising that all the answers written before me do not correspond to the condition of the task. Pay attention to the fact that you need to track exactly the image size:
How to make the image resize (or viewport)
And all 4 answers written to me are not taken into account at all and are tracked as one window resizing. It is also not clear why, after 4 months, nobody paid attention to this ?! It reminded me of a funny old joke about developers .
But if someone still needs to respond to a window change, then study the first 4 answers and the article by reference (it's about CSS media requests such as @media (max-width:600px) ).
If we translate the word “adaptive” into Russian, we will get two words “adaptable” and “adaptable”. The ending "-th" always implies that the object of the action itself (reduction-end at the end) will adapt. But “adaptable” means that the subject of the action will be adapted by someone (something). For example, a higher window will adjust it - that is, someone (something), but not himself.
A case where it is “adaptable”
In this case, this adaptive will be our SVG object, which will track changes in itself and adapt itself . To do this, we are in the SVG object itself (although it is possible outside) through JavaScript using the window.setTimeout function every 50 милисекунд monitor image resizing by comparing the width property svg.getAttribute('width') . And if this value changes, then we change the location of the rectangle by changing the values of its properties (or so-called attributes) x and y with the help of the function rect.setAttribute(); . We can also instead change the CSS property transform:translate(...px, ...px); , the reference to which in JavaScript looks like this:
rect.style.transform = 'translate(...px, ...px)'; But it makes no sense to give an example of transform , since This has already been done in the first two examples.
It is also important to note that svg.setAttribute('width', ...); image using svg.setAttribute('width', ...); we must also change the size of its viewBox , for otherwise there will be a discrepancy and the image will be distorted.
So, the first example / case:
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} <font color="white">Ширина <s>окна</s> SVG изображения: <select onchange="changeWidth(this)"> <option>320</option> <option>210</option> </select> px.</font><br><br> <svg id="svg" viewBox="0 0 320 320" width="320" height="320" style="background:#fff"> <g fill="none" stroke="#f93" stroke-width="3"> <polygon points="60,10,110,60,60,110,10,60"/> <rect id="rect" x="130" y="10" width="180" height="100"/> </g> <script type="text/javascript"> var svg = document.querySelector('#svg'), rect = svg.getElementsByTagName('rect')[0]; (function checkWidth() { var w = +svg.getAttribute('width'); //+ значит перевод из string в integer if(w < 211) { rect.setAttribute('x', 10); rect.setAttribute('y', 120) } else { rect.setAttribute('x', 130); rect.setAttribute('y', 10) } window.setTimeout(checkWidth, 50) })() </script> </svg> A case where it is “adaptable”
This case is more complicated for this task, since SVG is a vector image and there must be certain coordinates for each point. And although the decision, when the properties of the rectangle are changed from the outside, one could, with a stretch, be called “adjustable”, but this is still wrong, because we change its location properties.
So, see what I mean by “adjustable” SVG (an example that also solves the problem):
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} <font color="white">Размер SVG изображения: <select onchange="changeWidth(this)"> <option value="">320 x 120</option> <option value="">200 x 240</option> </select> px.</font><br><br> <svg id="svg" viewBox="0 0 320 120" width="320" height="120" style="background:#fff"> <svg preserveAspectRatio="xMinYMin meet" width="120" height="120" viewBox="0 0 120 120"> <polygon points="60,10,110,60,60,110,10,60" fill="none" stroke="#f93" stroke-width="3"/> </svg> <svg preserveAspectRatio="xMaxYMax meet" width="100%" height="100%" viewBox="0 0 200 120"> <rect x="10" y="10" width="180" height="100" fill="none" stroke="#f93" stroke-width="3"/> </svg> </svg> Notice how the preserveAspectRatio properties are displayed in the internal SVG images, which help us to arrange our images in this way. Also important are the width and height properties, which are set to 100% in the second inner SVG. And when used together, they act in such a way that our second internal SVG is built either to the far right or to the very bottom.
This is what I call an “adjustable” SVG here, because Nowhere in the code does not change anything (not specified) depending on the size of the image as in the case of the "adapting" SVG. All we do is only resize the image and nothing more .
Source: https://ru.stackoverflow.com/questions/873904/
All Articles