score:1

Accepted answer

You need just one modification:

Since you have 3 inner arrays, each SVG has one of such arrays bound as data. So, when it comes to append the circles, instead of...

var circles = canvas.selectAll("circle")
    .data(pathData)
    .enter()        
    .append("circle")

..., which points to the whole data array, it should be...

var circles = canvas.selectAll("circle")
    .data(d => d)
    .enter()        
    .append("circle")

... which makes the inner arrays (that is, the data bound to each SVG) as the data array for each group of circles.

Here is your working code with that modification only (also, you had a typo on heightScale):

var canvasWidth  = 200,
    canvasHeight = 150;

    var pathData = [
        [
            { "x": 0,   "y": 50}, { "x": 20,  "y": 20}, 
            { "x": 60,  "y": 40}, { "x": 80,  "y": 30},
            { "x": 120, "y": 90}, { "x": 150, "y": 70}, 
            { "x": 180, "y": 30}, { "x": 190, "y": 90},
        ],
        [    
            { "x": 0,   "y": 90}, { "x": 20,  "y": 20}, 
            { "x": 30,  "y": 80}, { "x": 80,  "y": 30},
            { "x": 120, "y": 90}, { "x": 150, "y": 70}, 
            { "x": 180, "y": 30}, { "x": 190, "y": 90},
        ],
        [    
            { "x": 0,   "y": 40}, { "x": 20,  "y": 20}, 
            { "x": 30,  "y": 80}, { "x": 80,  "y": 30},
            { "x": 120, "y": 90}, { "x": 150, "y": 70}, 
            { "x": 180, "y": 30}, { "x": 190, "y": 90},
        ]
    ];

    var widthScale = d3.scaleLinear()
      .domain([0, 190])
      .range([0, canvasWidth - 30]);

    var heightScale = d3.scaleLinear()
      .domain([0, 90])
      .range([0, canvasHeight - 10]);

    // Canvas
    var container = d3.select("body")


    // Create accessor function
    var pathFunction = d3.line()
      .x(function(d) { return widthScale(d.x); })
      .y(function(d) { return heightScale(d.y); })
      .curve(d3.curveCatmullRom);


    var canvas = container.selectAll("svg")
        .data(pathData)
        .enter()
            .append("svg")
            .attr("width", canvasWidth)
            .attr("height", canvasHeight)
            .append("g")
            .attr("transform","translate(20)");

    var sparklines = canvas.append("path")
        .attr("d", pathFunction)
        .attr("stroke", "#19ff9f")
        .attr("stroke-width", 2)
        .attr("fill","none");


    var circles = canvas.selectAll("circle")
        .data(d=>d)
        .enter()        
            .append("circle")
            .attr("cx", function(d,i) { return widthScale(d.x); })
            .attr("cy", function(d,i) { return heightScale(d.y); })
            .attr("fill", "black")
            .attr("r", 3);
<script src="https://d3js.org/d3.v4.min.js"></script>

score:0

One useful way I've found to inspect a problem like this is to log your "d" value to the console:

.attr("cx", function(d,i) { console.log(d); return widthScale(d.x) })

That will probably highlight that, because you are now using a multidimensional array, the data bound to your circle elements doesn't provide you with immediate access to the data points anymore. Something like the following will probably work:

.attr("cx", function(d,i) { return widthScale(d[i].x) })

Related Query

More Query from same tag