#html #css #svg #d3js
Есть SVG Path. Он генерируется по данным пользователя и может принимать вид как кривой, как видно на скрине, так и простой линии. Path генерируется в d3 через d3.line(...). Нужно реализовать возможность отображения маркеров на данной линии. Проблема в том, что эти маркеры должны идти друг рядом с другом с некоторым отступом. В данный момент, при моей реализации, их количество ограничено количеством опорных точек кривой. Как это решить и сделать так, чтобы они отображались "плотно" друг к другу? Может стоит использовать другой подход?
Ответы
Ответ 1
Вот так можно все посчитать в runtime: // ищем необходимую точку var p1 = path.node().getPointAtLength(d); // ищем точку чуть дальше по пути var p2 = path.node().getPointAtLength(d + len/1000); // считаем угол в полярных координатах второй точки относительно первой // и прибавляем к нему необходимый поворот var a = Math.atan2(p1.y - p2.y, p1.x - p2.x) + Math.PI/2; // считаем положение второй точки штриха за счет полученной только что нормали return `M${p1.x},${p1.y}L${p1.x+Math.cos(a)*size},${p1.y+Math.sin(a)*size}` render(); function render() { let size = 20, offset = 5, distance = 10+d3.select('#distance').node().value /5; let svg = d3.select('svg'); let path = svg.select('path'); let len = path.node().getTotalLength(); let count = Math.floor(len/distance); let data = Array(count).fill(0).map((d, i) => offset+len/count * i); svg.selectAll('path.marker').remove() svg.selectAll('path.marker') .data(data) .enter() .append('path') .classed('marker', true) .attr('d', d => { var p1 = path.node().getPointAtLength(d) var p2 = path.node().getPointAtLength(d + len/1000) var a = Math.atan2(p1.y - p2.y, p1.x - p2.x) + Math.PI/2; return `M${p1.x},${p1.y}L${p1.x+Math.cos(a)*size},${p1.y+Math.sin(a)*size}`; }) } path { fill:none; stroke:red; stroke-width:5px; }
Ответ 2
Способ с помощью векторного редактора Идея состоит в том, что маркеры присоединяются к узловым точкам. Поэтому, если добавить новые узловые точки, то появятся новые маркеры. В исходном примере было 5 узловых точек внутри линии и две точки на концах линии. Но на них не присоединялись маркеры, так как было указано на маркеры в середине: marker-mid="url(#marker-1)" Добавляем новые узловые точки: Сохраняем файл в формате *.svg. В принципе всё готово. Если нужно присоединить маркеры на концы линии, то добавляем: marker-start="url(#marker-1)" marker-end="url(#marker-1)" Подробнее о маркерах здесь.Ответ 3
Можно использовать такой приём: Вместо маркеров использовать атрибут stroke-dasharray с толщиной строки равной высоте маркера для одного патча. Расчет делается следующим образом: Длина Path в вашем примере равна 335px Допустим нам нужно 10 верт. столбиков. Их роль будет выполнять длина черты 3.5px и пробел между ними будет 30px В сумме это 33.5px - один из 10 сегментов линии. Высоту столбика будет играть ширина path stroke-width="20" Размещаем сверху второй патч, который не имеет разрывов:
Комментариев нет:
Отправить комментарий