score:1
reorder elements in the dom
to reorder elements in the dom with d3 you can use selection.sort and selection.order:
// sort & then order:
selection.sort(function(a,b) {
return a.property - b.property;
})
.order();
selection.sort sorts a selection based on the bound data, a
and b
each represent a datum bound to a single element. the resulting behavior is essentially the same as array.sort, but rather than using an array, you are sorting elements in a selection using their bound data. the content of the function provided to selection.sort (the compare function) determines sorting order:
the compare function, which defaults to ascending, is passed two elements’ data a and b to compare. it should return either a negative, positive, or zero value. if negative, then a should be before b; if positive, then a should be after b; otherwise, a and b are considered equal and the order is arbitrary. (docs)
once we have a sorted selection we can apply selection.order()
, which re-inserts each element into the dom based on the selection's order. remember that elements drawn first can be covered by elements drawn later - first in the selection means potentially underneath everything.
so if we had something like this, where overlapping bars are drawn sequentially based on the order of a data array:
var bars = [
{value: 100},
{value: 50},
{value: 200},
{value: 70},
{value: 40},
{value: 120}
];
var height = 200;
var width = 500;
var svg = d3.select("body")
.append("svg")
.attr("height",height)
.attr("width",width);
var bars = svg.selectall("rect")
.data(bars)
.enter()
.append("rect")
.attr("width", 45)
.attr("height", function(d) { return d.value; })
.attr("y", function(d) { return height-d.value; })
.attr("x", function(d,i) { return i * 30 + 50; })
.attr("fill", function(d,i){ return d3.schemecategory10[i]; })
.attr("stroke","black")
.attr("stroke-width",1);
// order the bars:
bars.sort(function(a,b) {
return b.value - a.value;
}).order();
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
we can pull up the small bars, say, for greater visibility with a sort and order:
var bars = [
{value: 100},
{value: 50},
{value: 200},
{value: 70},
{value: 40},
{value: 120}
];
var height = 200;
var width = 500;
var svg = d3.select("body")
.append("svg")
.attr("height",height)
.attr("width",width);
var bars = svg.selectall("rect")
.data(bars)
.enter()
.append("rect")
.attr("width", 45)
.attr("height", function(d) { return d.value; })
.attr("y", function(d) { return height-d.value; })
.attr("x", function(d,i) { return i * 30 + 50; })
.attr("fill", function(d,i){ return d3.schemecategory10[i]; })
.attr("stroke","black")
.attr("stroke-width",1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
reposition based on order
as you can see above, this doesn't reset the x or y attribute of each bar to reflect the ordering on the z (as in your example). as in my basic example above, we can reset the x values based on i (this can be done by rescaling too, but is enough to be a separate question and answer):
var bars = [
{value: 100},
{value: 50},
{value: 200},
{value: 70},
{value: 40},
{value: 120}
];
var height = 200;
var width = 500;
var svg = d3.select("body")
.append("svg")
.attr("height",height)
.attr("width",width);
var bars = svg.selectall("rect")
.data(bars)
.enter()
.append("rect")
.attr("width", 45)
.attr("height", function(d) { return d.value; })
.attr("y", function(d) { return height-d.value; })
.attr("x", function(d,i) { return i * 30 + 50; })
.attr("fill", function(d,i){ return d3.schemecategory10[i]; })
.attr("stroke","black")
.attr("stroke-width",1)
bars = bars.sort(function(a,b) {
return a.value - b.value;
}).order();
bars.transition()
.attr("x", function(d,i) { return i * 30 + 50; })
.delay(500)
.duration(2000);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
see also: this question and answer which has a lot of similarities to the example you have: sorting and ordering are used while transitioning both length of bars and bar order.
Source: stackoverflow.com
Related Query
- How to rearrange the DOM order of svg elements based on their data values in a dynamically changing d3 vis?
- How to modify the content of an svg based dom using nodejs, d3 and jsdom?
- Why do my DOM elements lose their location attributes when I size my SVG based on container size?
- How to access the DOM element that correlates to a D3 SVG object?
- d3.js - How can I set the cursor to hand when mouseover these elements on SVG container?
- How to update elements of D3 force layout when the underlying data changes
- In d3, how to get the interpolated line data from a SVG line?
- How to update the fill color on existing svg elements with d3.js?
- How do I associate SVG elements generated by graphviz to elements in the DOT source code
- How to update elements of an HTML that the elements are created using data from a CSV file?
- Join existing elements of the DOM to data with d3.js
- How to create SVG elements of different types based on data?
- In D3, how can I create multiple elements for each data element based on value in data?
- How do you retrieve the key values of a nested data set in D3
- How do I scroll d3 elements while keeping a portion of the svg in a fixed position?
- How do I get the d3 svg points to stay in their correct position on the leaflet map when zooming?
- How to get SVG path data of TopoJSON feature without adding it to the DOM?
- How do you prevent the interference of MULTIPLE SVG elements (text labels) on mouseover of a different SVG element?
- How can the elements in SVG can't be dragged out of the scope of SVG?
- How to retrieve the key values of a nested data set in D3
- D3 - reordering elements based on their data
- How would I create my own color scale based on the id of my data in d3?
- How do I interpret the __transition__ property that D3 attaches to DOM elements as part of a transition?
- How can I get the dom svg element from d3 node data?
- Updating only those SVG elements where the underlying bound data has been modified
- d3.js: How to deal with svg elements that are being appended on the same position, one on top of the other?
- Dynamically set the width and height of SVG based on data
- How to bring foreignObject elements in SVG to the top layer?
- How to determine a SVG shape based off of data using d3.js
- How to simultaneously update the color of elements in a SVG when I mouseover elements of a second SVG using D3
More Query from same tag
- d3 chord diagram on angular2
- Transition of labels in D3.js: Rename label names on change and transition smoothly
- How to group labels in Timeline chart in JS
- C3.js chart title overlapped if I change the size of title
- Debugging Incorrectly Displaying Bars
- d3.js dynamic style filling only displays black bar chart
- How does datamaps display images instead of bubbles?
- D3.geo.bounds does not return bounding box?
- Getting access to individual area elements with d3
- How to implement collision avoidance of points in d3.js v5?
- d3.js plotting the graph on time series scale
- How can I find the translated co-ordinates of an SVG element?
- d3 Click to create circle and click to remove
- D3.js: Force-directed graph from adjacency matrix
- How to remove empty rows in tables when they are zero, and how to allow selection in only one table at a time?
- D3 Javascript loop doesn't render
- Is there a way to add a canvas element as an image to svg
- Using D3 transition method with data for scatter plot
- max and min values from json in d3
- pandas groupby to nested json -- dont want calculated fields
- Search for an element in D3 - force layout or tree
- How can I animate the top of my svg element like in this gif using d3.js?
- Drawing Multiple Lines in D3.js
- How to read nested json in d3.js pie chart?
- how to use d3.data().enter().call()
- D3 fetch from django serialized model json returning blank array
- svg coordinate of g element larger than other element
- How to load data to D3 chart from JSON when there are only tuples
- In D3 bar graph, y-axis ordinal scale is not aligning properly with bars
- Multiple Classes in SVG