2017-04-08 33 views
1

我有一個兩個環狀餅圖的視覺效果。 我在建的是: - 如果一個扇區的弧度對於指定的文本來說太小,那麼文本是隱藏的。這已完成,似乎工作正常 - 如果文本隱藏,則標籤應出現在餅圖的外面。當視覺初始呈現時,這也是完成的。如何停止屏幕上的文本過渡

當按下單選按鈕時,餅圖外的標籤應該相應地轉換。我嘗試過渡並將其放慢到3500,這些標籤只是慢慢地從屏幕上跳下來。

如何解決此過渡問題?

我已經加入到嘗試創建過渡的片段開始於行241:

var arcs2 = svg.data([json]).selectAll(".arcG"); 

arcs2.data(partition.nodes) 
    .transition() 
    .duration(3500) 
    .attr("transform", function(d) { 

    var c = arc.centroid(d), 
     x = c[0], 
     y = c[1], 
     // pythagorean theorem for hypotenuse 
     h = Math.sqrt(x * x + y * y); 
    return "translate(" + (x/h * labelr) + ',' + 
     (y/h * labelr) + ")"; 
    }) 
    .attr("text-anchor", "middle"); 


svg.selectAll(".theTxtsOuter") 
    .text(function(d, i) { 
    if (d.name === 'root') { 
     return; 
    } else if ((d.depth === 1) && (d.dx < (d.name.length * 0.15))) { 
     return d.name; 
    } else if ((d.depth === 2) && (d.dx < (d.name.length * 0.1))) { 
     return d.name; 
    } else { 
     return; 
    } 
    }); 

這是工作的一個視覺普拉克(!):

https://plnkr.co/edit/jYVPCL?p=preview

這裏是餡餅使用的完整JavaScript:

function pieChart(dataFile) { 

    var plot; 
    var vis; 

    var width = 400, 
    height = 400, 
    radius = Math.min(width, height)/2.1, 
    color = d3.scale.ordinal() 
    .range(["#338ABA", "#016da9", "#4c96d5"]) 
    .domain([0, 2]); 

    var labelr = radius + 5 // radius for label anchor 

    var div = d3.select("body") 
    .append("div") 
    .attr("class", "toolTip"); 



    var arc = d3.svg.arc() 
    .startAngle(function(d) { 
     return d.x; 
    }) 
    .endAngle(function(d) { 
     return d.x + d.dx; 
    }) 
    .outerRadius(function(d) { 
     return (d.y + d.dy)/(radius); 
    }) 
    .innerRadius(function(d) { 
     return d.y/(radius); 
    }); 


    //check if the svg already exists 
    plot = d3.select("#svgPIEChart"); 
    if (plot.empty()) { 
    vis = d3.select("#pieChart") 
     .append("svg") 
     .attr({ 
     id: "svgPIEChart" 
     }); 
    } else { 
    vis = d3.select("#svgPIEChart"); 
    vis.selectAll("*").remove(); 
    } 

    //group of the svg element 
    var svg = vis 
    .append("g") 
    .attr({ 
     'transform': "translate(" + width/2 + "," + height * .52 + ")" 
    }); 


    //svg element 
    vis.attr({ 
    //set the width and height of our visualization (these will be attributes of the <svg> tag 
    width: width, 
    height: height 
    }); 



    d3.text(dataFile, function(text) { 
    var csv = d3.csv.parseRows(text); 
    var json = buildHierarchy(csv); 

    // it seems d3.layout.partition() can be either squares or arcs 
    var partition = d3.layout.partition() 
     .sort(null) 
     .size([2 * Math.PI, radius * radius]) 
     .value(function(d) { 
     return d.SalesRev; 
     }); 

    var path = svg.data([json]).selectAll(".theArc") 
     .data(partition.nodes) 
     .enter() 
     .append("path") 
     .attr("class", "theArc") 
     .attr("id", function(d, i) { 
     return "theArc_" + i; 
     }) //Give each slice a unique ID 
     .attr("display", function(d) { 
     return d.depth ? null : "none"; 
     }) 
     .attr("d", arc) 
     .style("stroke", "#fff") 
     .style("fill", function(d) { 
     return color((d.children ? d : d.parent).name); 
     }) 
     .attr("fill-rule", "evenodd") 
     .style("opacity", 0.01) 
     .style("stroke-opacity", 0.01) 
     .each(stash); 


    path.transition() 
     .duration(PIEOBJ.transTime) 
     .style("opacity", 1) 
     .style("stroke-opacity", 1) 

    path 
     .on("mouseout", mouseout) 
     .on("mousemove", function(d) { 
     div.style("left", d3.event.pageX + 10 + "px"); 
     div.style("top", d3.event.pageY - 25 + "px"); 
     div.style("display", "inline-block"); 
     div.html(d.name + "<br>" + PIEOBJ.formatShrtInt(d.SalesRev)); 
     }) 



    var txts = svg.data([json]).selectAll(".theTxts") 
     .data(partition.nodes) 
     .enter() 
     .append("text"); 
    txts 
     .attr("class", "theTxts") 
     .attr("dx", 10) //Move the text from the start angle of the arc 
     .attr("dy", 15) //Move the text down 
     .style("opacity", 0) 
    txts 
     .transition() 
     .duration(PIEOBJ.transTime) 
     .style("opacity", 1); 



    var txtPths = txts.append("textPath") 
     // .attr("xlink:href", function(d, i) { 
     .attr("href", function(d, i) { 
     return "#theArc_" + i; 
     }) 
     .text(function(d) { 
     if (d.name === 'root') { 
      return; 
     } else if ((d.depth === 1) && (d.dx < (d.name.length * 0.15))) { 
      return; 
     } else if ((d.depth === 2) && (d.dx < (d.name.length * 0.1))) { 
      return; 
     } else { 
      return d.name; 
     } 
     }); 




    /* ------- TEXT LABELS OUTSIDE THE PIE-------*/ 
    //var arcs = svg.selectAll(".theArc"); 
    var arcs = svg.data([json]).selectAll(".arcG") 
     .data(partition.nodes) 
     .enter() 
     .append("g") 
     .attr("class", "arcG"); 

    arcs.append("text") 
     .attr("transform", function(d) { 

     var c = arc.centroid(d), 
      x = c[0], 
      y = c[1], 
      // pythagorean theorem for hypotenuse 
      h = Math.sqrt(x * x + y * y); 
     console.log(c, h); 
     return "translate(" + (x/h * labelr) + ',' + 
      (y/h * labelr) + ")"; 
     }) 
     .attr("text-anchor", "middle") 
     .text(function(d, i) { 
     if (d.name === 'root') { 
      return; 
     } else if ((d.depth === 1) && (d.dx < (d.name.length * 0.15))) { 
      return d.name; 
     } else if ((d.depth === 2) && (d.dx < (d.name.length * 0.1))) { 
      return d.name; 
     } else { 
      return; 
     } 
     }) 
     .attr("class", "theTxtsOuter"); 
    /* ----------------------------------------*/ 





    d3.selectAll("input").on("change", function change() { 


     function createValueFunc(val) { 
     // currentMeasure = val; 
     return function(d) { 
      return d[val]; 
     }; 
     } 

     value = createValueFunc(this.value); 

     PIEOBJ.currentMeasure = this.value; 

     var path2 = svg.data([json]).selectAll(".theArc"); 
     path2 
     .data(partition.value(value).nodes) 
     .transition() 
     .duration(1500) 
     .attrTween("d", arcTween) 
     .each("start", function() { 
      d3.select(this) 
      .on("mouseout", null) //CLEARING the listeners 
      .on("mousemove", null); 
     }) 
     .each("end", function() { 
      d3.select(this) 
      .on("mouseout", mouseout) //attaching the listeners 
      .on("mousemove", function(d) { 
       div.style("left", d3.event.pageX + 10 + "px"); 
       div.style("top", d3.event.pageY - 25 + "px"); 
       div.style("display", "inline-block"); 
       div.html(d.name + "<br>" + PIEOBJ.formatShrtInt(value(d))); 
      }); 
     }); 

     svg.selectAll("textPath") 
     .text(function(d) { 
      if (d.name === 'root') { 
      return; 
      } else if ((d.depth === 1) && (d.dx < (d.name.length * 0.15))) { 
      return; 
      } else if ((d.depth === 2) && (d.dx < (d.name.length * 0.1))) { 
      return; 
      } else { 
      return d.name; 
      } 
     }); 


     var arcs2 = svg.data([json]).selectAll(".arcG"); 

     arcs2.data(partition.nodes) 
     .transition() 
     .duration(3500) 
     .attr("transform", function(d) { 

      var c = arc.centroid(d), 
      x = c[0], 
      y = c[1], 
      // pythagorean theorem for hypotenuse 
      h = Math.sqrt(x * x + y * y); 
      return "translate(" + (x/h * labelr) + ',' + 
      (y/h * labelr) + ")"; 
     }) 
     .attr("text-anchor", "middle"); 


     svg.selectAll(".theTxtsOuter") 
     .text(function(d, i) { 
      if (d.name === 'root') { 
      return; 
      } else if ((d.depth === 1) && (d.dx < (d.name.length * 0.15))) { 
      return d.name; 
      } else if ((d.depth === 2) && (d.dx < (d.name.length * 0.1))) { 
      return d.name; 
      } else { 
      return; 
      } 
     }); 

     // the following deletes what was originally created and then recreates the text 
     // svg.selectAll("#titleX").remove(); 

    }); 



    function mouseout() { 
     div.style("display", "none"); //<< gets rid of the tooltip << 
    } 

    // Stash the old values for transition. 
    function stash(d) { 
     d.x0 = d.x; 
     d.dx0 = d.dx; 
    } 

    // Interpolate the arcs in data space. 
    function arcTween(a) { 
     var i = d3.interpolate({ 
     x: a.x0, 
     dx: a.dx0 
     }, a); 
     return function(t) { 
     var b = i(t); 
     a.x0 = b.x; 
     a.dx0 = b.dx; 
     return arc(b); 
     }; 
    } 

    }); 


} 

// // Take a 2-column CSV and transform it into a hierarchical structure suitable 
// // for a partition layout. 
function buildHierarchy(csv) { 
    var root = { 
    "name": "root", 
    "children": [] 
    }; 
    for (var i = 0; i < csv.length; i++) { 

    var sequence = csv[i][0]; 

    // var APD = +csv[i][1]; 
    var SalesRev = +csv[i][1]; 
    var Amount = +csv[i][2]; 

    if (isNaN(SalesRev)) { // e.g. if this is a header row 
     continue; 
    } 
    var parts = sequence.split("-"); 
    var currentNode = root; 
    for (var j = 0; j < parts.length; j++) { 
     var children = currentNode.children; 
     var nodeName = parts[j]; 
     var childNode; 
     if (j + 1 < parts.length) { 
     // Not yet at the end of the sequence; move down the tree. 
     var foundChild = false; 
     for (var k = 0; k < children.length; k++) { 
      if (children[k].name == nodeName) { 
      childNode = children[k]; 
      foundChild = true; 
      break; 
      } 
     } 
     // If we don't already have a child node for this branch, create it. 
     if (!foundChild) { 
      childNode = { 
      "name": nodeName, 
      "children": [] 
      }; 
      children.push(childNode); 
     } 
     currentNode = childNode; 
     } else { 
     // Reached the end of the sequence; create a leaf node. 
     childNode = { 
      "name": nodeName, 
      // "APD": APD, 
      "SalesRev": SalesRev, 
      "Amount": Amount 
     }; 
     children.push(childNode); 
     } 
    } 
    } 

    root.children.forEach(function(v) { 
    v.SalesRev = 0; 
    v.Amount = 0; 

    v.children.forEach(function(a) { 
     v.SalesRev += a.SalesRev; 
     v.Amount += a.Amount; 
    }); 
    }); 

    return root; 
} 

回答

1

當你最初定位它們,您正在轉換text元素。當您轉換它們時,您正在定位外部g元素。這些導致轉換衝突。使用方法:

arcs2.data(partition.nodes) 
    .select('text') //<-- apply on child text 
    .transition() 
    .duration(3500) 
    .attr("transform", function(d) { 
    ... 
    }); 

更新plunker

+0

優秀 - 現在我只需要弄清楚如何創建從每個片段的中心到每個標籤的轉換線! – whytheq