簡體   English   中英

如何在 d3.js 中使用縮放和平移繪制網格線

[英]How do I draw gridlines in d3.js with zoom and pan

我已經能夠使用縮放和平移功能制作散點圖,其中軸正確縮放並且一切正常。 現在我想弄清楚如何添加網格線,但遇到了一些問題。 我開始只添加 x 軸網格線來解決問題。 我附上了一個帶有工作示例的小提琴。

我在生成圖表時注釋掉了初始網格線,因為它們會在縮放后保留,導致混亂,我會在以后工作時將它們添加回來。 縮放時,網格線似乎繪制正確,但它們與 x 軸標簽不匹配,並且 x 軸標簽在縮放或平移后消失。

如果您注釋掉第 163 行並取消注釋第 164 行,您可以看到沒有任何網格線的基本圖形。 單擊繪圖按鈕將始終生成一個新圖形。 我留下了一些我通過stackoverflow搜索嘗試過的不同事物的注釋代碼。

示例是使用 d3.js - 5.9.2

JSFiddle: https ://jsfiddle.net/eysLvqkh/11/

HTML:

<div id="reg_plot"></div>
<button id="b" class="myButton">plot</button>

Javascript:

var theButton = document.getElementById("b");
theButton.onclick = createSvg;

function createSvg() {
                        // clear old chart when 'plot' is clicked
                        document.getElementById('reg_plot').innerHTML = ""
                        // dimensions
            var margin = {top: 20, right: 20, bottom: 30, left: 55},
                svg_dx = 1200, 
                svg_dy =600,
                chart_dx = svg_dx - margin.right - margin.left,
                chart_dy = svg_dy - margin.top - margin.bottom;

            // data
            var y = d3.randomNormal(400, 100);
            var x_jitter = d3.randomUniform(-100, 1400);

            var d = d3.range(1000)
                        .map(function() { 
                            return [x_jitter(), y()]; 
                        });

            // fill
            var colorScale = d3.scaleLinear()
                                .domain(d3.extent(d, function(d) { return d[1]; }))
                                .range([0, 1]);


            // y position
            var yScale = d3.scaleLinear()
                            .domain(d3.extent(d, function(d) { return d[1]; }))
                            .range([chart_dy, margin.top]);
            
            // x position
            var xScale = d3.scaleLinear()
                            .domain(d3.extent(d, function(d) { return d[0]; }))
                            .range([margin.right, chart_dx]);

            // y-axis
            var yAxis = d3.axisLeft(yScale);

            // x-axis
            var xAxis = d3.axisBottom(xScale);

            // append svg to div element 'reg_plot' and set zoom to our function named 'zoom'
            var svg = d3.select("#reg_plot")
                        .append("svg")
                        .attr("width", svg_dx)
                        .attr("height", svg_dy);
            svg.call(d3.zoom().on("zoom", zoom));

            // clip path - sets boundaries so points will not show outside of the axes when zooming/panning
            var clip = svg.append("defs").append("svg:clipPath")
            .attr("id", "clip")
            .append("svg:rect")
            .attr("id", "clip-rect")
            .attr("x", "0")
            .attr("y", "0")
            .attr('width', chart_dx)
            .attr('height', chart_dy);

            // plot data
            var circles = svg.append("g")
                            .attr("id", "circles")
                            .attr("transform", "translate(75, 0)")
                            .attr("clip-path", "url(#clip)")
                            .selectAll("circle")
                            .data(d)
                            .enter()
                            .append("circle")
                            .attr("r", 4)
                            .attr("cx", function(d) { return xScale(d[0]); })
                            .attr("cy", function(d) { return yScale(d[1]); })
                            .style("fill", function(d) { 
                                var norm_color = colorScale(d[1]);
                                return d3.interpolateInferno(norm_color) 
                            });

            // add y-axis
            var y_axis = svg.append("g")
                            .attr("id", "y_axis")
                            .attr("transform", "translate(75,0)")
                            .call(yAxis).style("font-size", "10px")
                        
            // add x-axis
            var x_axis = svg.append("g")
                            .attr("id", "x_axis")
                            .attr("transform", `translate(${margin.left}, ${svg_dy - margin.bottom - margin.top})`)
                            .call(xAxis).style("font-size", "10px")
            
            // add x and y grid lines
            x_axis.call(xAxis.scale(xScale).ticks(20).tickSize(-chart_dy));
            y_axis.call(yAxis.scale(yScale).ticks(20).tickSize(-chart_dx));

            function zoom(e) {
                // re-scale y axis during zoom
                y_axis.transition()
                        .duration(50)
                        .call(yAxis.scale(d3.event.transform.rescaleY(yScale)));

                // re-scale x axis during zoom
                x_axis.transition()
                        .duration(50)
                        .call(xAxis.scale(d3.event.transform.rescaleX(xScale)));

                // re-draw circles using new scales
                var new_xScale = d3.event.transform.rescaleX(xScale);
                var new_yScale = d3.event.transform.rescaleY(yScale);

                // re-scale axes and gridlines
                x_axis.call(xAxis.scale(new_xScale).ticks(20).tickSize(-chart_dy));
                y_axis.call(yAxis.scale(new_yScale).ticks(20).tickSize(-chart_dx));
                circles.data(d)
                    .attr('cx', function(d) {return new_xScale(d[0])})
                    .attr('cy', function(d) {return new_yScale(d[1])});                
            }

        }
             

對於任何尋找的人,我已經解決了這個問題。 我已經更新了原始帖子中的 javascript,並更新了 jsfiddle。 如果您將此代碼復制到使用 d3.js 7.4.4 或更高版本的本地計算機,則需要將 d3.event.transform.... 的行更改為僅 e.transform。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM