0

我将如何修改以下使用 d3 的代码,以允许沿 x 轴拖动图形:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title></title>
<style type="text/css">
    .axis path, .axis line {
        fill: none;
        stroke: #ddd;
        stroke-width: 1px;
        shape-rendering: crispEdges;
    }
    .axis path
    {
        stroke: #999;
        stroke-width: 2px;
    }

</style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript" src="http://d3js.org/d3.v2.min.js?2.9.4"></script>
</head>
<body>
    <div id="chart" class="background">
    </div>
</body>
    <script type="text/javascript">
        var data = [{
            Id: "1",
            Year: 1950,
            Relevance: 55,
            Category: "Cat1",
            SpecFreq: 5,
            GenFreq: 10
        }, {
            Id: "2",
            Year: 1975,
            Relevance: 25,
            Category: "Cat1",
            SpecFreq: 2,
            GenFreq: 31
        }, {
            Id: "1",
            Year: 1990,
            Relevance: 75,
            Category: "Cat1",
            SpecFreq: 8,
            GenFreq: 23
        }];

        $(function () {
            DrawFocus(data);
        });

        function DrawFocus(data) {
            //dimensions
            var margin = {
                top: 5.5,
                right: 19.5,
                bottom: 39.5,
                left: 39.5
            },
            width = 800 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

            //data domain extents
            var extentX = d3.extent(data, function (d) {
                return d.Year;
            });
            var extentY = d3.extent(data, function (d) {
                return d.Relevance;
            });

            //pad extents to provide some extra "blank" areas around edge of graph
            extentX[0] = extentX[0] - 5;
            extentX[1] = extentX[1] + 5;
            extentY[0] = extentY[0] - 5;
            extentY[1] = extentY[1] + 5;

            //scales
            var x = d3.scale.linear().domain(extentX).range([0, width]);
            var y = d3.scale.linear().domain(extentY).range([height, 0]);
            var radiusMax = .025 * width;
            var radius = d3.scale.sqrt().domain([0, 100]).range([0, radiusMax]);
            var color = d3.scale.ordinal().domain(["Cat1", "Cat2", "Cat3"]).range(["#b7b8a0", "#898a72", "#878772"]);

            //axes
            var xAxis = d3.svg.axis().scale(x).orient("bottom").tickFormat(d3.format("d")).tickSize(-height);
            var yAxis = d3.svg.axis().scale(y).orient("left").tickSize(-width);

            //create and size svg element, add zoom behavior
            var svg = d3.select("#chart").append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
                .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            // Add the x-axis.
            svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0," + height + ")")
                .call(xAxis)
                .selectAll("text")
                .style("font-size", "10px")
                .attr("dy", "1.5em");

            // Add the y-axis.
            svg.append("g")
                .attr("class", "y axis")
                .call(yAxis);

            // Add the x-axis label.
            svg.append("text")
                .attr("class", "x label")
                .attr("text-anchor", "end")
                .attr("x", width / 2)
                .attr("y", height + 35)
                .text(" Year");

            // Add the y-axis label.
            svg.append("text")
                .attr("class", "y label")
                .attr("text-anchor", "end")
                .attr("x", -1 * height / 2)
                .attr("y", -40)
                .attr("dy", ".75em")
                .attr("transform", "rotate(-90)")
                .text("Relevance");

            //plot genFreq
            var gGenerally = svg.append("g").selectAll("circle")
                .data(data)
                .enter().append("circle")
                .style("fill", function (d) {
                    return color(d.Category);
                })
                .attr("cx", function (d) {
                    return x(d.Year);
                })
                .attr("cy", function (d) {
                    return y(d.Relevance);
                })
                .attr("r", function (d) {
                    return radius(d.GenFreq);
                })
                .append("title")
                .text(function (d) {
                    return "(" + d.Year + ", " + d.Relevance + ", " + d.GenFreq + ", " + d.SpecFreq + ")";
                });

            //plot specFreq
            var gWithin = svg.append("g").selectAll("circle")
                .data(data)
                .enter().append("circle")
                .style("fill", function (d) {
                    return "#d6d487";
                })
                .attr("cx", function (d) {
                    return x(d.Year);
                })
                .attr("cy", function (d) {
                    return y(d.Relevance);
                })
                .attr("r", function (d) {
                    return radius(d.SpecFreq);
                })
                .append("title")
                .text(function (d) {
                    return "(" + d.Year + ", " + d.Relevance + ", " + d.GenFreq + ", " + d.SpecFreq + ")";
                });

            return svg;
        }
    </script>
</html>

我在网上找到了几个示例,并意识到我需要使用缩放行为,但无法准确地弄清楚如何做到这一点。上面的代码有一个小提琴可用。

4

1 回答 1

1

应用如下所示的缩放功能,以及一些额外的代码来限制缩放域,我需要做的就是让它工作。一旦图形被滚动到任何方向的远端,我似乎确实会出现一些奇怪的“粘性”。它有时会犹豫片刻,然后再往回滚动。我不确定是什么原因造成的。此外,这个例子有点不切实际,因为我正在修剪我的域以匹配我的数据中的最小值和最大值,然后添加一个 +- 5 缓冲区。所以,你真的只能滚动那个缓冲区域。但是,我认为如果您应用了更大的域,它的行为会相同。

<html>
<head>
<style type="text/css">
    .axis path, .axis line {
        fill: none;
        stroke: #ddd;
        stroke-width: 1px;
        shape-rendering: crispEdges;
    }
    .axis path
    {
        stroke: #999;
        stroke-width: 2px;
    }

</style>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js" type="text/javascript"></script>
    <script type="text/javascript" src="http://d3js.org/d3.v2.min.js?2.9.4"></script>
</head>
<body>
    <div id="chart" class="background">
    </div>
</body>
    <script type="text/javascript">
        var data = [{
            Id: "1",
            Year: 1950,
            Relevance: 55,
            Category: "Cat1",
            SpecFreq: 5,
            GenFreq: 10
        }, {
            Id: "2",
            Year: 1975,
            Relevance: 25,
            Category: "Cat1",
            SpecFreq: 2,
            GenFreq: 31
        }, {
            Id: "1",
            Year: 1990,
            Relevance: 75,
            Category: "Cat1",
            SpecFreq: 8,
            GenFreq: 23
        }];

        $(function () {
            DrawFocus(data);
        });

        function DrawFocus(data) {
            //dimensions
            var margin = {
                top: 5.5,
                right: 19.5,
                bottom: 39.5,
                left: 39.5
            },
            width = 800 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;

            //data domain extents
            var extentX = d3.extent(data, function (d) {
                return d.Year;
            });
            var extentY = d3.extent(data, function (d) {
                return d.Relevance;
            });

            //pad extents to provide some extra "blank" areas around edge of graph
            extentX[0] = extentX[0] - 5;
            extentX[1] = extentX[1] + 5;
            extentY[0] = extentY[0] - 5;
            extentY[1] = extentY[1] + 5;

            //scales
            var x = d3.scale.linear().domain(extentX).range([0, width]);
            var y = d3.scale.linear().domain(extentY).range([height, 0]);
            var radiusMax = .025 * width;
            var radius = d3.scale.sqrt().domain([0, 100]).range([0, radiusMax]);
            var color = d3.scale.ordinal().domain(["Cat1", "Cat2", "Cat3"]).range(["#b7b8a0", "#898a72", "#878772"]);

            //axes
            var xAxis = d3.svg.axis().scale(x).orient("bottom").tickFormat(d3.format("d")).tickSize(-height).ticks(10);
            var yAxis = d3.svg.axis().scale(y).orient("left").tickSize(-width).ticks(10);

            //create and size svg element, add zoom behavior
            var svg = d3.select("#chart").append("svg")
                .attr("width", width + margin.left + margin.right)
                .attr("height", height + margin.top + margin.bottom)
                .call(d3.behavior.zoom().x(x).y(y).scaleExtent([1, 8]).on("zoom", zoom))
                .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            // Add the x-axis.
            svg.append("g")
                .attr("class", "x axis")
                .attr("transform", "translate(0," + height + ")")
                .call(xAxis)
                .selectAll("text")
                .style("font-size", "10px")
                .attr("dy", "1.5em");

            // Add the y-axis.
            svg.append("g")
                .attr("class", "y axis")
                .call(yAxis)
                .selectAll("text")
                .style("font-size", "10px")
                .attr("dx", "-1em");

            // Add the x-axis label.
            svg.append("text")
                .attr("class", "x label")
                .attr("text-anchor", "end")
                .attr("x", width / 2)
                .attr("y", height + 35)
                .text(" Year");

            // Add the y-axis label.
            svg.append("text")
                .attr("class", "y label")
                .attr("text-anchor", "end")
                .attr("x", -1 * height / 2)
                .attr("y", -40)
                .attr("dy", ".75em")
                .attr("transform", "rotate(-90)")
                .text("Relevance");

            //plot genFreq
            var gGenerally = svg.append("g").selectAll("circle")
                .data(data)
                .enter().append("circle")
                .style("fill", function (d) {
                    return color(d.Category);
                })
                .attr("cx", function (d) {
                    return x(d.Year);
                })
                .attr("cy", function (d) {
                    return y(d.Relevance);
                })
                .attr("r", function (d) {
                    return radius(d.GenFreq);
                })
                .append("title")
                .text(function (d) {
                    return "(" + d.Year + ", " + d.Relevance + ", " + d.GenFreq + ", " + d.SpecFreq + ")";
                });

            //plot specFreq
            var gWithin = svg.append("g").selectAll("circle")
                .data(data)
                .enter().append("circle")
                .style("fill", function (d) {
                    return "#d6d487";
                })
                .attr("cx", function (d) {
                    return x(d.Year);
                })
                .attr("cy", function (d) {
                    return y(d.Relevance);
                })
                .attr("r", function (d) {
                    return radius(d.SpecFreq);
                })
                .append("title")
                .text(function (d) {
                    return "(" + d.Year + ", " + d.Relevance + ", " + d.GenFreq + ", " + d.SpecFreq + ")";
                });

            function zoom() {
                if (x.domain()[0] >= extentX[0] -5 && x.domain()[1] <= extentX[1] +5 && y.domain()[0] >= extentY[0] -5 && y.domain()[1] <= extentY[1] +5) {
                    svg.select(".x.axis").call(xAxis).selectAll("text")
                    .style("font-size", "10px")
                    .attr("dy", "1.5em");

                    svg.select(".y.axis").call(yAxis).selectAll("text")
                    .style("font-size", "10px")
                    .attr("dx", "-1em");

                    svg.selectAll("circle").attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
                }
            }

            return svg;
        }
    </script>
</html>
于 2013-04-03T20:25:01.717 回答