我正在尝试使用 d3 构建一个可以缩放的趋势。那工作得很好。它可以在趋势内部(缩放所有轴)和通过鼠标滚轮按每个轴进行缩放。
现在我想通过按钮单击添加一些缩放。这些变焦也工作正常。
通过按钮放大 X 方向,然后通过鼠标滚轮放大 Y 方向或趋势,效果很好。
但是在 X 方向上通过按钮缩放和在 X 方向上通过鼠标滚轮缩放后,趋势开始从默认值缩放。
这是我的例子:https ://jsfiddle.net/DaWa/d5fdLwv0/
<label>X</label>
<button onclick="zoomXIn()">+</button>
<button onclick="zoomXOut()">-</button>
<br/>
<label>Y</label>
<button onclick="zoomYIn()">+</button>
<button onclick="zoomYOut()">-</button>
<br/>
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var xyTransform;
var xTransform;
var yTransform;
function zoomXIn() {
xZoom.scaleBy(xGroup, 2);
}
function zoomXOut() {
xZoom.scaleBy(xGroup, 0.5);
}
function zoomYIn() {
yZoom.scaleBy(yGroup, 2);
}
function zoomYOut() {
yZoom.scaleBy(yGroup, 0.5);
}
var svg = d3.select("svg"),
margin = {top: 20, right: 20, bottom: 110, left: 40},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var xScale = d3.scaleTime().range([0, width]),
yScale = d3.scaleLinear().range([height, 0]),
yOld, xOld;
var xAxis = d3.axisBottom(xScale),
yAxis = d3.axisLeft(yScale);
var xZoom = d3.zoom()
.on("zoom", function () {
xTransform = d3.event.transform;
zoomBoth("x")
});
var yZoom = d3.zoom()
.on("zoom", function () {
yTransform = d3.event.transform;
zoomBoth("y")
});
var zoom = d3.zoom()
.on("zoom", function () {
xyTransform = d3.event.transform;
setDefault();
zoomBoth()
});
function setDefault() {
if (!xTransform) {
xTransform = d3.zoomTransform(overlayX.node());
}
if (!yTransform) {
yTransform = d3.zoomTransform(overlayY.node());
}
}
var line = d3.line()
.curve(d3.curveMonotoneX)
.x(function (d) {
return xScale(d.date);
})
.y(function (d) {
return yScale(d.price);
});
svg.append("defs").append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var focus = svg.append("g")
.attr("class", "focus")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var data = getData();
xScale.domain(d3.extent(data, function (d) {
return d.date;
}));
yScale.domain([0, d3.max(data, function (d) {
return d.price;
})]);
var path = focus.append("path")
.datum(data)
.attr("class", "line")
.attr("d", line);
var xGroup = focus.append("g")
.attr("transform", "translate(0," + height + ")").call(xAxis);
var yGroup = focus.append("g")
.call(yAxis);
var overlayX = focus
.append("rect")
.attr("fill", "rgba(0,0,0,0.5)")
.attr("width", width)
.attr("height", 30)
.attr("y", height)
.call(xZoom);
var overlayY = focus
.append("rect")
.attr("fill", "rgba(0,0,0,0.5)")
.attr("width", 30)
.attr("height", height)
.attr("x", -30)
.call(yZoom);
var overlayRect = svg.append("rect")
.attr("class", "zoom")
.attr("width", width)
.attr("height", height)
.attr("transform", "translate(" + margin.left + "," + margin.top + ")")
.call(zoom);
function zoomBoth(axisType) {
getZoomedScales(axisType);
updateData();
updateAxes();
}
function getZoomedScales(axisType) {
if (!xOld) {
xOld = xScale.copy();
}
if (!yOld) {
yOld = yScale.copy();
}
var transformXY = d3.zoomTransform(overlayRect.node());
if (axisType === 'x') {
xScale = transformXY.rescaleX(xTransform.rescaleX(xOld));
} else if (axisType === 'y') {
yScale = transformXY.rescaleY(yTransform.rescaleY(yOld));
} else {
xScale = xyTransform.rescaleX(xTransform.rescaleX(xOld));
yScale = xyTransform.rescaleY(yTransform.rescaleY(yOld));
}
}
function updateAxes() {
xGroup.call(xAxis.scale(xScale));
yGroup.call(yAxis.scale(yScale));
}
function updateData() {
focus.select(".line").attr("d", line);
}
function getData() {
var data = [];
var date = new Date('Jan 2000');
for (var i = 0; i < 120; i++) {
data.push({date: new Date(date), price: Math.random() * 100});
date.setMonth(date.getMonth() + 1);
}
return data;
}
</script>
我该如何解决这个问题?
我希望你能理解我的问题并能提供帮助。
最好的问候, DW