我知道这里有一个简单的解决方案,但我已经尝试了一些教程并且无法将它们应用到我的代码中。我通过为3-5个数据点的每个段绘制单独的area
来创建高程图。所以,我在同一个图表上发生了不少情节。因此我尝试了缩放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);
}
答案 0 :(得分:4)
D3关于附加到zoom behaviour的比例的文档指定:
#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);
加载数据后,缩放&#39;相应地设置了域值,您可以将比例绑定到侦听器,然后将其附加到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,看看这是否能解决您的问题。