官术网_书友最值得收藏!

Sorting with data

In many cases, it is desirable to sort your visual elements according to the data they represent so that you can highlight the significance of different elements visually. In this recipe, we will explore how this can be achieved in D3.

Getting ready

Open your local copy of the following file in your web browser:

https://github.com/NickQiZhu/d3-cookbook-v2/blob/master/src/chapter3/data-sort.html .

How to do it...

Let's take a look at how data-driven sorting and further manipulation can be performed using D3. In this example, we will sort the bar chart we created in the previous recipe based on either expense (width) or category, using a user's input:

<script type="text/javascript"> 
    var data = [ // <-A 
        {expense: 10, category: "Retail"}, 
        {expense: 15, category: "Gas"}, 
        {expense: 30, category: "Retail"}, 
        {expense: 50, category: "Dining"}, 
        {expense: 80, category: "Gas"}, 
        {expense: 65, category: "Retail"}, 
        {expense: 55, category: "Gas"}, 
        {expense: 30, category: "Dining"}, 
        {expense: 20, category: "Retail"}, 
        {expense: 10, category: "Dining"}, 
        {expense: 8, category: "Gas"} 
    ]; 
    function render(data, comparator) { 
        var bars = d3.select("body").selectAll("p.h-bar") // <-B 
                .data(data); 
        // Enter 
        bars.enter().append("p") // <-C 
                .attr("class", "h-bar") 
                .append("span"); 
        // Update 
        d3.selectAll("p.h-bar") // <-D 
                .style("width", function (d) { 
                    return (d.expense * 5) + "px"; 
                }) 
                .select("span") 
                .text(function (d) { 
                    return d.category; 
                }); 
        // Sort 
        if(comparator) 
            bars.sort(comparator); // <-E 
    } 
    var compareByExpense = function (a, b) {  // <-F 
        return a.expense < b.expense?-1:1; 
    }; 
    var compareByCategory = function (a, b) {  // <-G 
        return a.category < b.category?-1:1; 
}; 
 
    render(data); 
     
    function sort(comparator) { 
        render(data, comparator); 
    } 
</script> 
 
<p class="control-group"> 
    <button onclick="sort(compareByExpense)"> 
        Sort by Expense 
    </button> 
    <button onclick="sort(compareByCategory)"> 
        Sort by Category 
    </button> 
    <button onclick="sort()"> 
        Reset 
    </button> 
</p> 

This preceding code generates sorted horizontal bars as shown in the following screenshot:

Data-based Sorting

How it works...

In this recipe, we set up a simple row-based visualization (in lines B, C, and D) of some simulated personal expense records containing two attributes, expense and category, that are defined on line A. This is almost exactly the same as the previous recipe and quite similar to what we have done in the Binding object literals as data recipe. Once the basics are done, we then select all existing bars on line E and perform sorting using D3's selection.sort function:

        // Sort 
        if(comparator) 
            bars.sort(comparator); // <-E 

The selection.sort function accepts a comparator function:

var compareByExpense = function (a, b) {  // <-F 
    return a.expense < b.expense?-1:1; 
}; 
var compareByCategory = function (a, b) {  // <-G 
    return a.category < b.category?-1:1; 
}; 

The comparator function receives two data elements: a and b, to compare, returning either a negative, positive, or zero value. If the value is negative, a will be placed before b; if positive, a will be placed after b; otherwise, a and b are considered equal and the order is arbitrary. The sort() function returns a new selection with all elements sorted in an order that is determined by the specified comparator function. The newly returned selection can then be manipulated further to generate the desired visualization.

Note

As a and b are placed arbitrarily when they are equal, D3 selection.sort is not guaranteed to be stable; however, it is guaranteed to be consistent with your browser's built-in sort method on arrays.

主站蜘蛛池模板: 镇赉县| 乾安县| 成武县| 湖南省| 汝阳县| 庆城县| 浦城县| 肥城市| 施甸县| 广南县| 年辖:市辖区| 衡水市| 肇州县| 左云县| 读书| 松桃| 红安县| 吴旗县| 顺昌县| 邢台市| 邢台市| 马公市| 长顺县| 霞浦县| 博白县| 大石桥市| 景宁| 花垣县| 临泉县| 焦作市| 雷山县| 依兰县| 富顺县| 密山市| 清涧县| 寻乌县| 雷州市| 商丘市| 合江县| 饶平县| 龙井市|