Javascript d3js v4:独立多轴缩放和平移

Javascript d3js v4:独立多轴缩放和平移,javascript,d3.js,Javascript,D3.js,我正在尝试实现一个图表框架,它能够为每个方向创建多轴的线图和面积图,即左2-y轴、右1-YAX轴和底部1-x轴 我得去工作。我的下一个任务是实现图表的缩放行为。我缩进以获得全局缩放行为,如果用户在绘图区域内使用鼠标,就会触发该行为。显示的序列将被重新缩放,并且可以平移绘图。这个我也得去工作 此外,我希望每个轴都有独立的缩放。我得到了缩放,但是我仍然有全局缩放和平移的问题。如果缩放一个轴,打印区域中的关联系列将重新缩放,但平移不起作用。在轴的独立缩放之后,如果我使用全局重缩放,缩放会重置,然后通过

我正在尝试实现一个图表框架,它能够为每个方向创建多轴的线图和面积图,即左2-y轴、右1-YAX轴和底部1-x轴

我得去工作。我的下一个任务是实现图表的缩放行为。我缩进以获得全局缩放行为,如果用户在绘图区域内使用鼠标,就会触发该行为。显示的序列将被重新缩放,并且可以平移绘图。这个我也得去工作

此外,我希望每个轴都有独立的缩放。我得到了缩放,但是我仍然有全局缩放和平移的问题。如果缩放一个轴,打印区域中的关联系列将重新缩放,但平移不起作用。在轴的独立缩放之后,如果我使用全局重缩放,缩放会重置,然后通过全局缩放行为进行缩放

在d3.js页面上,我发现了一个简单的用于独立和全局缩放和平移的方法,但它是用d3v3编写的

我以这种方式更改了示例,以便它显示我的问题。在轴上和打印区域中使用鼠标

<!DOCTYPE html>
<html>
  <head>
    <title>TODO supply a title</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Simple Independent Axis Zooms on x, y, or xy</title>
    <script src="//d3js.org/d3.v4.min.js"></script>
    <style>
        .axis path, .axis line {
            fill: none;
            stroke: #000;
            shape-rendering: crispEdges;
        }
    </style>
</head>
<body>
    <div id="chart"></div>
    <script>


        var data = [];
        for (var i = 0; i < 100; i++) {
            data.push([Math.random(), Math.random()]);
        }
        var svg = d3.select('#chart')
                .append("svg")
                .attr("width", window.innerWidth).attr("height", window.innerHeight);

        function example(svg, data) {
            var svg;
            var margin = {
                top: 60,
                bottom: 80,
                left: 60,
                right: 0
            };
            var width = 500;
            var height = 400;
            var xaxis = d3.axisBottom();
            var yaxis = d3.axisLeft();
            var xscale = d3.scaleLinear();
            var yscale = d3.scaleLinear();
            var xcopyScale, ycopyScale;
            var xyzoom, xzoom, yzoom;
            updateZooms();





            function update() {

                var gs = svg.select("g.scatter");

                var circle = gs.selectAll("circle")
                        .data(data);

                circle.enter().append("svg:circle")
                        .attr("class", "points")
                        .style("fill", "steelblue")
                        .attr("cx", function (d) {
                            return X(d);
                        })
                        .attr("cy", function (d) {
                            return Y(d);
                        })
                        .attr("r", 4);

                circle.attr("cx", function (d) {
                    return X(d);
                })
                        .attr("cy", function (d) {
                            return Y(d);
                        });

                circle.exit().remove();
            }

            function updateZooms() {
                xyzoom = d3.zoom()
                        .on("zoom", function () {
                            xaxis.scale(d3.event.transform.rescaleX(xscale));
                            yaxis.scale(d3.event.transform.rescaleY(yscale));
                            draw();
                        });

                xzoom = d3.zoom()
                        .on("zoom", function () {
                            xaxis.scale(d3.event.transform.rescaleX(xscale));
                            draw();
                        });

                yzoom = d3.zoom()
                        .on("zoom", function () {
                            yaxis.scale(d3.event.transform.rescaleY(yscale));
                            draw();
                        });
            }

            function draw() {
                svg.select('g.x.axis').call(xaxis);
                svg.select('g.y.axis').call(yaxis);
                update();
                // After every draw, we reinitialize zoom. After every zoom, we reexecute draw, which will reinitialize zoom.
                // This is how we can apply multiple independent zoom behaviors to the scales.
                // (Note that the zoom behaviors will always end up with zoom at around 1.0, and translate at around [0,0])
                svg.select('rect.zoom.xy.box').call(xyzoom);
                svg.select('rect.zoom.x.box').call(xzoom);
                svg.select('rect.zoom.y.box').call(yzoom);
            }
            // X value to scale
            function X(d) {
                return xaxis.scale() !== undefined && xaxis.scale() !== null
                        ? xaxis.scale()(d[0])
                        : xscale(d[0]);
            }

            // Y value to scale
            function Y(d) {
                return yaxis.scale() !== undefined && yaxis.scale() !== null
                        ? yaxis.scale()(d[1])
                        : yscale(d[1]);
            }


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

            g.append("defs").append("clipPath")
                    .attr("id", "clip")
                    .append("rect")
                    .attr("width", width - margin.left - margin.right)
                    .attr("height", height - margin.top - margin.bottom);

            g.append("svg:rect")
                    .attr("class", "border")
                    .attr("width", width - margin.left - margin.right)
                    .attr("height", height - margin.top - margin.bottom)
                    .style("stroke", "black")
                    .style("fill", "none");

            g.append("g").attr("class", "x axis")
                    .attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")");

            g.append("g").attr("class", "y axis");

            g.append("g")
                    .attr("class", "scatter")
                    .attr("clip-path", "url(#clip)");

            g
                    .append("svg:rect")
                    .attr("class", "zoom xy box")
                    .attr("width", width - margin.left - margin.right)
                    .attr("height", height - margin.top - margin.bottom)
                    .style("visibility", "hidden")
                    .attr("pointer-events", "all")
                    .call(xyzoom);

            g
                    .append("svg:rect")
                    .attr("class", "zoom x box")
                    .attr("width", width - margin.left - margin.right)
                    .attr("height", height - margin.top - margin.bottom)
                    .attr("transform", "translate(" + 0 + "," + (height - margin.top - margin.bottom) + ")")
                    .style("visibility", "hidden")
                    .attr("pointer-events", "all")
                    .call(xzoom);

            g
                    .append("svg:rect")
                    .attr("class", "zoom y box")
                    .attr("width", margin.left)
                    .attr("height", height - margin.top - margin.bottom)
                    .attr("transform", "translate(" + -margin.left + "," + 0 + ")")
                    .style("visibility", "hidden")
                    .attr("pointer-events", "all")
                    .call(yzoom);

            // Update the x-axis
            xscale.domain(d3.extent(data, function (d) {
                return d[0];
            })).range([0, width - margin.left - margin.right]);

            xaxis.scale(xscale)
                    .tickPadding(10);

            svg.select('g.x.axis').call(xaxis);

            // Update the y-scale.
            yscale.domain(d3.extent(data, function (d) {
                return d[1];
            })).range([height - margin.top - margin.bottom, 0]);

            yaxis.scale(yscale)
                    .tickPadding(10);

            svg.select('g.y.axis').call(yaxis);

            draw();

        }

        var exampleChart = example(svg, data);
    </script>
  </body>
</html>

提供头衔
简单独立轴在x、y或xy上缩放
.轴路径,.轴线{
填充:无;
行程:#000;
形状渲染:边缘清晰;
}
var数据=[];
对于(变量i=0;i<100;i++){
data.push([Math.random(),Math.random()]);
}
var svg=d3。选择(“#图表”)
.append(“svg”)
.attr(“宽度”,window.innerWidth).attr(“高度”,window.innerHeight);
功能示例(svg、数据){
var-svg;
var保证金={
排名:60,
底部:80,
左:60,,
右:0
};
var宽度=500;
var高度=400;
var xaxis=d3.axisBottom();
var yaxis=d3.axisLeft();
var xscale=d3.scaleLinear();
var yscale=d3.scaleLinear();
var xcopyScale,ycopyScale;
变量xyzoom、xzoom、yzoom;
updateZooms();
函数更新(){
var gs=svg.select(“g.scatter”);
变量循环=gs。选择全部(“循环”)
.数据(数据);
circle.enter().append(“svg:circle”)
.attr(“类”、“点”)
.样式(“填充”、“钢蓝”)
.attr(“cx”,功能(d){
返回X(d);
})
.attr(“cy”,函数(d){
返回Y(d);
})
.attr(“r”,4);
圆属性(“cx”,函数(d){
返回X(d);
})
.attr(“cy”,函数(d){
返回Y(d);
});
circle.exit().remove();
}
函数updateZooms(){
xyzoom=d3.zoom()
.on(“缩放”,函数(){
scale(d3.event.transform.rescaleX(xscale));
yaxis.scale(d3.event.transform.rescaleY(yscale));
draw();
});
xzoom=d3.zoom()
.on(“缩放”,函数(){
scale(d3.event.transform.rescaleX(xscale));
draw();
});
yzoom=d3.zoom()
.on(“缩放”,函数(){
yaxis.scale(d3.event.transform.rescaleY(yscale));
draw();
});
}
函数绘图(){
svg.select('g.x.axis').call(xaxis);
svg.select('g.y.axis').call(yaxis);
更新();
//在每次绘图之后,我们重新初始化缩放。在每次缩放之后,我们重新执行绘图,这将重新初始化缩放。
//这就是我们如何将多个独立缩放行为应用于缩放的方法。
//(请注意,缩放行为将始终以1.0左右的缩放和[0,0]左右的平移结束)
选择('rect.zoom.xy.box')。调用(xyzoom);
选择('rect.zoom.x.box')。调用(xzoom);
svg.select('rect.zoom.y.box').call(yzoom);
}
//缩放的X值
函数X(d){
返回xaxis.scale()!==undefined&&xaxis.scale()!==null
?xaxis.scale()(d[0])
:xscale(d[0]);
}
//比例Y值
函数Y(d){
返回yaxis.scale()!==undefined&&yaxis.scale()!==null
?yaxis.scale()(d[1])
:yscale(d[1]);
}
var g=svg.append('g')
.attr(“转换”、“平移”(+margin.left+)、“+margin.top+”);
g、 附加(“defs”)。附加(“clipPath”)
.attr(“id”、“剪辑”)
.append(“rect”)
.attr(“宽度”,宽度-边距。左侧-边距。右侧)
.attr(“高度”,高度-边距。顶部-边距。底部);
g、 追加(“svg:rect”)
.attr(“类”、“边界”)
.attr(“宽度”,宽度-边距。左侧-边距。右侧)
.attr(“高度”,高度-边距.顶部-边距.底部)
.style(“笔划”、“黑色”)
.样式(“填充”、“无”);
g、 附加(“g”).attr(“类”、“x轴”)
.attr(“转换”、“平移”(+0+),“+(高度-边距.顶部-边距.底部)+”);