Javascript D3数据在平移或缩放后无法正确重新缩放

Javascript D3数据在平移或缩放后无法正确重新缩放,javascript,d3.js,svg,Javascript,D3.js,Svg,我正在使用D3V4和JS。我有一个散点图,其中包含一组预定义的数据,以及能够平移和缩放的轴。我需要能够动态添加点,并最终在数据空间而不是像素空间中输出它们。我正在使用缩放对象的“rescaleX”和“rescaleY”方法。它们可以很好地重新缩放轴,但当我尝试添加新点时,打印点的位置确实与鼠标位置相对应。以下是代码的简化版本: <!DOCTYPE html> <html> <head> <meta charset="utf-8">

我正在使用D3V4和JS。我有一个散点图,其中包含一组预定义的数据,以及能够平移和缩放的轴。我需要能够动态添加点,并最终在数据空间而不是像素空间中输出它们。我正在使用缩放对象的“rescaleX”和“rescaleY”方法。它们可以很好地重新缩放轴,但当我尝试添加新点时,打印点的位置确实与鼠标位置相对应。以下是代码的简化版本:

<!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);
}
我想出来了。公共关系