Я пытаюсь реализовать эффект анимации, используя элементы круга svg для события наведения курсора на пути аккордов на диаграмме аккордов D3.
Вдохновением для этого испытания является следующая реализация диаграммы Санки:
https://bl.ocks.org/micahstubbs/ed0ae1c70256849dab3e35a0241389c9
Мне удалось вставить элементы круга в событие наведения мыши для аккордов.Однако мне трудно понять, как заставить их следовать по пути аккорда.(Строка 69-106 в следующем коде JS).
Мой код JS (chord.js)
//*******************************************************************
// CREATE MATRIX AND MAP
//*******************************************************************
var matrix, mmap, rdr;
d3.csv('data/out.csv', function(error, data) {
var mpr = chordMpr(data);
mpr.addValuesToMap('Source')
.setFilter(function(row, a, b) {
return (row.Source === a.name && row.Destination === b.name)
})
.setAccessor(function(recs, a, b) {
if (!recs[0]) return 0;
return +recs[0].Count;
});
matrix = mpr.getMatrix();
mmap = mpr.getMap();
rdr = chordRdr(matrix, mmap);
drawChords();
});
//*******************************************************************
// DRAW THE CHORD DIAGRAM
//*******************************************************************
function drawChords() {
var w = window.innerWidth || document.body.clientWidth,
h = 700,
r1 = h / 2,
r0 = r1 - 150;
var svg = d3.select("body").append("svg:svg")
.attr("width", w)
.attr("height", h)
.append("svg:g")
.attr("id", "circle")
.attr("transform", "translate(" + w / 2 + "," + h / 2 + ")");
var chord = d3.layout.chord()
.padding(.15)
.sortChords(d3.descending);
chord.matrix(matrix);
var arc = d3.svg.arc()
.innerRadius(r0*1.03)
.outerRadius(r0*1.03 + 20);
var path = d3.svg.chord()
.radius(r0);
var g = svg.selectAll("g.group")
.data(chord.groups())
.enter()
.append("g")
.attr("class", "group");
var paths = g.append("svg:path")
.style("stroke", function(d) { return fillcolor(rdr(d).gname); })
.style("fill", function(d) { return fillcolor(rdr(d).gname); })
.attr("d", arc)
.attr("class", "arcs");
var chordPaths = svg.selectAll("path.chord")
.data(chord.chords())
.enter().append("svg:path")
.attr("class", "chord")
.on("mouseover", function(d) {
//context = d3.select('canvas').node().getContext('2d');
//context.clearRect(0, 0, 1000, 1000);
//context.fillStyle = 'gray';
//context.lineWidth = '1px';
currentTime = 500;
current = currentTime * 0.15 * (0.5 + (Math.random()));
currentPos = this.getPointAtLength(current);
//context.beginPath();
//context.fillStyle = "black";
/*context.arc(
Math.abs(currentPos.x),
Math.abs(currentPos.y),
2,
0,
2 * Math.PI
);
context.fill();*/
currentpath = this;
svg.insert("circle")
.attr("cx",currentPos.x)
.attr("cy",currentPos.y)
.attr("r",2)
.style("stroke-opacity", 1)
.style("fill", this.style.fill)
.transition()
.duration(1000)
.ease(Math.sqrt)
.attr("cx",function(){
currentPos = currentpath.getPointAtLength(current+100);
return currentPos.x;
})
.attr("cy",function(){
currentPos = currentpath.getPointAtLength(current-100);
return currentPos.y;
})
.remove();
})
.style("fill", function(d) { return fillcolor(rdr(d.target).gname); })
.attr("d", path);
}
function fillcolor(segmentvalue){
if (segmentvalue.includes("Segment A")) {
return '#ff3a21'
} else if (segmentvalue.includes("Segment C")) {
return '#26bde2'
} else if (segmentvalue.includes("Segment D")) {
return '#fcc30b'
} else if (segmentvalue.includes("Segment B")) {
return '#dd1367'
} else if (segmentvalue.includes("Segment E")) {
return '#a1e972'
} else {
return '#72e8a4'
}
}
Вот HTML-код:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
#circle circle {
fill: none;
pointer-events: all;
}
path.chord {
fill-opacity: .6;
stroke: #000;
stroke-width: .25px;
}
</style>
</head>
<body>
<script src="d3/d3.js"></script>
<script src="d3/underscore.js"></script>
<script type="text/javascript" src="d3/gistfile1.js"></script>
<script type="text/javascript" src="js/chord.js"></script>
</body>
</html>
Здесьмой файл данных (out.csv):
Source,Destination,Count,
Segment A,Segment A,597.7731179,
Segment B,Segment A,428.4797097,
Segment C,Segment A,242.5536698,
Segment D,Segment A,39.18270781,
Segment F,Segment A,373.4118141,
Segment E,Segment A,342.1175938,
Segment B,Segment B,695.841404,
Segment C,Segment B,586.8204889,
Segment D,Segment B,519.0497198,
Segment F,Segment B,142.271554,
Segment E,Segment B,282.7048795,
Segment A,Segment B,552.8162888,
Segment C,Segment C,162.7852664,
Segment D,Segment C,150.6887517,
Segment F,Segment C,631.6468679,
Segment E,Segment C,611.0627425,
Segment A,Segment C,344.1286204,
Segment B,Segment C,395.710855,
Segment D,Segment D,141.5878005,
Segment F,Segment D,254.2566994,
Segment E,Segment D,483.4672747,
Segment A,Segment D,5.942896921,
Segment B,Segment D,185.6991357,
Segment C,Segment D,138.2424522,
Я реализовал достаточно близкое решение и разместил его по адресу:
https://jsfiddle.net/Edwig_Noronha/fb9j5v4t/