gpt4 book ai didi

javascript - 放大和缩小功能在 D3 图表中未按预期工作并使用react

转载 作者:行者123 更新时间:2023-12-02 22:59:20 24 4
gpt4 key购买 nike

在我的 D3 图表中,放大和缩小功能未按 D3 图表中的预期工作。

它正在缩放整个图形,而不仅仅是绘制的线条和区域。预期的行为应该只是放大和缩小图表,而不是 x 轴和 y 轴。

当我使用以下代码使用 d3.zoom() 时 -

.call(d3.zoom().on("zoom", function () {
svg.attr("transform", d3.event.transform)
}));

但是上面的代码也会更新轴。所以我尝试添加剪辑路径并尝试使用它,但它不起作用。

   // A function that updates the chart when the user zoom and thus new boundaries are available

const updateChart = () => {
// recover the new scale
var newX = d3.event.transform.rescaleX(xScale);
var newY = d3.event.transform.rescaleY(yScale);

// update axes with these new boundaries
xAxis.call(d3.axisBottom(newX));
yAxis.call(d3.axisLeft(newY));

// update circle position
scatter
.selectAll("circle")
.attr("cx", function(d) {
return newX(d.Sepal_Length);
})
.attr("cy", function(d) {
return newY(d.Petal_Length);
});
};

var zoom = d3
.zoom()
.scaleExtent([0.5, 20]) // This control how much you can unzoom (x0.5) and zoom (x20)
.extent([[0, 0], [containerWidth, containerHeight]])
.on("zoom", updateChart);

var svg = d3
.select(this.refs.chart)
.append("svg")
.attr("width", containerWidth)
.attr("height", containerHeight)
.call(zoom);

// Create the scatter variable: where both the circles and the brush take place
var scatter = svg.append("g").attr("clip-path", "url(#clip)");

这种散布应该移动圆圈以进行放大和缩小。我的工作代码沙箱here -

谢谢。

最佳答案

我尝试在react之外重新制作这个,你必须遵循d3 Zoom hierarki,

  1. 绘制定义,

  2. 绘制剪辑,

  3. 在剪辑中绘制要移动的项目,

  4. 更新元素

缩放后请记住比例正在更改,请使用新比例来更新所有元素,如果不这样做,它将跟随缩放而下降。

var data = [
{
startTime: "1567765320049",
magnitude: 0,
startupMagnitude: 0,
startupRunningStatus: "IN_SYNC"
},
{
startTime: "1567851720049",
magnitude: 0,
startupMagnitude: 0,
startupRunningStatus: "IN_SYNC"
},
{
startTime: "1568024520049",
magnitude: 10,
startupMagnitude: 10,
startupRunningStatus: "IN_SYNC"
},
{
startTime: "1568283720049",
magnitude: 10,
startupMagnitude: 0,
startupRunningStatus: "OUT_OF_SYNC"
},
{
startTime: "1568629320049",
magnitude: 0,
startupMagnitude: 10,
startupRunningStatus: "OUT_OF_SYNC"
},
{
startTime: "1569061320049",
magnitude: 0,
startupMagnitude: 0,
startupRunningStatus: "IN_SYNC"
},
{
startTime: "1569579720049",
magnitude: -20,
startupMagnitude: 0,
startupRunningStatus: "OUT_OF_SYNC"
},
{
startTime: "1570184520049",
magnitude: -20,
startupMagnitude: -10,
startupRunningStatus: "OUT_OF_SYNC"
},
{
startTime: "1570875720049",
magnitude: 0,
startupMagnitude: 0,
startupRunningStatus: "IN_SYNC"
},
{
startTime: "1571653320049",
magnitude: 10,
startupMagnitude: -0,
startupRunningStatus: "OUT_OF_SYNC"
},
{
startTime: "1572517320049",
magnitude: 0,
startupMagnitude: -10,
startupRunningStatus: "OUT_OF_SYNC"
},
{
startTime: "1573467720049",
magnitude: 0,
startupMagnitude: -10,
startupRunningStatus: "OUT_OF_SYNC"
},
{
startTime: "1574504520049",
magnitude: 10,
startupMagnitude: -10,
startupRunningStatus: "OUT_OF_SYNC"
},
{
startTime: "1575627720049",
magnitude: 10,
startupMagnitude: -10,
startupRunningStatus: "OUT_OF_SYNC"
}
];


var drawLineGraph = function(containerHeight, containerWidth, data, yLabel, warnLine) {
// A function that updates the chart when the user zoom and thus new boundaries are available
var newX = ''
const updateChart = () => {
d3.select("#focusCircle").style('display', 'none')
// recover the new scale
newX = d3.event.transform.rescaleX(xScale);
var newY = yScale;


// update axes with these new boundaries
d3.select("#axisX").call(d3.axisBottom(newX));
//d3.select('#axisY').call(d3.axisLeft(newY));

// update circle position
scatter
.selectAll("circle")
.attr("cx", function(d) {
if (d) {
return newX(d.startTime);
}
})
.attr("cy", function(d) {
if (d) {
return newY(d.magnitude);
}
});

var line2 = d3
.line()
.x(function(d) {
return newX(d.startTime);
})
.y(function(d) {
return newY(d.startupMagnitude);
});

var area = d3
.area()
.x(function(d) {
return newX(d.startTime);
})
.y0(function(d) {
return yScale(d.startupMagnitude);
})
.y1(height);

var line = d3
.line()
.x(function(d) {
return newX(d.startTime);
})
.y(function(d) {
return newY(d.magnitude);
});

svg.on("mousemove", function() {
d3.select("#focusCircle").style('display', 'block')
var mouse = d3.mouse(this);
var mouseDate = newX.invert(mouse[0]);
var i = bisectDate(data, mouseDate); // returns the index to the current data item

var d0 = data[i - 1];
var d1 = data[i];
let d;
// work out which date value is closest to the mouse
if (typeof d1 !== "undefined") {
d = mouseDate - d0.startTime > d1.startTime - mouseDate ? d1 : d0;
} else {
d = d0;
}

div
.html(
`<span>${parseDate(d.startTime)}</span>
<span>Magnitude: ${d.magnitude} </span>`
)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY - 28 + "px");
var x = newX(d.startTime);
var y = yScale(d.magnitude);

focus
.select("#focusCircle")
.attr("cx", x)
.attr("cy", y);
focus
.select("#focusLineX")
.attr("x1", x)
.attr("y1", yScale(yDomain[0]))
.attr("x2", x)
.attr("y2", yScale(yDomain[1]));
focus
.select("#focusLineY")
.attr("x1", xScale(xDomain[0]))
.attr("y1", y)
.attr("x2", xScale(xDomain[1]))
.attr("y2", y);
});

scatter.select("#line2").attr("d", line2);
scatter.select(".line").attr("d", line);
scatter.select("#area").attr("d", area);
};

var zoom = d3
.zoom()
.scaleExtent([0.5, 20]) // This control how much you can unzoom (x0.5) and zoom (x20)
.extent([[0, 0], [containerWidth, containerHeight]])
.on("zoom", updateChart);

var svg = d3
.select('#chart')
.append("svg")
.attr("width", containerWidth)
.attr("height", containerHeight);

var clip = svg
.append("defs")
.append("SVG:clipPath")
.attr("id", "clip")
.append("SVG:rect")
.attr("width", containerWidth)
.attr("height", containerHeight)
.attr("x", 50)
.attr("y", 0);

// Create the scatter variable: where both the circles and the brush take place
var scatter = svg.append("g").attr("clip-path", "url(#clip)");

var margin = { top: 50, left: 50, right: 50, bottom: 80 };

var height = containerHeight - margin.top - margin.bottom;
var width = containerWidth - margin.left - margin.right;

var xDomain = d3.extent(data, function(d) {
return d.startTime;
});
var yDomain = d3.extent(data, function(d) {
return d.magnitude;
});

var xScale = d3
.scaleTime()
.range([0, width])
.domain(xDomain);
var yScale = d3
.scaleLinear()
.range([height, 0])
.domain(yDomain);

var xAxis = d3.axisBottom(xScale);
var yAxis = d3.axisLeft(yScale);

var line = d3
.line()
.x(function(d) {
return xScale(d.startTime);
})
.y(function(d) {
return yScale(d.magnitude);
});

var line2 = d3
.line()
.x(function(d) {
return xScale(d.startTime);
})
.y(function(d) {
return yScale(d.startupMagnitude);
});

var area = d3
.area()
.x(function(d) {
return xScale(d.startTime);
})
// .x0(function(d) {
// return xScale(d.startTime);
// })
// .x1(function(d) {
// return xScale(d.magnitude);
// })
.y0(function(d) {
return yScale(d.startupMagnitude);
})
.y1(height);
// .y0(height)
// .y1(function(d) { return yScale(d.magnitude); });

// var area = d3
// .area()
// .x0(function(d) {
// return xScale(d.startTime);
// })
// .x1(function(d) {
// return xScale(d.startTime);
// })
// .y0(function(d) {
// return yScale(d.magnitude);
// })
// .y1(function(d) {
// return yScale(0);
// });

// var area = d3
// .area()
// .x(function(d) {
// return xScale(d.startTime);
// })
// .y0(function(d) {
// return yScale(d.magnitude);
// })
// .y1(yScale(0));

// Define the div for the tooltip
var div = d3
.select("body")
.append("div")
.attr("class", "tooltip")
.style("opacity", 0);

var g = scatter
.append("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");

var g2 = svg
.append("g")
.attr("transform", "translate(" + margin.left + ", " + margin.top + ")");

g.append("path")
.datum(data)
.attr("class", "area")
.attr("id", "area")
.attr("d", area);

g.append("g")
.attr("class", "x axis")
.attr("id", "axisX")
.attr("transform", "translate(0, " + height + ")")
.call(xAxis);

g2.append("g")
.attr("class", "y axis")
.attr("id", "axisY")
.call(yAxis)
.append("text")
.attr("transform", "rotate(-90)")
.attr("y", 6)
.attr("dy", ".71em")
.attr("text-anchor", "end")
.text(yLabel);

g.append("path")
.datum(data)
.attr("class", "line")

.attr("d", line);

g.append("path")
.datum(data)
.attr("class", "line2")
.attr("id", "line2")
.attr("d", line2);

g.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", function(d) {
return xScale(d.startTime);
})
.attr("cy", function(d) {
return yScale(d.magnitude);
})
.attr("r", function(d) {
if (d.startupRunningStatus === "OUT_OF_SYNC") {
return 5;
}
})
.attr("class", "circle");

//legend code
svg
.append("circle")
.attr("cx", 40)
.attr("cy", 380)
.attr("r", 6)
.style("fill", "#1391d8");
svg
.append("circle")
.attr("cx", 40)
.attr("cy", 400)
.attr("r", 6)
.style("fill", "red");
svg
.append("text")
.attr("x", 60)
.attr("y", 380)
.text("Startup Config")
.style("font-size", "15px")
.attr("alignment-baseline", "middle");
svg
.append("text")
.attr("x", 60)
.attr("y", 400)
.text("Running Config")
.style("font-size", "15px")
.attr("alignment-baseline", "middle");

// focus tracking
var focus = g.append("g").style("display", "none");

focus
.append("line")
.attr("id", "focusLineX")
.attr("class", "focusLine");
focus
.append("line")
.attr("id", "focusLineY")
.attr("class", "focusLine");
focus
.append("circle")
.attr("id", "focusCircle")
.attr("r", 5)
.attr("class", "circle focusCircle");

//grid line
const make_x_axis = () => {
return d3.axisBottom(xScale);
};

scatter
.append("g")
.attr("class", "grid")
.attr("transform", "translate(50," + (height + 50) + ")")
.call(
make_x_axis()
.tickSize(-height, 0, 0)
.tickFormat("")
);

var bisectDate = d3.bisector(function(d) {
return d.startTime;
}).left;
var parseDate = d3.timeFormat("%Y-%m-%d %H:%M:%S");
g.selectAll("dot")
.data(data)
.enter()
.append("rect")
.attr("class", "overlay")
.attr("width", width)
.attr("height", height)


svg.on("mouseover", function(d) {
console.log('ok')
focus.style("display", null);
div
.transition()
.duration(200)
.style("opacity", 0.9);
})
.on("mouseout", function() {
focus.style("display", "none");
div
.transition()
.duration(300)
.style("opacity", 0);
})

.on("mousemove", function() {
var mouse = d3.mouse(this);
var mouseDate = xScale.invert(mouse[0]);
var i = bisectDate(data, mouseDate); // returns the index to the current data item

var d0 = data[i - 1];
var d1 = data[i];
let d;
// work out which date value is closest to the mouse
if (typeof d1 !== "undefined") {
d = mouseDate - d0.startTime > d1.startTime - mouseDate ? d1 : d0;
} else {
d = d0;
}

div
.html(
`<span>${parseDate(d.startTime)}</span>
<span>Magnitude: ${d.magnitude} </span>`
)
.style("left", d3.event.pageX + "px")
.style("top", d3.event.pageY - 28 + "px");
var x = xScale(d.startTime);
var y = yScale(d.magnitude);

focus
.select("#focusCircle")
.attr("cx", x)
.attr("cy", y);
focus
.select("#focusLineX")
.attr("x1", x)
.attr("y1", yScale(yDomain[0]))
.attr("x2", x)
.attr("y2", yScale(yDomain[1]));
focus
.select("#focusLineY")
.attr("x1", xScale(xDomain[0]))
.attr("y1", y)
.attr("x2", xScale(xDomain[1]))
.attr("y2", y);
});

svg
.append("rect")
.attr("width", containerWidth)
.attr("height", containerHeight)
.style("fill", "none")

.style("pointer-events", "all")

.call(zoom);

// warn line

// if (
// warnLine &&
// yDomain[0] < warnLine.lineValue &&
// yDomain[1] > warnLine.lineValue
// ) {
// g.append("line")
// .attr("x1", xScale(xDomain[0]))
// .attr("y1", yScale(warnLine.lineValue))
// .attr("x2", xScale(xDomain[1]))
// .attr("y2", yScale(warnLine.lineValue))
// .attr("class", "zeroline");
// g.append("text")
// .attr("x", xScale(xDomain[1]))
// .attr("y", yScale(warnLine.lineValue))
// .attr("dy", "1em")
// .attr("text-anchor", "end")
// .text(warnLine.label)
// .attr("class", "zerolinetext");
// }
}

drawLineGraph(410, 700, data, "Magnitude", {
lineValue: 0,
label: "Startup Config!"
});
.axis path,
.axis line {
fill: none;
stroke: #e0e0e0;
shape-rendering: crispEdges;
}

.x.axis path {
display: none;
}

.line {
fill: none;
stroke: red;
stroke-width: 2px;
}

.line2 {
fill: none;
stroke: #2e59cf;
stroke-width: 0.3px;
}

.circle {
/* fill: white;
stroke: steelblue;
stroke-width: 2px; */
fill: steelblue;
stroke: steelblue;
/* stroke-width: 2px; */
}

.area {
fill: #2e59cf;
stroke: none;
opacity: 0.1;
}

.zeroline {
fill: none;
stroke: #1391d8;
stroke-width: 1px;
stroke-dasharray: 8 8;
}

.zerolinetext {
fill: #1391d8;
}

.overlay {
fill: none;
stroke: none;
pointer-events: all;
}

.focusLine {
fill: none;
stroke: steelblue;
stroke-width: 0.5px;
}

.focusCircle {
fill: red;
}

div.tooltip {
position: absolute;
text-align: center;
width: 150px;
height: 38px;
padding: 2px;
font: 12px sans-serif;
background: lightsteelblue;
border: 0px;
border-radius: 8px;
pointer-events: none;
}

.grid .tick {
stroke: lightgrey;
stroke-width: 0.7px;
stroke-dasharray: 8 8;
opacity: 0.3;
}
.grid path {
stroke-width: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div className="App">
<h1>Chart</h1>
</div>
<div id="chart"></div>

关于javascript - 放大和缩小功能在 D3 图表中未按预期工作并使用react,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57849225/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com