score:3
Accepted answer
On top of the comment about re-appending the groups and the answer about splitting the selection, you have to change the text position in your update selection...
labelArcs.transition().duration(1000)
.attr("transform", (d) => `translate(${arcLabels.centroid(d)})`);
...as well as changing the text values in the <tspan>
elements:
labelArcs.select(".type")
.text((d) => d.data.type);
labelArcs.select(".value")
.text((d) => commaFormat(d.data.percentage).toLocaleString() + " %");
Here is the resulting code:
async function draw() {
// Data
let dataset;
let dataTime;
const commaFormat = d3.format(",");
const timeFormat = d3.timeFormat("%d-%m-%Y %I:%M");
// Dimensions
let dimensions = {
width: 700,
height: 700,
margins: 10,
};
dimensions.ctrWidth = dimensions.width - dimensions.margins * 2;
dimensions.ctrHeight = dimensions.height - dimensions.margins * 2;
const radius = dimensions.ctrHeight / 3;
// Draw Image
const svg = d3
.select("#chart-area")
.append("svg")
.attr("width", dimensions.width)
.attr("height", dimensions.height);
const ctr = svg
.append("g") // <g>
.attr(
"transform",
`translate(${dimensions.margins}, ${dimensions.margins})`
);
const arc = d3
.arc()
.outerRadius(radius)
.innerRadius(radius * 0.8);
const arcLabels = d3
.arc()
.outerRadius(radius * 1.2)
.innerRadius(radius * 1.2);
const arcGroup = ctr
.append("g")
.attr(
"transform",
`translate(${dimensions.ctrHeight / 2}, ${dimensions.ctrWidth / 2})`
);
const dataTimestamp = svg
.append("text")
.attr(
"transform",
`translate(${dimensions.ctrHeight / 2}, ${dimensions.ctrWidth / 2})`
)
.attr("text-anchor", "middle")
.append("tspan")
.attr("x", "+0.2em")
.attr("y", "+2.5em")
.attr("font-size", 20);
//Labels
const labelsGroup = ctr
.append("g")
.attr(
"transform",
`translate(${dimensions.ctrHeight / 2}, ${dimensions.ctrWidth / 2})`
);
d3.json("https://raw.githubusercontent.com/1crisl/test/main/data.json").then((data) => {
const timeArray = data.map((record) => {
return record.unixTime;
});
const minTime = d3.min(timeArray);
const maxTime = d3.max(timeArray);
let i = timeArray.length - 1;
$("#dateLabel1").text(timeFormat(minTime));
$("#dateLabel2").text(timeFormat(maxTime));
$("#date-slider").slider({
max: timeArray.length - 1,
min: 0,
value: timeArray.length - 1,
change: (event, ui) => {
i = $("#date-slider").slider("value");
dataTime = data[i].unixTime;
dataset = data[i].data.filter(function(obj) {
return obj.percentage > "1";
});
update();
},
});
dataTime = data[i].unixTime;
dataset = data[i].data.filter(function(obj) {
return obj.percentage > "1";
});
update();
});
function update() {
// Scales
const colors = d3.quantize(d3.interpolateSpectral, dataset.length); //Generates a colour for each item in the dataset array
const colorScale = d3
.scaleOrdinal()
.domain(dataset.map((d) => d.type))
.range(colors);
//Define Pie Chart
const generationPie = d3
.pie()
.padAngle(0.005)
.value((d) => d.generation)
.sort(null);
//Pass dataset into Pie Chart
const slices = generationPie(dataset);
//JOIN DATA
const arcs = arcGroup.selectAll("path").data(slices);
//ENTER NEW DATA
arcs
.enter()
.append("path")
.attr("d", arc)
.attr("fill", (d) => colorScale(d.data.type))
.each(function(d) {
this._current = d;
});
//UPDATE
arcs.transition().duration(1000).attrTween("d", arcTween);
//REMOVE OLD DATA
arcs.exit().remove();
function arcTween(a) {
var i = d3.interpolate(this._current, a);
this._current = i(0);
return function(t) {
return arc(i(t));
};
}
//==============================================================
//Data timestamp
//Join
const dataTimeLabel = dataTimestamp.text(timeFormat(dataTime));
//Update
dataTimeLabel.transition().duration(1000);
//ENTER
dataTimeLabel.enter().text(timeFormat(dataTime));
//REMOVE
dataTimeLabel.exit().remove();
//==============================================================
//JOIN
const labelArcs = labelsGroup.selectAll("text").data(slices, d => d.data.type);
//ENTER
const textGroup = labelArcs
.enter()
.append("text")
.attr("transform", (d) => `translate(${arcLabels.centroid(d)})`);
textGroup
.append("tspan")
.attr("font-weight", "bold")
.attr("font-size", 14)
.attr("x", "-2em")
.attr("class", "type")
.text((d) => d.data.type);
textGroup
.append("tspan")
.attr("x", "-2.3em")
.attr("y", "+1.2em")
.attr("fill-opacity", 0.7)
.attr("font-size", 12)
.attr("class", "value")
.text((d) => commaFormat(d.data.percentage).toLocaleString() + " %");
//UPDATE
labelArcs.select(".type")
.text((d) => d.data.type);
labelArcs.select(".value")
.text((d) => commaFormat(d.data.percentage).toLocaleString() + " %");
labelArcs.transition().duration(1000)
.attr("transform", (d) => `translate(${arcLabels.centroid(d)})`);
//REMOVE
labelArcs.exit().remove();
}
}
draw();
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta name="description" content="">
<title>Visualisation</title>
<!-- Bootstrap -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!-- jQueryUI styling -->
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
</head>
<body>
<!-- Bootstrap grid setup -->
<div class="container">
<div class="row">
<div class="col-md-12 d-flex justify-content-center">
<div id="chart-area"></div>
</div>
<div class="col-md-12 d-flex justify-content-center">
<div id="slider-div">
<label>Data Extent</label>
<br>
<label><span id="dateLabel1">01/01/2000</span> to <span id="dateLabel2">18/03/2021</span></label>
<div id="date-slider"></div>
</div>
</div>
</div>
</div>
<!-- External JS libraries -->
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
<!-- Custom JS -->
<script src="js/main.js"></script>
</body>
</html>
PS: your percentages are way off.
score:1
Try to split code:
const textGroup = labelArcs
.enter()
.append("text")
.attr("transform", (d) => `translate(${arcLabels.centroid(d)})`)
textGroup.append("tspan")
.attr("font-weight", "bold")
.attr("font-size", 14)
.attr("x", "-2em")
.text((d) => d.data.type)
textGroup.append("tspan")
.attr("x", "-2.3em")
.attr("y", "+1.2em")
.attr("fill-opacity", 0.7)
.attr("font-size", 12)
.text((d) => commaFormat(d.data.percentage).toLocaleString() + " %")
If it does not help, please provide a snippet of a fiddle to work with
Source: stackoverflow.com
Related Query
- How to use an exit selection on text with tspan
- How to append a text element with inline tspan children?
- How to use D3 selectAll with multiple class names
- How do I resolve "[ERR_REQUIRE_ESM]: Must use import to load ES Module" when using D3.js 7.0.0 with Next.js 11.0.1?
- How can I use d3 classed selection to have name as function
- How to use 'this' in Angular with D3?
- How to put text data with d3.js
- How to use D3 zoom behavior with ViewBox instead of transform
- How can I use d3-scale-chromatic functions with a domain other than [0, 1]?
- How to use x and width in a bar chart with scaleTime?
- With D3, how can I set attribute ("fill", "none") of axis path and line, but not text (without editing stylesheet)
- How do I implement d3's enter update exit pattern for an area chart with focus and context?
- How to update the contents of a text input with d3?
- How to limit the text of polygons in Voronoi diagram with D3.js?
- How to use D3 force layout with existing SVG elements as nodes
- how to use .scale and .translate with d3.js?
- How to use d3.symbols with an ordinal scale
- How to use d3's each method with ES6 arrow notation
- How to use Leaflet.js plugin with Stamen maps?
- How to Use D3 charts with angular 2 or 4
- how to use svg:defs to create rect with same height in d3.js?
- How to enable text selection in a D3.js-SVG that has zoom enabled?
- How to properly use the Use tag in SVG with d3 js?
- How to make D3.js use UTC times for the x-axis, with Moment.js
- How do I use d3.js to display text in an SVG rect only if the text will fit?
- how to add array of text to multiple divs with d3
- D3 How to update the chart after selection from drop down menu with new data
- How can I use D3.js "onClick" event with an nvd3 bar when zoomed in on chart data?
- How to use d3 v4 with Polymer 2.0 classes?
- How to use the quantize function with my json data file
More Query from same tag
- How can I remove spurious line on zoomable sunburst?
- D3 force layout graph zoom functionality
- How does d3.svg.diagonal() read bound data?
- Removing unwanted axes on small multiples in D3
- Python json.dump() to javascript JSON.parse()
- How to overwrite the array inside a function?
- use d3 treemap to go upto child on going on clicking parent to child nodes
- d3pie.js formatted value displaying
- What counts as inline-svg
- Trigger 2 mouseover events after hovering on a Bar of Bar Chart created using d3.js?
- How to convert to D3's JSON format?
- How to show the barlength in px of a SVG above the mouse pointer
- Waiting for rendering a chart till data has loaded
- D3 force layout by node size
- D3.Js charts in excel
- D3.js cluster node is overlapping
- Issue creating overlapping multiple pie charts (circular progress bars)
- CSS in Dynamically generated angular component
- A list of event types that d3js supports
- drag svg element onto HTML element
- d3.js Force Chart online now app with different symbol shapes
- Using a range slider to change the radius of an SVG circle
- Creating a force layout in D3.js visualisation library
- Add a "Select All" checkbox to lists of checkboxes that update an array of objects
- How do I use mutationobserver instead of mutation events?
- dc.js reductio helper function, how to get output in object format
- Using vanilla JS selectors with D3.js
- Modify Cubism.js Graphite Title Text
- d3js v5: Create a SVG with groups from a JSON file
- mouseover on d3 force layout bubbles not working