score:0

Accepted answer

Well, this could be way easier if you had a point scale for positioning the circles in the x axis. Since you have a linear scale, the function I wrote has some cumbersome parts...

First things first: you have to create a function that repaint the elements in the SVG. In the following demo, it's named draw, and we pass the series array to that function.

The most important part, however, is sorting the series array. This, for instance, is the function for sorting the blue dots and rearranging the orange ones accordingly:

d3.select("#button1").on("click", function() {
    series[0] = series[0].sort(function(a, b) {
        return d3.ascending(a.y, b.y)
    }).map(function(e, i) {
        return {
            x: i,
            fx: e.fx,
            y: e.y,
            u: e.u
        }
    });
    series[1].forEach(function(d, i, arr) {
        d.x = order0.indexOf(d.fx)
    });
    draw(series);
});

As you can see, sorting alone won't work, because the x property will be sorted together. Thus, we have to sort according to y and then reassign x from 0 to 10.

For keeping the object constancy, I created an property named u, using Math.random(). There is a very little chance that two properties have the same value. However, I advise you to create your own unique property in each object (otherwise you cannot keep object constancy). The fx property is just to keep track of the original sequence, and order0/order1 are arrays with the ordered sequence of each series.

Here is the demo, using most of your code but creating draw and reducing the SVG size, for better fit in a Stack snippet. Click the button to sort:

var data = d3.csvParse(d3.select("#csv").text());

var w = 600;
var h = 200;
var padding = 30;

//Define scale
var x = d3.scaleLinear().range([padding, w - padding * 2]);
var y = d3.scaleLinear().range([h - padding, padding]);
var z = d3.scaleOrdinal(d3.schemeCategory10);

var xAxis = d3.axisBottom().scale(x).ticks(10);
var yAxis = d3.axisLeft().scale(y).ticks(5);

//Define Canvas     
var svg = d3.select("body").append("svg")
  .attr("width", w).attr("height", h)

//Define clipping path
svg.append("clipPath").attr("id", "chart-area").append("rect")
  .attr("x", padding).attr("y", padding)
  .attr("width", w - padding * 3).attr("height", h - padding * 2);



// Extract yn using key
var seriesNames = d3.keys(data[0])
  .filter(function(d) {
    return d !== "x";
  })
  .sort();

// Map data to cartesian tuple {x,y}
var series = seriesNames.map(function(series) {
  return data.map(function(d, i) {
    return {
      x: +d.x,
      fx: +d.x,
      y: +d[series],
      u: Math.random()
    };
  });
});

var order0 = series[0].sort(function(a, b) {
  return d3.ascending(a.y, b.y)
}).map(function(e) {
  return e.x
});

var order1 = series[1].sort(function(a, b) {
  return d3.ascending(a.y, b.y)
}).map(function(e) {
  return e.x
});

// Compute domains
x.domain(d3.extent(d3.merge(series), function(d) {
  return d.x;
})).nice();
y.domain(d3.extent(d3.merge(series), function(d) {
  return d.y;
})).nice();

// X axis.
svg.append("g").attr("class", "axis").attr("transform",
  "translate(0," + (h - padding) + ")").call(xAxis)

// Y axis.
svg.append("g").attr("class", "axis").attr("transform",
  "translate(" + padding + ",0)").call(yAxis);

draw(series);

function draw(data) {

  // Append circles
  var groups = svg.selectAll(".series")
    .data(data);

  var groupsEnter = groups.enter()
    .append("g")
    .attr("class", "series")
    .style("fill", function(d, i) {
      return z(i);
    });

  var circlesEnter = groupsEnter.selectAll(".point")
    .data(function(d) {
      return d;
    }, function(e) {
      return e.u
    }).enter().append("circle")
    .attr("class", "point")
    .attr("cx", function(d) {
      return x(d.x);
    })
    .attr("cy", function(d) {
      return y(d.y);
    })
    .attr("r", 4);

  groups.selectAll(".point").data(function(d) {
      return d;
    }, function(e) {
      return e.u
    })
    .transition()
    .duration(2500)
    .attr("cx", function(d) {
      return x(d.x);
    })
    .attr("cy", function(d) {
      return y(d.y);
    })
    .attr("r", 4);

}

//On click, update order
d3.select("#button1").on("click", function() {
  series[0] = series[0].sort(function(a, b) {
    return d3.ascending(a.y, b.y)
  }).map(function(e, i) {
    return {
      x: i,
      fx: e.fx,
      y: e.y,
      u: e.u
    }
  });
  series[1].forEach(function(d, i, arr) {
    d.x = order0.indexOf(d.fx)
  });
  draw(series);
});

d3.select("#button2").on("click", function() {
  series[1] = series[1].sort(function(a, b) {
    return d3.ascending(a.y, b.y)
  }).map(function(e, i) {
    return {
      x: i,
      fx: e.fx,
      y: e.y,
      u: e.u
    }
  });
  series[0].forEach(function(d, i, arr) {
    d.x = order1.indexOf(d.fx)
  });
  draw(series);
});
pre {
  display: none;
}

button {
  margin-right: 5px;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<button id="button1">Click to sort by Blue</button><button id="button2">Click to sort by Orange</button>
<pre id="csv">x,y1,y2
0,0.85337,0.10198
1,0,0.30274
2,0.85311,0.08623
3,0.82759,0.08711
4,0.89602,0.03472
5,0.8,0.16295
6,0,0.27028
7,0.76167,0.2155
8,0.75,0.08359
9,0.81775,0.16535
10,0,0.2311</pre>


Related Query