Формула для динамического интервала в svg
Как сделать базу динамического интервала из координат возвращенных данных?
Я хочу, чтобы, если возвращаются только одно значение, они располагались посередине. Если возвращены несколько данных, он будет скорректирован и так далее.
var prev = {
"Prev": [{
"type": "Prev1",
},
{
"type": "Prev2",
},
{
"type": "Prev3",
},
]
};
var draw = document.getElementById('drawing');
prev.Prev.forEach((p, i, arr) => {
let x = 55;
let y = 250/arr.length*i+50;
draw.innerHTML += `<g transform="translate(${x} ${y})">
<rect x="-50" y="-20" width="100" height="40" rx="10" />
<text dominant-baseline="middle" text-anchor="middle" width="100">${p.type}</text>
<line x1="50" y1="0" x2="100" y2="${250/arr.length-y+50}" />
</g>`;
});
draw.innerHTML += `<g>
<rect x="150" y="110" width="100" height="40" rx="10" />
<text x="200" y="130" dominant-baseline="middle" text-anchor="middle" width="100">BASE</text>
</g>`;
line, rect {stroke-width: 1; stroke: navy; fill: none;}
text {fill: navy;}
<svg id="drawing" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg">
</svg>
Свободный перевод вопроса Formula for dynamic spacing in svg от участника @Jomari Ryan Ramirez.
Ответы (2 шт):
Все очень просто. Вам для этого нужно вычислить верхнюю часть первого прямоугольника, а затем добавить в i раз больше расстояние от верха одного элемента до верха следующего.
var prev = {
"Prev": [{
"type": "Prev1",
},
{
"type": "Prev2",
},
{
"type": "Prev3",
}
]
};
var draw = document.getElementById('drawing');
var RECT_HEIGHT = 40;
var RECT_SPACING = 50;
var SVG_HEIGHT = 300;
prev.Prev.forEach((p, i, arr) => {
// количество прямоугольников / элементов графика
let num = arr.length;
// общая высота всех <num>
let totalHeight = num * RECT_HEIGHT + (num - 1) * RECT_SPACING;
let x = 55;
//конечная позиция = позиция первого прямоугольника + i * distance_between_rects
let y = (SVG_HEIGHT - totalHeight) / 2 // верх первого прямоугольника
+ i * (RECT_HEIGHT + RECT_SPACING); // i * distance_between_rects
draw.innerHTML += `<g transform="translate(${x} ${y})">
<rect x="-50" y="0" width="100" height="40" rx="10" />
<text y="20" dominant-baseline="middle" text-anchor="middle"
width="100">${p.type}</text>
<line x1="50" y1="20" x2="100" y2="${SVG_HEIGHT / 2 - y}" />
</g>`;
});
/*
draw.innerHTML += `<g>
<rect x="150" y="110" width="100" height="40" rx="10" />
<text x="200" y="130" dominant-baseline="middle" text-anchor="middle" width="100">BASE</text>
</g>`;
*/
svg {
background: linen;
}
<svg id="drawing" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg">
<style>
line, rect {stroke-width: 1; stroke: navy; fill: none;}
text {fill: navy;}
</style>
</svg>
Свободный перевод ответа от участника @Paul LeBeau.
Хорошо, это не проблема, это просто упражнение по внедрению. Я не привожу результат, а лишь намекаю. Это основные элементы вашего SVG. <g> группирует элементы и может перемещаться с помощью атрибута преобразования.
<svg viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg">
<style>
line, rect {stroke-width: 1; stroke: navy; fill: none;}
text {fill: navy;}
</style>
<g transform="translate(200 150)">
<rect x="-50" y="-20" width="100" height="40" rx="10" />
<text dominant-baseline="middle" text-anchor="middle" width="100">Text 1</text>
<line x1="50" y1="0" x2="100" y2="60" />
</g>
</svg>
Элемент должен быть динамичным. Вы знаете размер каждого элемента и расстояние между ними. С помощью цикла forEach() вы можете перебрать все элементы в списке и «разложить» их. Я просто «добавляю» новые элементы SVG с помощью ... innerHTML + = ...
var prev = {
"Prev": [{
"type": "Prev1",
"Count": 1,
"Time": 0
},
{
"type": "Prev2",
"Count": 2,
"Time": 0
},
{
"type": "Prev3",
"Count": 3,
"Time": 0
},
]
};
var drawing = document.getElementById('drawing');
prev.Prev.forEach((p, i, arr) => {
let x = 55;
let y = 250/arr.length*i+50;
drawing.innerHTML += `<g transform="translate(${x} ${y})">
<rect x="-50" y="-20" width="100" height="40" rx="10" />
<text dominant-baseline="middle" text-anchor="middle" width="100">${p.type}</text>
<line x1="50" y1="0" x2="100" y2="${250/arr.length-y+50}" />
</g>`;
});
<svg id="drawing" viewBox="0 0 400 300" xmlns="http://www.w3.org/2000/svg">
<style>
line, rect {stroke-width: 1; stroke: navy; fill: none;}
text {fill: navy;}
</style>
</svg>