首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >D3-和弦:弦上流动的圆圈元素-路径滑鼠

D3-和弦:弦上流动的圆圈元素-路径滑鼠
EN

Stack Overflow用户
提问于 2018-11-13 10:22:55
回答 1查看 217关注 0票数 0

我试图在D3 chord图中的chord路径的鼠标越界事件上使用svg循环元素来实现动画效果。

这项试验的灵感来自以下sankey图的实现:

https://bl.ocks.org/micahstubbs/ed0ae1c70256849dab3e35a0241389c9

我成功地将圆圈元素插入到和弦的鼠标过关事件中。然而,我很难弄清楚如何让他们走和弦的道路。(以下JS代码中的第69-106行)。

我的JS代码(chord.js)

代码语言:javascript
复制
//*******************************************************************  
//  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:

代码语言:javascript
复制
<!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):

代码语言:javascript
复制
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,

我已经实现了一个足够接近的解决方案,并将其托管在:

Noronha/fb9j5v4t/

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-12-07 12:21:16

代码语言:javascript
复制
//*******************************************************************
//  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(),function(d,i){return i;})
        .enter().append("svg:path")
        .attr("class", "chord")
        .attr("id", function(d,i){return "chord"+i})
        .on("mouseover", function(d,i) {
              this.classList.add("hovered");
              currentpath = this;
              startPoint = pathStartPoint(currentpath);

              function loop(thispath) {
                if (!thispath.classList.contains("hovered")) return;
                setTimeout(function () {
                    particle = svg.insert("circle")                
                        .attr("class",function(){return currentpath.getAttribute("id")+"-circle"})
                        .attr("r",2)
                        .style("stroke-opacity", 1)
                        .style("fill", currentpath.style.fill)
                        .attr("transform", "translate(" + startPoint[0] + "," + startPoint[1] + ")")
                        .transition()
                        .duration(2000)
                        .attrTween("transform", translateAlong(currentpath))
                        .remove();
                    loop(thispath);
                }, 300);
              }

            loop(this);                                         
        })
        .on("mouseout",function(d,i){
            this.classList.remove("hovered");
        })
        .style("fill", function(d) { return fillcolor(rdr(d.target).gname); })
        .attr("d", path);
}

//Get path start point for placing marker
function pathStartPoint(path) {        
    var d = path.getAttribute("d");
    var dsplitted = d.split(" ");
    return dsplitted[1].split(",");
};

function translateAlong(path) {
    var l = path.getTotalLength();
    var t0 = 0;
    return function(i) {        
        return function(t) {                     
            var p0 = path.getPointAtLength(t0 * l);//previous point
            var p = path.getPointAtLength(t * l);////current point
            t0 = t;
            var centerX = p.x,
            centerY = p.y;
            return "translate(" + centerX + "," + centerY + ")"//rotate(" + angle + " 24" + " 12" +")";
        }
    }
}

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'
    }
}  

chord.js文件中的上述更改实现了足够接近的转换。

工作代码托管于:

Noronha/fb9j5v4t/

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53278827

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档