点击

时间:2017-03-22 16:18:45

标签: javascript d3.js sunburst-diagram

这是我在stackoverflow中的第一个问题,我希望你能帮我解决这个问题,而我还没有找到解决方案。我想在Web应用程序中使用D3 v4和sunburst可视化来显示和导航json文件给出的一些数据。我设法用sunburst(带工具提示)显示数据,当用户点击相应的弧时,它还允许使用转换放大到子项。

对于我的应用程序,我想使用一个初始的小json文件,它只显示完整(更大)数据的一部分。当用户点击弧(可以检索其他信息)时,这些小数据应按需扩展并在旭日动态中可视化。此外,当用户去"返回"对于父弧,应删除最近新添加的数据,以便仅再次显示初始数据。

所以工作流程:开始时有一个森伯斯特(data1);用户点击子弧;这个弧应该是旭日新的焦点/中心,同时初始数据扩展到(data2)更新旭日形象;用户看到新焦点和所选弧的新加载的子节点;当用户导航回来时,应再次显示(data1)。最后一部分仍然缺失,我将在稍后处理,但在此之前我遇到了问题。我设法在两个数据集之间实现切换,但新焦点和旭日行为的结果并不像预期的那样。 (data1)和(data2)是flare.json数据集中的部分数据示例,当点击arc" analytics"对于哪些新数据应加载和可视化,在转换后,其三个孩子(缺少"优化")中仅有两个("群集"和#34;图#34;)是显示。但是,另外点击" analytics"的弧线。揭示了越来越多失踪的第三个孩子。我点击的越多,"正确"结果以某种方式近似。

我在JSFiddle中创建了一个工作示例,展示了我的关注点和出现的问题。另外,这是代码:

var width = 500;
var height = 500;
var radius = Math.min(width, height) / 2 - 10;
var color = d3.scaleOrdinal(d3.schemeCategory20);

var x = d3.scaleLinear()
.range([0, 2 * Math.PI]);

var y = d3.scaleSqrt()
.range([0, radius]);

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height)
  .append("g")
    .attr("transform", "translate(" + width / 2 + "," + (height / 2 + 10) + ")");

var arc = d3.arc()
.padAngle(.01)
.padRadius(radius/3)
.startAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x0))); })
.endAngle(function(d) { return Math.max(0, Math.min(2 * Math.PI, x(d.x1))); })
.innerRadius(function(d) { return Math.max(0, y(d.y0)); })
.outerRadius(function(d) { return Math.max(0, y(d.y1)); });

var partition = d3.partition();
var root = d3.hierarchy( data1 ).count();

var g = svg.selectAll("g")
.data( partition(root).descendants(), function(d){return d.data.name;})
.enter().append("g");

var tt = d3.select("body").append("tt")
.attr("class", "tooltip")
.style("opacity", 0);

var path = g.append("path")
.attr("d", arc)
.style("stroke", "white")
.style('stroke-width', 0.5)
.attr( "id", function(d){ return 'path' + d.data.name; })
.style("fill", function(d) { return color((d.children ? d : d.parent).data.name); })
.style("opacity", 0)
.on("click", click)
.on("mouseover", function(d) {
    tt.transition()
    .duration(200)
    .style("opacity", 1.0);
    tt.html( showTooltipInfo(d) )
    .style("left", (d3.event.pageX) + "px")
    .style("top", (d3.event.pageY - 28) + "px");
})                  
.on("mouseout", function(d) {       
    tt.transition()
    .duration(500)
    .style("opacity", 0);
})
.each(function(d,i){
    this.xx0 = d.x0;
    this.xx1 = d.x1;
    this.yy0 = d.y0;
    this.yy1 = d.y1;
})
.transition()
.duration(1000)
.style("opacity", 1);

function showTooltipInfo(d){
    return d.data.name;
}

function click(d) {
    svg.selectAll("g").select("path")
    .transition()
    .duration(750)
    .attrTween("d", arcTweenZoom(d))
    .each(function(d,i){
        this.xx0 = d.x0;
        this.xx1 = d.x1;
        this.yy0 = d.y0;
        this.yy1 = d.y1;
    });
    var selectedD = d;

    setTimeout(function () {
        var newRoot;
        if (selectedD.data.name === "analytics")
            newRoot = d3.hierarchy( data2 ).count();
        else
            return;

        var groups = svg.selectAll("g")
        .data( partition(newRoot).descendants(), function(d){return d.data.name;} );

        groups.exit()
        .transition()
        .duration(10)
        .style("opacity", 0)
        .remove();

        groups.select("path")
        .transition()
        .duration(750)
        .attrTween("d", arcTweenData)
        .each(function(d,i){
            this.xx0 = d.x0;
            this.xx1 = d.x1;
            this.yy0 = d.y0;
            this.yy1 = d.y1;
        });

        groups.enter().append("g").append("path")
        .attr("d", arc)
        .style("stroke", "white")
        .style('stroke-width', 0.5)
        .attr( "id", function(d){ return 'path' + d.data.name; })
        .style("fill", function(d) { return color((d.children ? d : d.parent).data.name); })
        .style("opacity", 0)
        .on("click", click)
        .on("mouseover", function(d) {
            tt.transition()
            .duration(200)
            .style("opacity", 1.0);
            tt.html( showTooltipInfo(d) )
            .style("left", (d3.event.pageX) + "px")
            .style("top", (d3.event.pageY - 28) + "px");
        })                  
        .on("mouseout", function(d) {       
            tt.transition()
            .duration(500)
            .style("opacity", 0);
        })
        .each(function(d,i){
            this.xx0 = d.x0;
            this.xx1 = d.x1;
            this.yy0 = d.y0;
            this.yy1 = d.y1;
        })
        .transition()
        .delay(250)
        .duration(750)
        .style("opacity", 1);
    }, 500);
}

function arcTweenData(a){
    if ( this.xx0 !== undefined ){
        var oi = d3.interpolate({x0: this.xx0, x1: this.xx1, y0: this.yy0, y1: this.yy1}, a);
        var that = this;
        return function(t) {
            var b = oi(t);
            that.xx0 = b.x0;
            that.xx1 = b.x1;
            that.yy0 = b.y0;
            that.yy1 = b.y1;
            return arc(b);
        };
    }
}

function arcTweenZoom(d){
    var xd = d3.interpolate(x.domain(), [d.x0, d.x1]),
    yd = d3.interpolate(y.domain(), [d.y0, 1]),
    yr = d3.interpolate(y.range(), [d.y0 ? 20 : 0, radius]);
    return function(d, i){
        return i ? function(t){return arc(d)} : function(t){x.domain(xd(t)); y.domain(yd(t)).range(yr(t)); return arc(d);}
    }
}

数据集data1data2

var data1 = {
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": []
  },
  {
   "name": "animate",
   "children": [
    {"name": "Easing", "size": 17010},
    {"name": "FunctionSequence", "size": 5842},
    {
     "name": "interpolate",
     "children": [
      {"name": "ArrayInterpolator", "size": 1983},
      {"name": "ColorInterpolator", "size": 2047},
      {"name": "DateInterpolator", "size": 1375},
      {"name": "Interpolator", "size": 8746},
      {"name": "MatrixInterpolator", "size": 2202},
      {"name": "NumberInterpolator", "size": 1382},
      {"name": "ObjectInterpolator", "size": 1629},
      {"name": "PointInterpolator", "size": 1675},
      {"name": "RectangleInterpolator", "size": 2042}
     ]
    },
    {"name": "ISchedulable", "size": 1041},
    {"name": "Parallel", "size": 5176},
    {"name": "Pause", "size": 449},
    {"name": "Scheduler", "size": 5593},
    {"name": "Sequence", "size": 5534},
    {"name": "Transition", "size": 9201},
    {"name": "Transitioner", "size": 19975},
    {"name": "TransitionEvent", "size": 1116},
    {"name": "Tween", "size": 6006}
   ]
  }]
  };

var data2 = {
 "name": "flare",
 "children": [
  {
   "name": "analytics",
   "children": [
    {
     "name": "cluster",
     "children": [
      {"name": "AgglomerativeCluster", "size": 3938},
      {"name": "CommunityStructure", "size": 3812},
      {"name": "HierarchicalCluster", "size": 6714},
      {"name": "MergeEdge", "size": 743}
     ]
    },
    {
     "name": "graph",
     "children": [
      {"name": "BetweennessCentrality", "size": 3534},
      {"name": "LinkDistance", "size": 5731},
      {"name": "MaxFlowMinCut", "size": 7840},
      {"name": "ShortestPaths", "size": 5914},
      {"name": "SpanningTree", "size": 3416}
     ]
    },
    {
     "name": "optimization",
     "children": [
      {"name": "AspectRatioBanker", "size": 7074}
     ]
    }
   ]
  },
  {
   "name": "animate",
   "children": [
    {"name": "Easing", "size": 17010},
    {"name": "FunctionSequence", "size": 5842},
    {
     "name": "interpolate",
     "children": [
      {"name": "ArrayInterpolator", "size": 1983},
      {"name": "ColorInterpolator", "size": 2047},
      {"name": "DateInterpolator", "size": 1375},
      {"name": "Interpolator", "size": 8746},
      {"name": "MatrixInterpolator", "size": 2202},
      {"name": "NumberInterpolator", "size": 1382},
      {"name": "ObjectInterpolator", "size": 1629},
      {"name": "PointInterpolator", "size": 1675},
      {"name": "RectangleInterpolator", "size": 2042}
     ]
    },
    {"name": "ISchedulable", "size": 1041},
    {"name": "Parallel", "size": 5176},
    {"name": "Pause", "size": 449},
    {"name": "Scheduler", "size": 5593},
    {"name": "Sequence", "size": 5534},
    {"name": "Transition", "size": 9201},
    {"name": "Transitioner", "size": 19975},
    {"name": "TransitionEvent", "size": 1116},
    {"name": "Tween", "size": 6006}
   ]
  }]
  };

我在click方法中使用setTimeout调用的原因是,当我立即将切换应用于新数据时,click方法开头的第一个转换/缩放事件不会应用,因为切换发生得太快。在这种情况下,我的方法可能完全错误。

你知道我做错了什么或建议我如何才能更好地解决这个问题?

任何帮助表示赞赏!非常感谢你提前了!

0 个答案:

没有答案