D3缩放功能无法使用。

3
我知道这里有一个简单的解决方案,但我尝试运行了几个教程并未能将其应用到我的代码中。 我通过绘制每个3-5数据点段的单独区域来创建高程图表。 因此,在同一图表上发生了相当多的绘图。因此,我尝试了缩放技术,它们会在svg元素上进行缩放,但一直没有成功。 这是我最新的尝试。 希望你们能帮忙。
当前情况下,当我尝试缩放时,它会重置x和y比例尺为[0,1]并用填充颜色填充整个区域。
这是一个Plunk: 链接
// ***************************** //
//             Set Up            //
// ***************************** //

// *** MAP VARIABLES ***

L.mapbox.accessToken = 'pk.eyJ1Ijoid2lsbGlhbWx1Y2UiLCJhIjoiNE1zU0xMNCJ9.X9y-S0ubezlH-aefwUZslA';
var map = L.mapbox.map('map', 'examples.map-i86nkdio')



// *** CHART VARIABLES ***

var margin = {top: 10, right: 20, bottom: 30, left: 100},
    width = 1100 - margin.left - margin.right,
    height = 150 - margin.top - margin.bottom;

// Map colors to limits
var color = d3.scale.ordinal()
    .domain([-10,-5,0,5,10])
    .range(['#a1d99b','#c7e9c0','#fdd0a2','#fdae6b','#fd8d3c','#e6550d']);

// Set up the size of the chart relative to the div
var x = d3.scale.linear().range([0, width]);
var y = d3.scale.linear().range([height, 0]);

// Define the look of the axis
var xAxis = d3.svg.axis().scale(x).orient("bottom").ticks(5);
var yAxis = d3.svg.axis().scale(y).orient("left").ticks(5);

// Define an area. Areas are filled with color.
var area = d3.svg.area()
    .x(function(d) { return x(d.distance); })
    .y0(height)
    .y1(function(d) { return y(d.elevation); });

// Define the line
var valueline = d3.svg.line()
    .interpolate("linear")
    .x(function(d) { return x(d.distance); })
    .y(function(d) { return y(d.elevation); })

// Set up the SVG element
var svg = d3.select("#chart-container")
    .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 + ")")
    .call(zoomed);

// Define the zoom behavior
var zoom = d3.behavior.zoom()
    .x(x)
    .y(y)
    .scaleExtent([1, 10])
    .on("zoom", zoomed);

// Caculate the average gradient of a dataGroup.
function dataGroupGradient(dataGroup)
{
  var sum = dataGroup[0].gradient;
  for (var i = 1; i < dataGroup.length; i++)
  {
    sum += parseFloat(dataGroup[i].gradient);  
  }
  return sum/dataGroup.length;
}

// Define polyline options
// http://leafletjs.com/reference.html#polyline
var polyline_options = {
    stroke: true,
    weight: 3,
    fill: true,
    color: '#03f'
};

// Declare an array for holding the points that make up the path on the map
var line_points = [];


// ***************************** //
//     WORKING WITH THE DATA     //
// ***************************** //

// Get the data
d3.csv("first5km_Strade_Bianche.csv", function(error, data) {
    data.forEach(function(d) {
        d.distance = +d.distance;
        d.elevation = +d.elevation;
        d.gradient = +d.gradient;
        d.latitude = +d.latitude;
        d.longitude = +d.longitude;
        line_points.push([d.latitude, d.longitude]);
    });

    // Scale the range of the entire chart
    x.domain(d3.extent(data, function(d) { return d.distance; }));
    y.domain([0, d3.max(data, function(d) { return d.elevation; })]);

    // Add the overall valueline path. This path uses all of the data.
    svg.append("path")
        .attr("d", valueline(data));

    // Split the data based on "group"
    var dataGroup = d3.nest()
        .key(function(d) {
            return d.group;
        })
        .entries(data);

    // To remove white space between dataGroups, append the first element of one
    // dataGroup to the last element of the previous dataGroup.
    dataGroup.forEach(function(group, i) {
      if(i < dataGroup.length - 1) {
        group.values.push(dataGroup[i+1].values[0])
      }
    })

    // Draw the array of line_points to the map and fit the bounds.
    var polyline = L.polyline(line_points, polyline_options).addTo(map);
    map.fitBounds(polyline.getBounds());

    // Add a line and an area for each dataGroup
    dataGroup.forEach(function(d, i){
        svg.append("path")
            .datum(d.values)
            .attr("class", "area")
            .attr("d", area);
        });

    // Fill the dataGroups with color
    svg.selectAll(".area")
        .style("fill", function(d) { return color(dataGroupGradient(d)); });

    // Add the X Axis
    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);

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

    // Add the text label for the X axis
    svg.append("text")
        .attr("transform",
              "translate(" + (width/2) + " ," + 
                             (height+margin.bottom) + ")")
        .style("text-anchor", "middle")
        .text("Distance");

    // Add the text label for the Y axis
    svg.append("text")
        .attr("transform", "rotate(-90)")
        .attr("y", 6)
        .attr("x", margin.top - (height / 2))
        .attr("dy", ".71em")
        .style("text-anchor", "end")
        .text("");

    svg.append("clipPath")
        .attr("id", "clip")
        .append("rect")
        .attr("width", width)
        .attr("height", height);

});

// *********************** //
//  Zoom specific updates  //
// *********************** //
function zoomed() {
    svg.select(".x.axis").call(xAxis);
    svg.select(".y.axis").call(yAxis);   
    svg.selectAll('path.line').attr('d', line);   
}

你的 Plunk 不起作用,因为它缺少输入文件 first5km_Strade_Bianche.csv。此外,你选择了 d3.select("#chart-container"),但没有具有 id=chart-container 的元素。请修正你的 Plunk。 - altocumulus
不确定为什么会发生这种情况。可能是在保存之前获取了链接。现在已经好了。 - Will Luce
1个回答

5
D3文档中,比例尺被附加到缩放功能上,其中指定:

# zoom.x([x])

… 如果比例尺的域或范围是以编程方式修改的,则应再次调用此函数。

在设置比例尺的域之前,需要推迟将比例尺绑定到缩放侦听器上:

// create the zoom listener
var zoomListener = d3.behavior.zoom()
//    Defer binding of scales until domains have been set.
//    .x(x)  
//    .y(y)
    .scaleExtent([1, 10])
    .on("zoom", zoomHandler);

在数据加载完成并且比例尺的域值被设置好后,您可以将比例尺绑定到监听器上,并将其附加到您的svg

// Scale the range of the entire chart
x.domain(d3.extent(data, function(d) { return d.distance; }));
y.domain([0, d3.max(data, function(d) { return d.elevation; })]);
svg.call(zoomListener.x(x).y(y));

请检查已经调整的plunker,看它是否能解决你的问题。 点击此处

就是这样!我感觉现在我欠你费用了。有没有想法为什么在缩放时它会超出轴的范围? - Will Luce
你必须正确设置你的剪辑路径。它应该放在<defs>部分(在更新的plunker中第61行),然后在第127行被引用以供使用。你可能还想查看有关D3中有界平移的有用文章,以进一步限制平移的范围。 - altocumulus
太好了。谢谢你。我只是想要一个资源。 - Will Luce

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接