2017-01-03 16 views
5

Próbuję "przetłumaczyć" parallel coordinates example na nową wersję d3 v4. Mam przykład pracy z tym javascript (która dodatkowo jest dobrym przykładem, jeśli ktoś stara się współpracować z v4 D3 i ma problemy z nowymi funkcjami):Dołączony tekst nie wyświetla się w d3 v4

var margin = {top: 30, right: 10, bottom: 10, left: 10}, 
    width = 600 - margin.left - margin.right, 
    height = 200 - margin.top - margin.bottom; 

var x = d3.scaleBand().rangeRound([0, width]).padding(1), 
    y = {}, 
    dragging = {}; 


var line = d3.line(), 
    //axis = d3.axisLeft(x), 
    background, 
    foreground, 
    extents; 

var svg = d3.select("#body").append("svg") 
    .attr("width", width + margin.left + margin.right) 
    .attr("height", height + margin.top + margin.bottom) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

d3.csv("cars.csv", function(error, cars) { 
    // Extract the list of dimensions and create a scale for each. 
    //cars[0] contains the header elements, then for all elements in the header 
    //different than "name" it creates and y axis in a dictionary by variable name 
    x.domain(dimensions = d3.keys(cars[0]).filter(function(d) { 
    if(d == "name") { 
     return false; 
    } 
    return y[d] = d3.scaleLinear() 
     .domain(d3.extent(cars, function(p) { 
      return +p[d]; })) 
     .range([height, 0]); 
    })); 

    extents = dimensions.map(function(p) { return [0,0]; }); 

    // Add grey background lines for context. 
    background = svg.append("g") 
     .attr("class", "background") 
    .selectAll("path") 
     .data(cars) 
    .enter().append("path") 
     .attr("d", path); 

    // Add blue foreground lines for focus. 
    foreground = svg.append("g") 
     .attr("class", "foreground") 
    .selectAll("path") 
     .data(cars) 
    .enter().append("path") 
     .attr("d", path); 

    // Add a group element for each dimension. 
    var g = svg.selectAll(".dimension") 
     .data(dimensions) 
    .enter().append("g") 
     .attr("class", "dimension") 
     .attr("transform", function(d) { return "translate(" + x(d) + ")"; }) 
     .call(d3.drag() 
     .subject(function(d) { return {x: x(d)}; }) 
     .on("start", function(d) { 
      dragging[d] = x(d); 
      background.attr("visibility", "hidden"); 
     }) 
     .on("drag", function(d) { 
      dragging[d] = Math.min(width, Math.max(0, d3.event.x)); 
      foreground.attr("d", path); 
      dimensions.sort(function(a, b) { return position(a) - position(b); }); 
      x.domain(dimensions); 
      g.attr("transform", function(d) { return "translate(" + position(d) + ")"; }) 
     }) 
     .on("end", function(d) { 
      delete dragging[d]; 
      transition(d3.select(this)).attr("transform", "translate(" + x(d) + ")"); 
      transition(foreground).attr("d", path); 
      background 
       .attr("d", path) 
      .transition() 
       .delay(500) 
       .duration(0) 
       .attr("visibility", null); 
     })); 
    // Add an axis and title. 
    g.append("g") 
     .attr("class", "axis") 
     .each(function(d) { d3.select(this).call(d3.axisLeft(y[d]));}) 
     //text does not show up because previous line breaks somehow 
    .append("text") 
     .style("text-anchor", "middle") 
     .attr("y", -9) 
     .text(function(d) { return d; }); 

    // Add and store a brush for each axis. 
    g.append("g") 
     .attr("class", "brush") 
     .each(function(d) { 
     d3.select(this).call(y[d].brush = d3.brushY().extent([[-8, 0], [8,height]]).on("brush start", brushstart).on("brush", brush_parallel_chart)); 
     }) 
    .selectAll("rect") 
     .attr("x", -8) 
     .attr("width", 16); 
}); 

function position(d) { 
    var v = dragging[d]; 
    return v == null ? x(d) : v; 
} 

function transition(g) { 
    return g.transition().duration(500); 
} 

// Returns the path for a given data point. 
function path(d) { 
    return line(dimensions.map(function(p) { return [position(p), y[p](d[p])]; })); 
} 

function brushstart() { 
    d3.event.sourceEvent.stopPropagation(); 
} 


// Handles a brush event, toggling the display of foreground lines. 
function brush_parallel_chart() {  
    for(var i=0;i<dimensions.length;++i){ 
     if(d3.event.target==y[dimensions[i]].brush) { 
      extents[i]=d3.event.selection.map(y[dimensions[i]].invert,y[dimensions[i]]); 

     } 
    } 

     foreground.style("display", function(d) { 
     return dimensions.every(function(p, i) { 
      if(extents[i][0]==0 && extents[i][0]==0) { 
       return true; 
      } 
      return extents[i][1] <= d[p] && d[p] <= extents[i][0]; 
     }) ? null : "none"; 
     }); 
} 

wszystko działa poprawnie (szczotkowanie na każdym z osie, zmieniając kolejność osi ...) z tym wyjątkiem, że etykiety na górze każdej osi nie są wyświetlane, mimo że znacznik tekstowy jest dołączony, a tekst jest zapisany w znaczniku (można sprawdzić, sprawdzając wynikowy html za pomocą przeglądarki). Wierzę, że kod odpowiedzialny za to jest ta część, ale nie jestem w stanie znaleźć przyczynę, dlaczego tak się dzieje:

g.append("g") 
     .attr("class", "axis") 
     .each(function(d) { d3.select(this).call(d3.axisLeft(y[d]));}) 
     //text does not show up because previous line breaks somehow 
    .append("text") 
     .style("text-anchor", "middle") 
     .attr("y", -9) 
     .text(function(d) { return d; }); 

Dlaczego etykiety tekstowe nie pokazać?

Odpowiedz

7

W D3 v4 komponent osi będzie jawnie ustawiać wypełnienie na none w zaznaczonym wywołaniu. Z source code:

selection.filter(entering) 
    .attr("fill", "none")  // <=== Fill set to none by D3 
    .attr("font-size", 10) 
    .attr("font-family", "sans-serif") 
    .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle"); 

To stworzy następujący kod:

enter image description here

w przeciwieństwie do kodu wygenerowanego przez v3:

enter image description here

W <text> elementy będą dziedziczyć te właściwości, ponieważ są dziećmi tych grup, wh ereby ukrywanie tekstów.

Aby wyświetlić etykiety musisz wyraźnie styl nich, co można zrobić

  1. Via CSS:

    .axis text { 
        fill:black; /* <== Set the fill */ 
        text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff; 
        cursor: move; 
    } 
    

    Praca demo.

  2. ustawiając atrybut fill na samego elementu <text>:

    .append("text") 
        .attr("fill", "black")   // <=== Set the fill 
    // .style("fill", "black")  // Will also work when using .style() 
        .style("text-anchor", "middle") 
        .attr("y", -9) 
        .text(function(d) { return d; }); 
    

    Praca demo.

+0

To nie są naprawdę działające wersje demonstracyjne. Wiem, że to nie było pytanie, ale pędzle nie działają w zamieszczonym przykładzie. Nie resetują filtrowania po usunięciu szczotki. – konrad

+0

@konrad Dema to tylko repliki kodu OP z jedną linią dodaną do rozwiązania problemu, o który chodziło w pytaniu. Nie twierdzę, że są one wolne od błędów lub w pełni funkcjonalne. – altocumulus

+0

Pewnie. Chciałem tylko wskazać to na wypadek, gdyby inni też to zauważyli. Chcesz się wypowiedzieć na temat ewentualnego rozwiązania tego problemu? – konrad