#javascript #svg #d3.js #plot
#javascript #svg #d3.js #график
Вопрос:
Я использую этот пример для реализации перетаскивания на графике.
Наиболее важная часть:
/// 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)
}
Функция dragged
ожидает событие. Но переданный объект dragged
— это просто координаты моей строки, ничего не говорящие о событии. Конечно, у него нет атрибута x
, поэтому код не работает.
Предполагается, что объект события должен выглядеть следующим образом:
Я не могу понять, что я делаю иначе, чем в примере.
Мой полный код:
/// 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
, и quantiles
являются объектами JSON, сгенерированными с использованием Python json.dumps()
. Я сомневаюсь, что JSON каким-то образом недействительны; Я могу нормально рисовать линии, проблема в перетаскивании.
Ответ №1:
Пример, на котором вы основываете свой код, — это d3v6. Канонические примеры обычно обновляются довольно последовательно с каждой версией. Вы используете d3v4.
Версии до d3v6 использовали другую подпись для функций, переданных .on()
. В d3v6 функции принимают форму function(event,d)
до этого эти функции принимали форму:
function(d,i,nodes) {
console.log(d3.event) // event information
}
Где d
— привязанный элемент данных, i
— индекс и nodes
— группа узлов в выделенном элементе. Таким образом, вы должны иметь возможность использовать:
function dragged(d) {
d3.select(this).attr("transform", 'translate(' d3.event.x ',' 0 ')')
}
Это изменение является наиболее заметным изменением в d3v6.