2017-04-08 3 views
2

Ich versuche, diese Voronoi-Segmente basierend auf dem 'd.lon'-Wert bedingt zu färben. Wenn es positiv ist, möchte ich, dass es grün ist, wenn es negativ ist, möchte ich, dass es rot ist. Im Moment gibt es jedes Segment als grün zurück.Bedingte Füllung/Farbe von Voronoi-Segmenten

Selbst wenn ich meinen < Operanden zu> vertausche, wird immer noch grün zurückgegeben.

Live-Beispiel hier: https://allaffects.com/world/

Danke :)

JS

// Stating variables 
var margin = {top: 20, right: 40, bottom: 30, left: 45}, 
width = parseInt(window.innerWidth) - margin.left - margin.right; 
height = (width * .5) - 10; 

var projection = d3.geo.mercator() 
.center([0, 5 ]) 
.scale(200) 
.rotate([0,0]); 

var svg = d3.select("body").append("svg") 
.attr("width", width) 
.attr("height", height); 

var path = d3.geo.path() 
.projection(projection); 

var voronoi = d3.geom.voronoi() 
.x(function(d) { return d.x; }) 
.y(function(d) { return d.y; }) 
.clipExtent([[0, 0], [width, height]]); 

var g = svg.append("g"); 

// Map data 
d3.json("/world-110m2.json", function(error, topology) { 

// Cities data 
d3.csv("/cities.csv", function(error, data) { 
g.selectAll("circle") 
    .data(data) 
    .enter() 
    .append("a") 
       .attr("xlink:href", function(d) { 
        return "https://www.google.com/search?q="+d.city;} 
      ) 
    .append("circle") 
    .attr("cx", function(d) { 
      return projection([d.lon, d.lat])[0]; 
    }) 
    .attr("cy", function(d) { 
      return projection([d.lon, d.lat])[1]; 
    }) 
    .attr("r", 5) 
    .style("fill", "red"); 

}); 

g.selectAll("path") 
    .data(topojson.object(topology, topology.objects.countries) 
     .geometries) 
.enter() 
    .append("path") 
    .attr("d", path) 
}); 

var voronoi = d3.geom.voronoi() 
     .clipExtent([[0, 0], [width, height]]); 

    d3.csv("/cities.csv", function(d) { 
    return [projection([+d.lon, +d.lat])[0], projection([+d.lon, +d.lat]) [1]]; 
    }, function(error, rows) { 
    vertices = rows; 
     console.log(vertices); 
     drawV(vertices); 
    } 
); 

     function polygon(d) { 
      return "M" + d.join("L") + "Z"; 
     } 

     function drawV(d) { 
      svg.append("g") 
      .selectAll("path") 
      .data(voronoi(d), polygon) 
      .enter().append("path") 
      .attr("class", "test") 
      .attr("d", polygon) 

// This is the line I'm trying to get to conditionally fill the segment. 
      .style("fill", function(d) { return (d.lon < 0 ? "red" : "green" );}) 
      .style('opacity', .7) 
      .style('stroke', "pink") 
      .style("stroke-width", 3); 
     } 

JS EDIT

d3.csv("/static/cities.csv", function(data) { 
    var rows = []; 
    data.forEach(function(d){ 
     //Added third item into my array to test against for color 
     rows.push([projection([+d.lon, +d.lat])[0], projection([+d.lon, +d.lat]) [1], [+d.lon]]) 
    }); 

    console.log(rows); // data for polygons and lon value 
    console.log(data); // data containing raw csv info (both successfully log) 

    svg.append("g") 
    .selectAll("path") 
    .data(voronoi(rows), polygon) 
    .enter().append("path") 
    .attr("d", polygon) 
    //Trying to access the third item in array for each polygon which contains the lon value to test 
    .style("fill", function(data) { return (rows[2] < 0 ? "red" : "green");}) 
    .style('opacity', .7) 
    .style('stroke', "pink") 
    .style("stroke-width", 3) 
}); 

Antwort

1

Dies ist, was passiert: Ihre Zeilenfunktion ändert die Objekte von rows Array. Zu dem Zeitpunkt, an dem Sie die Funktion zum Füllen der Polygone aufrufen, gibt es keine d.lon mehr, und da d.lonundefined ist, wird der ternäre Operator zu false ausgewertet, was Ihnen "grün" gibt. diese

Check:

var d = {}; 
 

 
console.log(d.lon < 0 ? "red" : "green");

Welche erklärt auch, was Sie gesagt haben:

Auch wenn ich meine < Operanden tauschen zu>, ist es noch grün zurückkehrt.

Da d.lon nicht definiert ist, spielt es keine Rolle, welchen Operator Sie verwenden.

Das gesagt, müssen Sie Ihre ursprüngliche rows Struktur mit der lon Eigenschaft in den Objekten behalten.

Eine Lösung wird immer der Reihe Funktion befreien ...

d3.csv("cities.csv", function(data){ 
    //the rest of the code 
}) 

... und rows Array innerhalb der Callback-Erstellung:

var rows = []; 
data.forEach(function(d){ 
    rows.push([projection([+d.lon, +d.lat])[0], projection([+d.lon, +d.lat]) [1]]) 
}); 

Jetzt haben Sie zwei Arrays: rows, mit dem Sie die Polygone genau so erstellen können, wie Sie es gerade verwenden, und data, die die Werte lon enthält.

Alternativ können Sie alles in nur einem Array speichern (indem Sie einfach die Zeilenfunktion ändern). Dies ist die beste Lösung, da die d.lon Werte leichter in die Eingabeauswahl für die Polygone übernommen werden können. Es ist jedoch schwierig, eine funktionierende Antwort zu liefern, ohne es mit Ihrem tatsächlichen Code zu testen (normalerweise endet es mit dem OP-Sprichwort "es funktioniert nicht!").

+0

Danke Gerado :) Ich habe meinen Beispielcode aktualisiert und verlinkt Beispiel mit Ihren Vorschlägen.Sie werden sehen, dass ich sowohl die Daten- als auch die Zeilen-Arrays erfolgreich protokollieren kann. Ich versuche, Ihren zweiten Vorschlag zu implementieren, alles in einem Array zu halten, ich bin nicht in der Lage, die Zeilen-Daten zu durchlaufen und auf den .lon-Wert in meiner bedingten .style-Fill-Anweisung zuzugreifen. – William

+1

Wie gesagt, der einzige Weg, um Ihnen mit dem zweiten Vorschlag zu helfen, ist, wenn Sie einen funktionierenden Code bereitstellen (setzen Sie diesen Code in Ihren Link in einem Plunker/Fiddle? CodePen/Was auch immer, so können wir es modifizieren). Was den ersten Vorschlag betrifft, machst du es falsch. Probieren Sie es aus: '.style (" fill ", Funktion (d, i) {return data [i] .lon <0?" Rot ":" grün ";})'. –

+0

Vielen Dank: D Genau das habe ich versucht. Als richtig gekennzeichnet. – William