Javascript D3数据在平移或缩放后无法正确重新缩放
我正在使用D3V4和JS。我有一个散点图,其中包含一组预定义的数据,以及能够平移和缩放的轴。我需要能够动态添加点,并最终在数据空间而不是像素空间中输出它们。我正在使用缩放对象的“rescaleX”和“rescaleY”方法。它们可以很好地重新缩放轴,但当我尝试添加新点时,打印点的位置确实与鼠标位置相对应。以下是代码的简化版本:Javascript D3数据在平移或缩放后无法正确重新缩放,javascript,d3.js,svg,Javascript,D3.js,Svg,我正在使用D3V4和JS。我有一个散点图,其中包含一组预定义的数据,以及能够平移和缩放的轴。我需要能够动态添加点,并最终在数据空间而不是像素空间中输出它们。我正在使用缩放对象的“rescaleX”和“rescaleY”方法。它们可以很好地重新缩放轴,但当我尝试添加新点时,打印点的位置确实与鼠标位置相对应。以下是代码的简化版本: <!DOCTYPE html> <html> <head> <meta charset="utf-8">
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
var data = [{x:17,y:3},
{x:20,y:16},
{x:2,y:13},
{x:19,y:10},
{x:13,y:15},
{x:2,y:2},
{x:5,y:8},
{x:11,y:19},
{x:20,y:12},
{x:10,y:20}];
var width = 600;
var height = 600;
var padding = 50;
var newXscale, newYscale;
var dataScale = d3.scaleLinear()
.domain([0,21])
.range([0, width]);
var svg = d3.select('body').append('svg')
.attr('width', width+2*padding)
.attr('height', height+2*padding)
.on('click', clicked);
var xAxis = d3.axisTop()
.scale(dataScale);
var gX = svg.append('g')
.attr('transform','translate(50,50)')
.call(xAxis);
var yAxis = d3.axisLeft()
.scale(dataScale);
var gY = svg.append('g')
.attr('transform','translate(50,50)')
.call(yAxis);
var canvas = svg.append('g')
var points = canvas.append('g');
points.selectAll('circle').data(data)
.enter().append('circle')
.attr('cx', function(d) {return dataScale(d.x)+padding})
.attr('cy', function(d) {return dataScale(d.y)+padding})
.attr('r', 5);
var zoom
var zoomOn = false;
window.addEventListener('keydown', function (event) {
if (event.key=='z') {
if (zoomOn) {
d3.select('#zoomBox').remove();
zoomOn = false;
} else {
zoom = d3.zoom()
.scaleExtent([0.1, 10])
.on('zoom', zoomed);
svg.append("rect")
.attr('cursor','move')
.attr("width", width+padding*2)
.attr("height", height+padding*2)
.attr('id','zoomBox')
.style("fill", "none")
.style("pointer-events", "all")
.call(zoom);
zoomOn = true;
}
}
});
function zoomed() {
canvas.attr("transform", d3.event.transform)
newXscale = d3.event.transform.rescaleX(dataScale);
newYscale = d3.event.transform.rescaleY(dataScale);
gX.call(xAxis.scale(newXscale));
gY.call(yAxis.scale(newYscale));
}
function clicked() {
var coords = d3.mouse(this);
points.append('circle')
.attr('cx',coords[0])
.attr('cy',coords[1])
.attr('r',5);
var x = newXscale.invert(coords[0]-padding);
var y = newYscale.invert(coords[1]-padding);
console.log(x+' '+y);
}
</script>
</body>
</html>
var data=[{x:17,y:3},
{x:20,y:16},
{x:2,y:13},
{x:19,y:10},
{x:13,y:15},
{x:2,y:2},
{x:5,y:8},
{x:11,y:19},
{x:20,y:12},
{x:10,y:20}];
var宽度=600;
var高度=600;
var=50;
var newXscale,newYscale;
var dataScale=d3.scaleLinear()
.domain([0,21])
.范围([0,宽度]);
var svg=d3。选择('body')。追加('svg'))
.attr('width',width+2*填充)
.attr('height',height+2*填充)
.打开(“单击”,单击);
var xAxis=d3.axisTop()
.规模(数据规模);
var gX=svg.append('g')
.attr('transform','translate(50,50)'))
.呼叫(xAxis);
var yAxis=d3.axisLeft()
.规模(数据规模);
var gY=svg.append('g')
.attr('transform','translate(50,50)'))
.呼叫(yAxis);
var canvas=svg.append('g')
var points=canvas.append('g');
点。选择全部(‘圆’)。数据(数据)
.enter().append('圆')
.attr('cx',函数(d){返回数据量表(d.x)+填充})
.attr('cy',函数(d){返回数据量表(d.y)+填充})
.attr('r',5);
变焦
var zoomOn=false;
window.addEventListener('keydown',函数(事件){
if(event.key='z'){
如果(zoomOn){
d3.选择(“#zoomBox”).remove();
zoomOn=false;
}否则{
zoom=d3.zoom()
.scaleExtent([0.1,10])
.打开(“缩放”,缩放);
svg.append(“rect”)
.attr('光标','移动')
.attr(“宽度”,宽度+填充*2)
.attr(“高度”,高度+填充*2)
.attr('id','zoomBox'))
.style(“填充”、“无”)
.style(“指针事件”、“全部”)
.呼叫(缩放);
zoomOn=true;
}
}
});
函数缩放(){
canvas.attr(“transform”,d3.event.transform)
newXscale=d3.event.transform.rescaleX(数据尺度);
newYscale=d3.event.transform.rescaleY(数据尺度);
调用(xAxis.scale(newXscale));
gY.call(雅克斯量表(新量表));
}
函数单击(){
var coords=d3.鼠标(此);
points.append('圆')
.attr('cx',坐标[0])
.attr('cy',coords[1])
.attr('r',5);
var x=newXscale.invert(坐标[0]-填充);
变量y=newYscale.invert(坐标[1]-填充);
控制台日志(x+“”+y);
}
创建一个变量来存储缩放级别:
newZscale = d3.event.transform.k;
function clicked() {
var coords = d3.mouse(this);
if (newXscale && newYscale) {
var x = newXscale.invert(coords[0] - padding);
var y = newYscale.invert(coords[1] - padding);
};
console.log(newZscale);
points.append('circle')
.attr('cx', (!x) ? coords[0] : dataScale(x) + (padding / newZscale))
.attr('cy', (!y) ? coords[1] : dataScale(y) + (padding / newZscale))
.attr('r', 5);
console.log(x + ' ' + y);
}
并且,在单击的函数中,使用dateScale
绘制新的圆圈,将填充除以缩放级别:
newZscale = d3.event.transform.k;
function clicked() {
var coords = d3.mouse(this);
if (newXscale && newYscale) {
var x = newXscale.invert(coords[0] - padding);
var y = newYscale.invert(coords[1] - padding);
};
console.log(newZscale);
points.append('circle')
.attr('cx', (!x) ? coords[0] : dataScale(x) + (padding / newZscale))
.attr('cy', (!y) ? coords[1] : dataScale(y) + (padding / newZscale))
.attr('r', 5);
console.log(x + ' ' + y);
}
以下是演示:
var数据=[{
x:17,
y:3
}, {
x:20,
y:16
}, {
x:2,
y:13
}, {
x:19,
y:10
}, {
x:13,
y:15
}, {
x:2,
y:2
}, {
x:5,
y:8
}, {
x:11,,
y:19
}, {
x:20,
y:12
}, {
x:10,
y:20
}];
var宽度=600;
var高度=600;
var=50;
var newXscale、newYscale、newZscale;
var dataScale=d3.scaleLinear()
.domain([0,21])
.范围([0,宽度]);
var svg=d3。选择('body')。追加('svg'))
.attr('width',width+2*填充)
.attr('height',height+2*填充)
.打开(“单击”,单击);
var xAxis=d3.axisTop()
.规模(数据规模);
var gX=svg.append('g')
.attr('transform','translate(50,50)'
.呼叫(xAxis);
var yAxis=d3.axisLeft()
.规模(数据规模);
var gY=svg.append('g')
.attr('transform','translate(50,50)'
.呼叫(yAxis);
var canvas=svg.append('g')
var points=canvas.append('g');
点。选择全部(‘圆’)。数据(数据)
.enter().append('圆')
.attr('cx',函数(d){
返回数据刻度(d.x)+填充
})
.attr('cy',函数(d){
返回数据刻度(d.y)+填充
})
.attr('r',5);
变焦
var zoomOn=false;
window.addEventListener('keydown',函数(事件){
如果(event.key='z'){
如果(zoomOn){
d3.选择(“#zoomBox”).remove();
zoomOn=false;
}否则{
zoom=d3.zoom()
.scaleExtent([0.1,10])
.打开(“缩放”,缩放);
svg.append(“rect”)
.attr('光标','移动')
.attr(“宽度”,宽度+填充*2)
.attr(“高度”,高度+填充*2)
.attr('id','zoomBox')
.style(“填充”、“无”)
.style(“指针事件”、“全部”)
.呼叫(缩放);
zoomOn=true;
}
}
});
函数缩放(){
canvas.attr(“transform”,d3.event.transform)
newXscale=d3.event.transform.rescaleX(数据尺度);
newYscale=d3.event.transform.rescaleY(数据尺度);
newZscale=d3.event.transform.k;
调用(xAxis.scale(newXscale));
gY.call(雅克斯量表(新量表));
}
函数单击(){
var coords=d3.鼠标(此);
if(newXscale&&newYscale){
var x=newXscale.invert(坐标[0]-填充);
变量y=newYscale.invert(坐标[1]-填充);
};
points.append('圆')
.attr('cx',(!x)?坐标[0]:数据刻度(x)+(填充/newZscale))
.attr('cy',(!y)?坐标[1]:数据量表(y)+(填充/newZscale))
.attr('r',5);
}
我想出来了。公共关系