Страницы

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

суббота, 28 декабря 2019 г.

Как изменить частоту размещения маркеров на SVG Path?

#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" Размещаем сверху второй патч, который не имеет разрывов: Так получилось, потому что толщина линии размещается симметрично относительно осевой линии. Пробовал обрезать третьим патчем нижние части столбиков, но не получается точно сместить командой transform="translate" Если вас не устроит такой вид, симметричного расположения верт. черточек, то придется искать решение JS Для прямых отрезков эту проблему можно решить с помощью подрезки третьим патчем.

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

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