我想制作一个条形图,我可以在其中显示由条形图表示的特定时间段。
$(document).ready(function() {
render_chart();
});
function render_chart() {
var dataset = {
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
],
"gates": [
"Test-Gate"
],
"operators": [
"Operator1",
"Operator2",
"Operator3",
],
"layers": [
[{
"fromHours": "14:20:00",
"toHours": "23:00:00",
"gate": "Test-Gate"
}],
[{
"fromHours": "08:30:00",
"toHours": "11:20:00",
"gate": "Test-Gate"
}],
[{
"fromHours": "16:00:00",
"toHours": "18:00:00",
"gate": "Test-Gate"
}]
]
};
n = dataset["operators"].length;
var today = new Date();
today.setHours(0, 0, 0, 0);
todayMillis = today.getTime();
var layersData = dataset["layers"];
console.log("BEFORE", layersData[0][0]);
layersData.forEach(function(layer) {
layer.forEach(function(innerLayer) {
var fromHourParts = innerLayer.fromHours.split(/:/);
var toHourParts = innerLayer.toHours.split(/:/);
innerLayer.fromHours = new Date();
innerLayer.fromHours.setTime(todayMillis + getTimePeriodMillis(fromHourParts));
innerLayer.toHours = new Date();
innerLayer.toHours.setTime(todayMillis + getTimePeriodMillis(toHourParts));
})
});
console.log("AFTER", dataset["layers"][0][0]);
function getTimePeriodMillis(parts) {
return (parseInt(parts[0], 10) * 60 * 60 * 1000) +
(parseInt(parts[1], 10) * 60 * 1000) +
(parseInt(parts[2], 10) * 1000);
}
function appendExtraZeroToSingleValues(inputValue) {
if (inputValue === 0) {
return inputValue + "0";
}
return inputValue;
}
var parseTime = d3.timeParse("%H:%M");
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var svg = d3.select("#groupchart").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 + ")");
var tomorrow = new Date();
tomorrow.setHours(0, 0, 0, 0);
tomorrow.setDate(today.getDate());
var xScale = d3.scaleTime()
.domain([new Date(), new Date()])
.nice(d3.timeDay, 1)
.range([0, width - margin.left]);
var yScale = d3.scaleBand()
.domain(dataset["gates"])
.rangeRound([0, height])
.padding(.08);
var xAxis = d3.axisBottom(xScale)
.ticks(24)
.tickSize(-height)
.tickFormat(d3.timeFormat("%H"));
console.log("X-DOMAIN", xScale.domain());
console.log("X-RANGE", xScale.range());
var yAxis = d3.axisLeft(yScale)
.tickSize(-(width - margin.left))
.tickPadding(5);
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("y", function(d, i, j) {
var k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes, j[i].parentNode);
return yScale(d.gate) + yScale.bandwidth() / n * k;
})
.attr("height", yScale.bandwidth() / n)
.transition()
.attr("x", function(d) {
console.log(xScale(d.fromHours));
return xScale(d.fromHours);
})
.attr("width", function(d) {
console.log(xScale(d.toHours - d.fromHours));
return xScale(Math.abs(d.toHours - d.fromHours / 36e5));
})
.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.select("g")
.attr("class", "y axis")
.call(yAxis);
var legend = svg.append("g")
.attr("class", "legend");
legend.selectAll('text')
.data(dataset["operators"])
.enter()
.append("rect")
.attr("x", function(d, i) {
return (i * 120) + (width / 3);
})
.attr("y", width / 2.8)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d, i) {
return dataset["colors"][i];
})
legend.selectAll('text')
.data(dataset["operators"])
.enter()
.append("text")
.attr("x", function(d, i) {
return (i * 120) + (width / 3) + 12;
})
.attr("y", (width / 2.8) + 10)
.text(function(d) {
return d;
});
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'gate');
tooltip.append('div')
.attr('class', 'tempRange');
svg.selectAll("rect")
.on('mouseover', function(d, i) {
if (!d.gate) return null;
tooltip.select('.gate').html("<b>" + dataset["operators"][i] + "</b>");
tooltip.select('.tempRange').html(appendExtraZeroToSingleValues(d.fromHours.getHours()) + ":" +
appendExtraZeroToSingleValues(d.fromHours.getMinutes()) + " Hours to " +
appendExtraZeroToSingleValues(d.toHours.getHours()) + ":" +
appendExtraZeroToSingleValues(d.toHours.getMinutes()) + " Hours");
tooltip.style('display', 'block');
tooltip.style('opacity', 2);
})
.on('mousemove', function(d) {
if (!d.gate) 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);
});
}
.axis .tick line {
stroke-width: 1;
stroke: rgba(0, 0, 0, 0.2);
}
.axis path,
.axis line {
fill: none;
font: 10px sans-serif;
stroke: #000;
shape-rendering: crispEdges;
}
.legend {
padding: 5px;
font-size: 15px;
font-family: 'Roboto', sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
z-index: 10;
display: block;
opacity: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Bar Graph</title>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="groupchart" class="chart"></div>
</body>
</html>
尝试如上,但无法弄清楚如何正确地做到这一点。我搞砸了,酒吧不会以某种方式结束在图表中。 x轴域全部搞乱,并且还有宽度。如果我采取另一种规模,它工作正常。但是在时间尺度上,我无法使其发挥作用。
我做错了什么?
答案 0 :(得分:1)
而不是将值的差异传递给比例......
scale(a - b)
...将每个值传递给比例并减去它们:
scale(a) - scale(b).
在你的情况下:
return xScale(Math.abs(d.toHours)) - xScale(Math.abs(d.fromHours));
以下是具有该更改的代码:
$(document).ready(function() {
render_chart();
});
function render_chart() {
var dataset = {
"colors": [
"#1f77b4",
"#aec7e8",
"#ff7f0e",
],
"gates": [
"Test-Gate"
],
"operators": [
"Operator1",
"Operator2",
"Operator3",
],
"layers": [
[{
"fromHours": "14:20:00",
"toHours": "23:00:00",
"gate": "Test-Gate"
}],
[{
"fromHours": "08:30:00",
"toHours": "11:20:00",
"gate": "Test-Gate"
}],
[{
"fromHours": "16:00:00",
"toHours": "18:00:00",
"gate": "Test-Gate"
}]
]
};
n = dataset["operators"].length;
var today = new Date();
today.setHours(0, 0, 0, 0);
todayMillis = today.getTime();
var layersData = dataset["layers"];
console.log("BEFORE", layersData[0][0]);
layersData.forEach(function(layer) {
layer.forEach(function(innerLayer) {
var fromHourParts = innerLayer.fromHours.split(/:/);
var toHourParts = innerLayer.toHours.split(/:/);
innerLayer.fromHours = new Date();
innerLayer.fromHours.setTime(todayMillis + getTimePeriodMillis(fromHourParts));
innerLayer.toHours = new Date();
innerLayer.toHours.setTime(todayMillis + getTimePeriodMillis(toHourParts));
})
});
console.log("AFTER", dataset["layers"][0][0]);
function getTimePeriodMillis(parts) {
return (parseInt(parts[0], 10) * 60 * 60 * 1000) +
(parseInt(parts[1], 10) * 60 * 1000) +
(parseInt(parts[2], 10) * 1000);
}
function appendExtraZeroToSingleValues(inputValue) {
if (inputValue === 0) {
return inputValue + "0";
}
return inputValue;
}
var parseTime = d3.timeParse("%H:%M");
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = 600 - margin.left - margin.right,
height = 300 - margin.top - margin.bottom;
var svg = d3.select("#groupchart").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 + ")");
var tomorrow = new Date();
tomorrow.setHours(0, 0, 0, 0);
tomorrow.setDate(today.getDate());
var xScale = d3.scaleTime()
.domain([new Date(), new Date()])
.nice(d3.timeDay, 1)
.range([0, width - margin.left]);
var yScale = d3.scaleBand()
.domain(dataset["gates"])
.rangeRound([0, height])
.padding(.08);
var xAxis = d3.axisBottom(xScale)
.ticks(24)
.tickSize(-height)
.tickFormat(d3.timeFormat("%H"));
console.log("X-DOMAIN", xScale.domain());
console.log("X-RANGE", xScale.range());
var yAxis = d3.axisLeft(yScale)
.tickSize(-(width - margin.left))
.tickPadding(5);
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("y", function(d, i, j) {
var k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes, j[i].parentNode);
return yScale(d.gate) + yScale.bandwidth() / n * k;
})
.attr("height", yScale.bandwidth() / n)
.transition()
.attr("x", function(d) {
console.log(xScale(d.fromHours));
return xScale(d.fromHours);
})
.attr("width", function(d) {
console.log(xScale(d.toHours - d.fromHours));
return xScale(Math.abs(d.toHours)) - xScale(Math.abs(d.fromHours));
})
.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.select("g")
.attr("class", "y axis")
.call(yAxis);
var legend = svg.append("g")
.attr("class", "legend");
legend.selectAll('text')
.data(dataset["operators"])
.enter()
.append("rect")
.attr("x", function(d, i) {
return (i * 120) + (width / 3);
})
.attr("y", width / 2.8)
.attr("width", 10)
.attr("height", 10)
.style("fill", function(d, i) {
return dataset["colors"][i];
})
legend.selectAll('text')
.data(dataset["operators"])
.enter()
.append("text")
.attr("x", function(d, i) {
return (i * 120) + (width / 3) + 12;
})
.attr("y", (width / 2.8) + 10)
.text(function(d) {
return d;
});
var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');
tooltip.append('div')
.attr('class', 'gate');
tooltip.append('div')
.attr('class', 'tempRange');
svg.selectAll("rect")
.on('mouseover', function(d, i) {
if (!d.gate) return null;
tooltip.select('.gate').html("<b>" + dataset["operators"][i] + "</b>");
tooltip.select('.tempRange').html(appendExtraZeroToSingleValues(d.fromHours.getHours()) + ":" +
appendExtraZeroToSingleValues(d.fromHours.getMinutes()) + " Hours to " +
appendExtraZeroToSingleValues(d.toHours.getHours()) + ":" +
appendExtraZeroToSingleValues(d.toHours.getMinutes()) + " Hours");
tooltip.style('display', 'block');
tooltip.style('opacity', 2);
})
.on('mousemove', function(d) {
if (!d.gate) 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);
});
}
&#13;
.axis .tick line {
stroke-width: 1;
stroke: rgba(0, 0, 0, 0.2);
}
.axis path,
.axis line {
fill: none;
font: 10px sans-serif;
stroke: #000;
shape-rendering: crispEdges;
}
.legend {
padding: 5px;
font-size: 15px;
font-family: 'Roboto', sans-serif;
background: yellow;
box-shadow: 2px 2px 1px #888;
}
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
font-size: 12px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
z-index: 10;
display: block;
opacity: 0;
}
&#13;
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Bar Graph</title>
<script
src="https://code.jquery.com/jquery-3.3.1.min.js"
integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
crossorigin="anonymous"></script>
<script src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div id="groupchart" class="chart"></div>
</body>
</html>
&#13;