2017-12-15 5 views
2

Derzeit versuche ich ein dynamisches Kreisdiagramm zu entwerfen, bei dem sich die Scheiben des Kreisdiagramms entsprechend den zufällig generierten Daten ändern. Unten ist der Code.Jede Auswahl in D3 Kreisdiagramm

var dataset = [ 
 
    { name: 'Smooth', percent: 40.00, class: 'custom-normal' }, 
 
    { name: 'Moderate', percent: 10.00, class: 'custom-warning' }, 
 
    { name: 'Heavy', percent: 50.00, class: 'custom-danger' } 
 
]; 
 
var width = 960, 
 
    height = 500, 
 
    radius = Math.min(width, height)/2; //Math.min return the smallest value between width and height (for optimization purposes) 
 

 
var colorValues = d3.scaleOrdinal().domain(["Smooth", "Moderate", "Heavy"]).range(["#605A4C", "#ff9900", "#ff1a1a"]); 
 
var percent = "percent"; //predefine the legend of dataset (the string index) 
 
var category = "class"; 
 
var name = "name"; 
 

 
var pie = d3.pie() 
 
    .value(function(d) { return d[percent]; }) 
 
    .sort(null) 
 
    .padAngle(.02); //the gap 
 

 
var arc = d3.arc() 
 
    .innerRadius(radius - 100) //optimization 
 
    .outerRadius(radius - 20); //optimization 
 

 
var svg = d3.select("#chart") 
 
    .append("svg") 
 
    .attrs({ 
 
     width: width, 
 
     height: height, 
 
     class: "shadow" 
 
    }).append("g") 
 
    .attrs({ 
 
     transform: 'translate(' + width/2 + ',' + height/2 + ')' 
 
    }); 
 
svg.append('g') 
 
    .attrs({ 
 
     class: 'slices' 
 
    }); 
 

 
var path = svg.select('.slices') 
 
    .selectAll('path') 
 
    .data(pie(dataset)) 
 
    .enter().append('path') 
 
    .attrs({ 
 
     d: arc 
 
    }).each(function(d, i) { 
 
     this._current = d; 
 
     console.log(this._current); 
 
     console.log('okay!'); 
 
    }).attrs({ 
 
     class: function(d, i){ 
 
     return d[category]; 
 
     }, 
 
     fill: function(d, i) { 
 
      console.log("this is color value" + colorValues()); 
 
      return colorValues(d[i]); 
 
     } 
 
    }); //initial details (this._current) 
 

 

 
var randomGenerator = setInterval(function() { 
 
    var data = dataset.map(function(d, i) { 
 
     for (var key in d) { 
 
      if (d[key] === "Smooth") { 
 
       //console.log("smooth"); 
 
       dataset[0].percent = Math.floor(Math.random() * 100); 
 
       //console.log(dataset[0].percent); 
 
      } else if (d[key] === "Moderate") { 
 
       dataset[1].percent = Math.floor(Math.random() * 100); 
 
       //console.log(dataset[1].percent); 
 
       //console.log("moderate"); 
 
      } else if (d[key] === "Heavy") { 
 
       dataset[2].percent = Math.floor(Math.random() * 100); 
 
       //console.log(dataset[2].percent); 
 
       //console.log("heavy"); 
 
      } 
 
     } 
 

 
    }); 
 

 
}, 3000); 
 

 

 
var timer = setInterval(function() { 
 
    pie.value(function(d) { 
 
     return d[percent]; 
 
    }); // change the value function 
 
    path = path.data(pie(dataset)); // compute the new angles 
 
    path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs 
 
}, 3000); 
 

 

 
// Store the displayed angles in _current. 
 
// Then, interpolate from _current to the new angles. 
 
// During the transition, _current is updated in-place by d3.interpolate. 
 
function arcTween(a) { 
 
    var i = d3.interpolate(this._current, a); 
 
    console.log(this._current); 
 
    this._current = i(0); 
 
    return function(t) { 
 
     return arc(i(t)); 
 
    }; 
 
}
body { 
 
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 
 
    margin: auto; 
 
    position: relative; 
 
    width: 960px; 
 
}
<meta charset="utf-8"> 
 
<div id="mydiv" class="widget"> 
 
    <div id="chart" class="Chart chart-container"></div> 
 
</div> 
 
<script src="https://d3js.org/d3.v4.js"></script> 
 
<script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>

Beachten Sie, dass die Farbe der einzelnen Scheiben nicht skaliert wird, nach dem, was ich früher definiert haben. d.h.: var colorValues = d3.scaleOrdinal().domain(["Smooth", "Moderate", "Heavy"]).range(["#605A4C", "#ff9900", "#ff1a1a"]);. Ich glaube, es sollte das Auswahlproblem sein, aber ich habe keine Ahnung davon gefunden. Und doch, auch die Klasse, bekommt sie nur die erste Datenzeile in var dataset und gilt für alle. Bitte helfen Sie mir bitte und danke im Voraus.

Antwort

3

Wenn ich richtig verstehe,

Durch Ihre Daten durch die Torte Funktion schieben, sind zu ändern Sie Ihre Daten. Im Laufe der ersten Struktur ist:

{ name: 'Smooth', percent: 40.00, class: 'custom-normal' } 

Nachdem diese Daten durch die Pastete Funktion ausgeführt wird, das Datum zu jedem Bogen gebunden hat die folgende Struktur:

{ 
    "data": { 
    "name": "Heavy", 
    "percent": 48, 
    "class": "custom-danger" 
    }, 
    "index": 2, 
    "value": 50, 
    "startAngle": 3.1515926535897933, 
    "endAngle": 6.283185307179586, 
    "padAngle": 0.02 
} 

In Ihrem Code sind Färben Sie die Keile basierend auf Dieser:

fill: function(d, i) { 
    console.log("this is color value" + colorValues()); 
    return colorValues(d[i]); 
} 

die d in function(d) {} zum Bezug Bezug nimmt, so ist es nur ein einzelne Element in den Eingangsdaten (der Nullpunkt auf eine Stufe gebunden (genauer Bogen), der ein Objekt ist - die Verwendung von d [Zahl] lässt vermuten, dass Sie ein Array erwarten. In jedem Fall erhalten Sie bei jeder Ausführung dieser Funktion undefined.

Zugriff Anstatt die Eigenschaft des Datums Sie wollen: name (ich nehme an) und Verwendung:

fill: function(d, i) { 
    console.log("this is color value" + colorValues()); 
    return colorValues(d.data.name); 
} 

var dataset = [ 
 
    { name: 'Smooth', percent: 40.00, class: 'custom-normal' }, 
 
    { name: 'Moderate', percent: 10.00, class: 'custom-warning' }, 
 
    { name: 'Heavy', percent: 50.00, class: 'custom-danger' } 
 
]; 
 
var width = 960, 
 
    height = 500, 
 
    radius = Math.min(width, height)/2; //Math.min return the smallest value between width and height (for optimization purposes) 
 

 
var colorValues = d3.scaleOrdinal().domain(["Smooth", "Moderate", "Heavy"]).range(["#605A4C", "#ff9900", "#ff1a1a"]); 
 
var percent = "percent"; //predefine the legend of dataset (the string index) 
 
var category = "class"; 
 
var name = "name"; 
 

 
var pie = d3.pie() 
 
    .value(function(d) { return d[percent]; }) 
 
    .sort(null) 
 
    .padAngle(.02); //the gap 
 

 
var arc = d3.arc() 
 
    .innerRadius(radius - 100) //optimization 
 
    .outerRadius(radius - 20); //optimization 
 

 
var svg = d3.select("#chart") 
 
    .append("svg") 
 
    .attrs({ 
 
     width: width, 
 
     height: height, 
 
     class: "shadow" 
 
    }).append("g") 
 
    .attrs({ 
 
     transform: 'translate(' + width/2 + ',' + height/2 + ')' 
 
    }); 
 
svg.append('g') 
 
    .attrs({ 
 
     class: 'slices' 
 
    }); 
 

 
var path = svg.select('.slices') 
 
    .selectAll('path') 
 
    .data(pie(dataset)) 
 
    .enter().append('path') 
 
    .attrs({ 
 
     d: arc 
 
    }).each(function(d, i) { 
 
     this._current = d; 
 
     console.log(this._current); 
 
     console.log('okay!'); 
 
    }).attrs({ 
 
     class: function(d, i){ 
 
     return d.data.class; 
 
     }, 
 
     fill: function(d, i) { 
 
      console.log("this is color value" + colorValues()); 
 
      return colorValues(d.data.name); 
 
     } 
 
    }); //initial details (this._current) 
 

 

 
var randomGenerator = setInterval(function() { 
 
    var data = dataset.map(function(d, i) { 
 
     for (var key in d) { 
 
      if (d[key] === "Smooth") { 
 
       //console.log("smooth"); 
 
       dataset[0].percent = Math.floor(Math.random() * 100); 
 
       //console.log(dataset[0].percent); 
 
      } else if (d[key] === "Moderate") { 
 
       dataset[1].percent = Math.floor(Math.random() * 100); 
 
       //console.log(dataset[1].percent); 
 
       //console.log("moderate"); 
 
      } else if (d[key] === "Heavy") { 
 
       dataset[2].percent = Math.floor(Math.random() * 100); 
 
       //console.log(dataset[2].percent); 
 
       //console.log("heavy"); 
 
      } 
 
     } 
 

 
    }); 
 

 
}, 3000); 
 

 

 
var timer = setInterval(function() { 
 
    pie.value(function(d) { 
 
     return d[percent]; 
 
    }); // change the value function 
 
    path = path.data(pie(dataset)); // compute the new angles 
 
    path.transition().duration(750).attrTween("d", arcTween); // redraw the arcs 
 
}, 3000); 
 

 

 
// Store the displayed angles in _current. 
 
// Then, interpolate from _current to the new angles. 
 
// During the transition, _current is updated in-place by d3.interpolate. 
 
function arcTween(a) { 
 
    var i = d3.interpolate(this._current, a); 
 
    console.log(this._current); 
 
    this._current = i(0); 
 
    return function(t) { 
 
     return arc(i(t)); 
 
    }; 
 
}
body { 
 
    font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 
 
    margin: auto; 
 
    position: relative; 
 
    width: 960px; 
 
}
<meta charset="utf-8"> 
 
<div id="mydiv" class="widget"> 
 
    <div id="chart" class="Chart chart-container"></div> 
 
</div> 
 
<script src="https://d3js.org/d3.v4.js"></script> 
 
<script src="https://d3js.org/d3-selection-multi.v0.4.min.js"></script>

+0

Danke für Ihre Hilfe Andrew. Ja, genau das habe ich gemeint. Kann ich jedoch wissen, wie ich das Klassenproblem lösen kann? Ich möchte die Klasse auch an jede einzelne Scheibe anhängen. – cypatrick

+0

Entschuldigung, das Snippet aktualisiert, um auf die Klasseneigenschaft zuzugreifen, die Sie 'd.data.class' verwenden würden, da die Klasse ursprünglich in d.class lag, aber nachdem Sie sie durch pie() ausgeführt haben, haben Sie d.data.class –

+0

@cpatrick Wenn diese Antwort Ihr Problem gelöst hat, sollten Sie [akzeptieren] (https://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work) in Betracht ziehen. Dies wird zukünftigen Lesern, die vor dem gleichen Problem stehen, helfen, die richtige Lösung zu finden. Siehe auch [* "Was bedeutet es, wenn eine Antwort" akzeptiert "ist?" *] (Https://stackoverflow.com/help/accepted-answer) und [* "Was soll ich tun, wenn jemand meine Frage beantwortet?" *] (https://stackoverflow.com/help/someone-answers). – altocumulus