d3.js: How to get event information for drag

Viewed 625

I am using this example to implement dragging on a graph.

The most relevant part:

/// IMPLEMENT DRAG BEHAVIOR
drag = d3.drag().on("drag", dragged)
function dragged(event,d) {
        d3.select(this).attr("transform", 'translate(' + event.x + ',' + 0 + ')')
    }
for (line of quantile_horizontal_lines) {
    line.call(drag)
}

The function dragged expects an event. But the object passed into dragged is just the coordinates of my line, with nothing about the event. Of course, it has no attribute x, so the code doesn't work.

enter image description here

An event object is supposed to look like this:

enter image description here

I can't figure out what I'm doing differently from the example.

My full code:

/// BASIC LINE GRAPH SETUP
// 2. Use the margin convention practice
var margin = {top: 50, right: 50, bottom: 50, left: 50}
  , width = window.innerWidth - margin.left - margin.right // Use the window's width
  , height = window.innerHeight - margin.top - margin.bottom; // Use the window's height

// 8. An array of objects of length N. Each object has key -> value pair, the key being "y" and the value is a random number
var dataset = data

// The number of datapoints
var n = data.length

// 5. X scale will use the index of our data
var xScale = d3.scaleLinear()
    .domain([metadata.xmin, metadata.xmax]) // input
    .range([0, width]); // output

// 6. Y scale will use the randomly generate number
var yScale = d3.scaleLinear()
    .domain([metadata.ymin, metadata.ymax]) // input
    .range([height, 0]); // output

// 7. d3's line generator
var line = d3.line()
    .x(function(d) { return xScale(d.x); }) // set the x values for the line generator
    .y(function(d) { return yScale(d.y); }) // set the y values for the line generator

// 1. Add the SVG to the graph div and employ #2
var svg = d3.select("#graph").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// 3. Call the x axis in a group tag
svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(d3.axisBottom(xScale)); // Create an axis component with d3.axisBottom

// 4. Call the y axis in a group tag
svg.append("g")
    .attr("class", "y axis")
    .call(d3.axisLeft(yScale)); // Create an axis component with d3.axisLeft

// 9. Append the path, bind the data, and call the line generator
plane = svg.append("g").attr('class','plane')

plane.append("path")
    .datum(dataset) // 10. Binds data to the line
    .attr("class", "line") // Assign a class for styling
    .attr("d", line); // 11. Calls the line generator

d3.select('.line') // move this to a CSS file later
    .attr('fill','none')
    .attr("stroke", "steelblue")
    .attr("stroke-width", 1.5)
    .attr("stroke-linejoin", "round")
    .attr("stroke-linecap", "round")


/// ADD HORIZONTAL/VERTICAL LINES
plane.on('click',onclick)

onclick = function (event){
    x = xScale.invert(event.layerX - margin.left);
    y = yScale.invert(event.layerY - margin.right);
    console.log(x,y)
}

quantile_horizontal_lines = new Array()

function drawQuantileLines(quantiles) {
    console.log("running drawQuantileLines")
    for (let i = 0; i < quantiles.length; i++) {
        quantile = quantiles[i]
        quantile_horizontal_line_0 = {'x': quantile.x, 'y': metadata.ymin}
        quantile_horizontal_line_1 = {'x': quantile.x, 'y': quantile.y}

        quantile_horizontal_lines.push(
            plane.append("path")
                .datum([quantile_horizontal_line_0, quantile_horizontal_line_1])
                .attr('d', line)
                .attr('class', 'line')
                .attr('stroke', 'red'))
    }
}

drawQuantileLines(quantiles)


/// IMPLEMENT DRAG BEHAVIOR
drag = d3.drag().on("drag", dragged)
function dragged(event,d) {
        d3.select(this).attr("transform", 'translate(' + event.x + ',' + 0 + ')')
    }
for (line of quantile_horizontal_lines) {
    line.call(drag)
}

data, metadata, and quantiles are JSON objects generated from Python using json.dumps(). I doubt the JSONs are invalid in some way; I am able to draw the lines fine, the problem is with the dragging.

1 Answers

The example you are basing your code off of is d3v6. The canonical examples are generally updated fairly consitently with each version. You are using d3v4.

Versions prior to d3v6 used a different signature for functions passed to .on(). In d3v6, the functions take the form of function(event,d) prior to this these functions took the form:

function(d,i,nodes) {
   console.log(d3.event) // event information
}

Where d is the bound datum, i is the index, and nodes is the group of nodes in the selection. So you should be able to use:

function dragged(d) {
    d3.select(this).attr("transform", 'translate(' + d3.event.x + ',' + 0 + ')')
}

This change is the most notable change in d3v6.

Related