我尝试使用d3 js创建具有缩放/平移功能的条形图。缩放效果很好,但是当我向左或向右平移图表时,条形在最小和最大X值旁边消失。我做错了什么? please check this image with issue described 这是小提琴:https://jsfiddle.net/Cayman/vpn8mz4g/1/
function render_chart(){
var stack = d3.layout.stack();
var dataset = {
"categories": ['2018-06-01T00:00:00.000+03:00',
'2018-06-02T00:00:00.000+03:00',
'2018-06-03T00:00:00.000+03:00',
'2018-06-04T00:00:00.000+03:00',
'2018-06-05T00:00:00.000+03:00',
'2018-06-06T00:00:00.000+03:00',
'2018-06-07T00:00:00.000+03:00',
'2018-06-08T00:00:00.000+03:00',
'2018-06-09T00:00:00.000+03:00',
'2018-06-10T00:00:00.000+03:00',
'2018-06-11T00:00:00.000+03:00',
'2018-06-12T00:00:00.000+03:00'],
"series": ["New York","Mumbai","Bengaluru"],
"colors": ["#3498db","#e74c3c","#2ecc71"],
"layers": [
[
{"y":1,"y0":20,"month":"2018-06-01T00:00:00.000+03:00"},
{"y":2,"y0":18,"month":"2018-06-02T00:00:00.000+03:00"},
{"y":5,"y0":18,"month":"2018-06-03T00:00:00.000+03:00"},
{"y":10,"y0":20,"month":"2018-06-04T00:00:00.000+03:00"},
{"y":14,"y0":23,"month":"2018-06-05T00:00:00.000+03:00"},
{"y":18,"y0":29,"month":"2018-06-06T00:00:00.000+03:00"},
{"y":20,"y0":31,"month":"2018-06-07T00:00:00.000+03:00"},
{"y":20,"y0":29,"month":"2018-06-08T00:00:00.000+03:00"},
{"y":16,"y0":24,"month":"2018-06-09T00:00:00.000+03:00"},
{"y":10,"y0":19,"month":"2018-06-10T00:00:00.000+03:00"},
{"y":5,"y0":23,"month":"2018-06-11T00:00:00.000+03:00"},
{"y":3,"y0":20,"month":"2018-06-12T00:00:00.000+03:00"}
],
[
{"y":12,"y0":24,"month":"2018-06-01T00:00:00.000+03:00"},
{"y":14,"y0":25,"month":"2018-06-02T00:00:00.000+03:00"},
{"y":13,"y0":31,"month":"2018-06-03T00:00:00.000+03:00"},
{"y":16,"y0":32,"month":"2018-06-04T00:00:00.000+03:00"},
{"y":18,"y0":33,"month":"2018-06-05T00:00:00.000+03:00"},
{"y":19,"y0":29,"month":"2018-06-06T00:00:00.000+03:00"},
{"y":20,"y0":27,"month":"2018-06-07T00:00:00.000+03:00"},
{"y":18,"y0":26,"month":"2018-06-08T00:00:00.000+03:00"},
{"y":20,"y0":31,"month":"2018-06-09T00:00:00.000+03:00"},
{"y":17,"y0":29,"month":"2018-06-10T00:00:00.000+03:00"},
{"y":18,"y0":26,"month":"2018-06-11T00:00:00.000+03:00"},
{"y":14,"y0":24,"month":"2018-06-12T00:00:00.000+03:00"}
],[
{"y":8,"y0":24,"month":"2018-06-01T00:00:00.000+03:00"},
{"y":14,"y0":26,"month":"2018-06-02T00:00:00.000+03:00"},
{"y":12,"y0":31,"month":"2018-06-03T00:00:00.000+03:00"},
{"y":15,"y0":33,"month":"2018-06-04T00:00:00.000+03:00"},
{"y":18,"y0":37,"month":"2018-06-05T00:00:00.000+03:00"},
{"y":16,"y0":29,"month":"2018-06-06T00:00:00.000+03:00"},
{"y":17,"y0":27,"month":"2018-06-07T00:00:00.000+03:00"},
{"y":19,"y0":25,"month":"2018-06-08T00:00:00.000+03:00"},
{"y":25,"y0":30,"month":"2018-06-09T00:00:00.000+03:00"},
{"y":23,"y0":31,"month":"2018-06-10T00:00:00.000+03:00"},
{"y":11,"y0":26,"month":"2018-06-11T00:00:00.000+03:00"},
{"y":12,"y0":23,"month":"2018-06-12T00:00:00.000+03:00"}
]
]
}
dataset["categories"].forEach(function(d2) {
d = new Date(d2);
});
dataset["layers"].forEach(function(d) {
d.forEach(function(d2) {
d2.month = new Date(d2.month);
});
});
n = dataset["series"].length, // Number of Layers
m = dataset["layers"].length, // Number of Samples in 1 layer
yGroupMax = d3.max(dataset["layers"], function(layer) { return d3.max(layer, function(d) { return d.y0; }); });
yGroupMin = d3.min(dataset["layers"], function(layer) { return d3.min(layer, function(d) { return d.y; }); });
var pWidth = document.getElementById('chart1').offsetWidth;
var margin = {top: 50, right: 0, bottom: 50, left: 100},
width = pWidth - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.time.scale()
.domain([new Date(dataset["categories"][0]),new Date(dataset["categories"][11]),])
.range([0, width]);
var y = d3.scale.linear()
.domain([yGroupMin, yGroupMax])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(dataset["categories"].length)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var zoom = d3.behavior.zoom()
.x(x)
.scaleExtent([0, Infinity])
.on("zoom", zoomed);
var svg = d3.select("#chart1").append("svg")
.call(zoom)
.attr("class", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer");
var rect = layer.selectAll("rect")
.data(function(d,i){d.map(function(b){b.colorIndex=i;return b;});return d;})
.enter().append("rect")
.transition()
.duration(500)
.delay(function(d, i) { return i * 10; })
.attr("x", function(d, i, j) {
var qqq = x(d.month);
var qqq2 = x(d.month) + 30 / n * j;
return x(d.month) + 30 / n * j;
})
.attr("width", 30 / n)
.transition()
.attr("y", function(d) { return y(d.y0); })
.attr("height", function(d) { return height - y(d.y0-0)})
.attr("class","bar")
.style("fill",function(d){return dataset["colors"][d.colorIndex];})
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("text")
.attr("x", width/3)
.attr("y", 0)
.attr("dx", ".71em")
.attr("dy", "-.71em")
.text("Min - Max Temperature (Month wise)");
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
function zoomed() {
console.warn("zoom");
svg.select(".x.axis").call(xAxis);
console.log(d3.event.translate[0] + " " + d3.event.translate[1]);
svg.selectAll(".chart rect").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
}
enter code here
}
答案 0 :(得分:0)
您需要在混合中添加一个剪切路径:
var svg = d3.select("#chart1").append("svg")
.call(zoom)
.attr("class", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
// create clip-path that's the same size as drawing area
svg.append('defs')
.append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', width)
.attr('height', height);
svg = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer")
.attr('clip-path', 'url(#clip)'); //<-- clip drawing area
运行代码:
$(document).ready(function() {
render_chart();
});
function render_chart() {
var stack = d3.layout.stack();
var dataset = {
"categories": ['2018-06-01T00:00:00.000+03:00',
'2018-06-02T00:00:00.000+03:00',
'2018-06-03T00:00:00.000+03:00',
'2018-06-04T00:00:00.000+03:00',
'2018-06-05T00:00:00.000+03:00',
'2018-06-06T00:00:00.000+03:00',
'2018-06-07T00:00:00.000+03:00',
'2018-06-08T00:00:00.000+03:00',
'2018-06-09T00:00:00.000+03:00',
'2018-06-10T00:00:00.000+03:00',
'2018-06-11T00:00:00.000+03:00',
'2018-06-12T00:00:00.000+03:00'
],
"series": ["New York", "Mumbai", "Bengaluru"],
"colors": ["#3498db", "#e74c3c", "#2ecc71"],
"layers": [
[{
"y": 1,
"y0": 20,
"month": "2018-06-01T00:00:00.000+03:00"
},
{
"y": 2,
"y0": 18,
"month": "2018-06-02T00:00:00.000+03:00"
},
{
"y": 5,
"y0": 18,
"month": "2018-06-03T00:00:00.000+03:00"
},
{
"y": 10,
"y0": 20,
"month": "2018-06-04T00:00:00.000+03:00"
},
{
"y": 14,
"y0": 23,
"month": "2018-06-05T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 29,
"month": "2018-06-06T00:00:00.000+03:00"
},
{
"y": 20,
"y0": 31,
"month": "2018-06-07T00:00:00.000+03:00"
},
{
"y": 20,
"y0": 29,
"month": "2018-06-08T00:00:00.000+03:00"
},
{
"y": 16,
"y0": 24,
"month": "2018-06-09T00:00:00.000+03:00"
},
{
"y": 10,
"y0": 19,
"month": "2018-06-10T00:00:00.000+03:00"
},
{
"y": 5,
"y0": 23,
"month": "2018-06-11T00:00:00.000+03:00"
},
{
"y": 3,
"y0": 20,
"month": "2018-06-12T00:00:00.000+03:00"
}
],
[{
"y": 12,
"y0": 24,
"month": "2018-06-01T00:00:00.000+03:00"
},
{
"y": 14,
"y0": 25,
"month": "2018-06-02T00:00:00.000+03:00"
},
{
"y": 13,
"y0": 31,
"month": "2018-06-03T00:00:00.000+03:00"
},
{
"y": 16,
"y0": 32,
"month": "2018-06-04T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 33,
"month": "2018-06-05T00:00:00.000+03:00"
},
{
"y": 19,
"y0": 29,
"month": "2018-06-06T00:00:00.000+03:00"
},
{
"y": 20,
"y0": 27,
"month": "2018-06-07T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 26,
"month": "2018-06-08T00:00:00.000+03:00"
},
{
"y": 20,
"y0": 31,
"month": "2018-06-09T00:00:00.000+03:00"
},
{
"y": 17,
"y0": 29,
"month": "2018-06-10T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 26,
"month": "2018-06-11T00:00:00.000+03:00"
},
{
"y": 14,
"y0": 24,
"month": "2018-06-12T00:00:00.000+03:00"
}
],
[{
"y": 8,
"y0": 24,
"month": "2018-06-01T00:00:00.000+03:00"
},
{
"y": 14,
"y0": 26,
"month": "2018-06-02T00:00:00.000+03:00"
},
{
"y": 12,
"y0": 31,
"month": "2018-06-03T00:00:00.000+03:00"
},
{
"y": 15,
"y0": 33,
"month": "2018-06-04T00:00:00.000+03:00"
},
{
"y": 18,
"y0": 37,
"month": "2018-06-05T00:00:00.000+03:00"
},
{
"y": 16,
"y0": 29,
"month": "2018-06-06T00:00:00.000+03:00"
},
{
"y": 17,
"y0": 27,
"month": "2018-06-07T00:00:00.000+03:00"
},
{
"y": 19,
"y0": 25,
"month": "2018-06-08T00:00:00.000+03:00"
},
{
"y": 25,
"y0": 30,
"month": "2018-06-09T00:00:00.000+03:00"
},
{
"y": 23,
"y0": 31,
"month": "2018-06-10T00:00:00.000+03:00"
},
{
"y": 11,
"y0": 26,
"month": "2018-06-11T00:00:00.000+03:00"
},
{
"y": 12,
"y0": 23,
"month": "2018-06-12T00:00:00.000+03:00"
}
]
]
}
var parseDate = d3.time.format("%Y-%m-%d").parse;
dataset["categories"].forEach(function(d2) {
d = new Date(d2);
});
dataset["layers"].forEach(function(d) {
d.forEach(function(d2) {
d2.month = new Date(d2.month);
});
});
n = dataset["series"].length, // Number of Layers
m = dataset["layers"].length, // Number of Samples in 1 layer
yGroupMax = d3.max(dataset["layers"], function(layer) {
return d3.max(layer, function(d) {
return d.y0;
});
});
yGroupMin = d3.min(dataset["layers"], function(layer) {
return d3.min(layer, function(d) {
return d.y;
});
});
var pWidth = document.getElementById('chart1').offsetWidth;
var margin = {
top: 50,
right: 0,
bottom: 50,
left: 100
},
width = pWidth - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var x = d3.time.scale()
.domain([new Date(dataset["categories"][0]), addDays(new Date(dataset["categories"][11]), 1)])
.range([0, width]);
var y = d3.scale.linear()
.domain([yGroupMin, yGroupMax])
.range([height, 0]);
var xAxis = d3.svg.axis()
.scale(x)
.tickSize(dataset["categories"].length)
.tickPadding(6)
.orient("bottom");
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");
var zoom = d3.behavior.zoom()
.x(x)
.scaleExtent([0, Infinity])
.on("zoom", zoomed);
var svg = d3.select("#chart1").append("svg")
.call(zoom)
.attr("class", "chart")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom);
svg.append('defs')
.append('clipPath')
.attr('id', 'clip')
.append('rect')
.attr('x', 0)
.attr('y', 0)
.attr('width', width)
.attr('height', height);
svg = svg.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var layer = svg.selectAll(".layer")
.data(dataset["layers"])
.enter().append("g")
.attr("class", "layer")
.attr('clip-path', 'url(#clip)');
var rect = layer.selectAll("rect")
.data(function(d, i) {
d.map(function(b) {
b.colorIndex = i;
return b;
});
return d;
})
.enter().append("rect")
.transition()
.duration(500)
.delay(function(d, i) {
return i * 10;
})
.attr("x", function(d, i, j) {
var qqq = x(d.month);
var qqq2 = x(d.month) + 30 / n * j;
return x(d.month) + 30 / n * j;
})
.attr("width", 30 / n)
.transition()
.attr("y", function(d) {
return y(d.y0);
})
.attr("height", function(d) {
return height - y(d.y0 - 0)
})
.attr("class", "bar")
.style("fill", function(d) {
return dataset["colors"][d.colorIndex];
})
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
svg.append("text")
.attr("x", width / 3)
.attr("y", 0)
.attr("dx", ".71em")
.attr("dy", "-.71em")
.text("Min - Max Temperature (Month wise)");
svg.append("clipPath")
.attr("id", "clip")
.append("rect")
.attr("width", width)
.attr("height", height);
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'month');
tooltip.append('div')
.attr('class', 'tempRange');
svg.selectAll("rect")
.on('mouseover', function(d) {
if (!d.month) return null;
tooltip.select('.month').html("<b>" + d.month + "</b>");
tooltip.select('.tempRange').html(d.y + "℃ to " + d.y0 + "℃");
tooltip.style('display', 'block');
tooltip.style('opacity', 2);
})
.on('mousemove', function(d) {
if (!d.month) return null;
tooltip.style('top', (d3.event.layerY + 10) + 'px')
.style('left', (d3.event.layerX - 25) + 'px');
})
.on('mouseout', function() {
tooltip.style('display', 'none');
tooltip.style('opacity', 0);
});
function zoomed() {
console.warn("zoom");
svg.select(".x.axis").call(xAxis);
console.log(d3.event.translate[0] + " " + d3.event.translate[1]);
svg.selectAll(".chart rect").attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ", 1)");
}
function addDays(startDate, numberOfDays) {
var returnDate = new Date(
startDate.getFullYear(),
startDate.getMonth(),
startDate.getDate() + numberOfDays,
startDate.getHours(),
startDate.getMinutes(),
startDate.getSeconds());
return returnDate;
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Multi Series Span Chart (Vertical)</title>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<div id="chart1" class="chart" style="width: 100%;"></div>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.min.js"></script>
</body>
<script type="text/javascript" src="main.js"></script>
</html>