HTML:
<svg id="svg" xmlns="http://www.w3.org/2000/svg">
<defs>
<marker id="arrowhead" fill="#FFF" markerWidth="10" markerHeight="3" refX="0" refY="1.5" orient="auto">
<polygon points="0 0, 2 1.5, 0 3" />
</marker>
</defs>
<circle class="circle-on-path" cx="0" cy="0" r="4" fill="#FFF">
<animateMotion dur="5s" repeatCount="indefinite">
<mpath xlink:href="#path_0"/>
</animateMotion>
</circle>
</svg>
CSS:
/*svg상의 path에 drop-shadow 효과를 주기 위해서는 svg태그에 filter를 정의한다.*/
svg {
filter:drop-shadow(0 0 2px black);
}
/*path의 선굵기, 색, 스타일을 정의한다.*/
svg path {
fill:none;
stroke:rgba(255, 255, 255, 0.6);
vector-effect:non-scaling-stroke;
stroke-width:2.5;
stroke-linejoin:round;
}
/*path:hover시 색을 정의한다. stroke만 변경 시,
path에 연결된 marker-end 개체의 색이 다르게 표시되므로 선색과 동일한 marker개체를 defs태그안에 정의한다. */
svg path:hover {
stroke:rgba(255, 0, 0, 0.3);
/*marker-end:url("#arrowhead-hover")!important;*/
}
Javascript:
//path개체를 생성한다. path와 marker를 연결하기 위해, path에 id속성을 추가한다.
function createPath(d, idx) {
var path = $(document.createElementNS('http://www.w3.org/2000/svg', "path"));
path.attr({
"id":`path${idx}`;
"maker-end":"url(#arrowhead)",
"d":d
});
return path;
}
var $svg = $("#svg");
$(".circle-on-path").hide();
$svg
.on("mouseenter", "path", function(e) {
var target = e.currentTarget;
//svg개체는 z-index와 상관없이 엘리먼트 정의순으로 렌더링 되므로
//:hover된 개체를 최상위로 표시하기 위해 맨아래로 이동한다.
$svg.append(target);
//path를 따라 움직일 .circle-on-path개체를 해당 path에 연결한다.
//dur값이 고정값 일 경우, 선의 길이에 따라 이동하는 속도가 다르므로,
//선 길이에 따라 동일한 속도가 동일하도록 dur값을 설정한다.(초당 150씩 이동하도록 계산)
$(".circle-on-path")
.find("mpath").attr("xlink:href", `#${target.id}`).end()
.find("animateMotion").attr("dur", Math.ceil(target.getTotalLength() / 150)).end()
.appendTo($svg)
.show();
})
.on("mouseout", "path", function(e) {
$(".circle-on-path").hide();
});
createPath("M190 658 L 190 658, 226 644, 242 558, 275 508,", 1);
createPath("M309 419 L 309 419, 311 417, 319 420, 319 427, 319 427, 459 575, 431 572, ", 2);