gpt4 book ai didi

d3.js - 在 d3 js 中移动 y 轴刻度线

转载 作者:行者123 更新时间:2023-12-02 02:53:47 26 4
gpt4 key购买 nike

我有如下带有刻度线的分组条形图。

$(document).ready(function() {
render_chart();
});

function render_chart() {

var dataset = {
"colors": [
"#1f77b4",
"#ffbb78",
"#e74c3c",
"#2ecc71",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#9467bd",
"#3498db",
],
"operators": [
"Client1",
"Client2",
"Client3",
"Client4"
],
"days": [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
],
"schedules": [{
"fromHours": "00:00:00",
"toHours": "08:00:00",
"operator": "Client1",
"day": "Monday",
"color": "#1f77b4"
},
{
"fromHours": "00:00:00",
"toHours": "08:00:00",
"operator": "Client2",
"day": "Monday",
"color": "#ffbb78"
},
{
"fromHours": "08:00:00",
"toHours": "14:00:00",
"operator": "Client2",
"day": "Monday",
"color": "#ffbb78"
},
{
"fromHours": "14:00:00",
"toHours": "18:00:00",
"operator": "Client3",
"day": "Monday",
"color": "#e74c3c"
},
{
"fromHours": "18:00:00",
"toHours": "23:59:59",
"operator": "Client4",
"day": "Monday",
"color": "#2ecc71"
},
{
"fromHours": "02:00:00",
"toHours": "16:00:00",
"operator": "Client4",
"day": "Tuesday",
"color": "#2ecc71"
},
{
"fromHours": "16:00:00",
"toHours": "20:00:00",
"operator": "Client3",
"day": "Tuesday",
"color": "#e74c3c"
},
{
"fromHours": "16:00:00",
"toHours": "23:59:59",
"operator": "Client1",
"day": "Tuesday",
"color": "#1f77b4"
},
{
"fromHours": "00:00:00",
"toHours": "17:00:00",
"operator": "Client4",
"day": "Wednesday",
"color": "#2ecc71"
},
{
"fromHours": "17:00:00",
"toHours": "23:59:59",
"operator": "Client3",
"day": "Wednesday",
"color": "#e74c3c"
}
]
};

var schedulesDataset = dataset["schedules"];
var daysDataset = dataset["days"];
dataset.layers = new Array();
var mondayData = new Array();
var tuesdayData = new Array();
var wednesdayData = new Array();
var thursdayData = new Array();
var fridayData = new Array();
var saturdayData = new Array();
var sundayData = new Array();

schedulesDataset.forEach(function(schedule) {
switch (schedule.day) {
case "Monday":
mondayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Tuesday":
tuesdayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Wednesday":
wednesdayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Thursday":
thursdayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Friday":
fridayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Saturday":
saturdayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Sunday":
sundayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
}
});

dataset.layers.push(mondayData);
dataset.layers.push(tuesdayData);
dataset.layers.push(wednesdayData);
dataset.layers.push(thursdayData);
dataset.layers.push(fridayData);
dataset.layers.push(saturdayData);
dataset.layers.push(sundayData);

var numberOfOperators = dataset["operators"].length;

var today = new Date();
today.setHours(0, 0, 0, 0);
todayMillis = today.getTime();
var layersData = dataset["layers"];
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));
})
});

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";
}
var parsedInputValue = inputValue.toString();
if (parsedInputValue.length === 1) {
return "0" + inputValue;
}
return inputValue;
}

var offsetWidth = 1000;
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = offsetWidth - margin.left - margin.right,
height = 600 - 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 xScale = d3.scaleTime()
.domain([new Date(), new Date()])
.nice(d3.timeDay, 1)
.range([0, width - margin.left]);

var yScale = d3.scaleBand()
.domain(dataset["days"])
.rangeRound([0, height])
.padding(.08);

var xAxis = d3.axisBottom(xScale)
.ticks(24)
.tickSize(-height)
.tickFormat(d3.timeFormat("%H"));

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) {
return d;
})
.enter()
.append("rect")
.transition()
.duration(500)
.delay(function(d, i) {
return i * 100;
})
.attr("y", function(d, i) {
return yScale(d.day) + yScale.bandwidth() / 7 * i;
})
.attr("height", yScale.bandwidth() / 7)
.transition()
.attr("x", function(d) {
return xScale(d.fromHours)
})
.attr("width", function(d) {
return xScale(Math.abs(d.toHours)) - xScale(Math.abs(d.fromHours));
})
.attr("class", "bar")
.style("fill", function(d, i) {
return d.color;
});

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 * (offsetWidth / 10)) + (width / numberOfOperators);
})
.attr("y", function(d, i) {
return height + 30;
})
.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 * (offsetWidth / 10)) + (width / numberOfOperators) + 12;
})
.attr("y", function(d, i) {
return height + 40;
})
.text(function(d) {
return d;
});

var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');

tooltip.append('div')
.attr('class', 'operator');
tooltip.append('div')
.attr('class', 'timeRange');

svg.selectAll("rect")
.on('mouseover', function(d, i) {
if (!d.day) return null;

tooltip.select('.operator').html("<b>" + d.operator + "</b>");
tooltip.select('.timeRange').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.day) 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>


由于某些条形不是从 0 位置开始,因此它看起来不像一个组。我想将那些 y 轴刻度线向上移动 half of the distance between current tick position and the next tick position ,因此分组条出现在 2 条黑线内。我认为在那种情况下它会更好看,也许我们可以应用一些 css 来区分每个相邻的组。

我不知道该怎么做,所以我四处搜索并没有找到类似的东西。有可能实现吗?

任何帮助是极大的赞赏 :)

最佳答案

这些线对应于轴的刻度,它们由轴生成器自动创建和定位。

无需过多的重构或定制,您可以在它们创建后简单地将它们向下移动:

d3.selectAll(".y.axis .tick line").each(function(){
d3.select(this)
.attr("transform", "translate(0," + yScale.bandwidth()/2 + ")")
});

这是具有该更改的代码:

$(document).ready(function() {
render_chart();
});

function render_chart() {

var dataset = {
"colors": [
"#1f77b4",
"#ffbb78",
"#e74c3c",
"#2ecc71",
"#aec7e8",
"#ff7f0e",
"#2ca02c",
"#98df8a",
"#9467bd",
"#3498db",
],
"operators": [
"Client1",
"Client2",
"Client3",
"Client4"
],
"days": [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
"Sunday"
],
"schedules": [{
"fromHours": "00:00:00",
"toHours": "08:00:00",
"operator": "Client1",
"day": "Monday",
"color": "#1f77b4"
},
{
"fromHours": "00:00:00",
"toHours": "08:00:00",
"operator": "Client2",
"day": "Monday",
"color": "#ffbb78"
},
{
"fromHours": "08:00:00",
"toHours": "14:00:00",
"operator": "Client2",
"day": "Monday",
"color": "#ffbb78"
},
{
"fromHours": "14:00:00",
"toHours": "18:00:00",
"operator": "Client3",
"day": "Monday",
"color": "#e74c3c"
},
{
"fromHours": "18:00:00",
"toHours": "23:59:59",
"operator": "Client4",
"day": "Monday",
"color": "#2ecc71"
},
{
"fromHours": "02:00:00",
"toHours": "16:00:00",
"operator": "Client4",
"day": "Tuesday",
"color": "#2ecc71"
},
{
"fromHours": "16:00:00",
"toHours": "20:00:00",
"operator": "Client3",
"day": "Tuesday",
"color": "#e74c3c"
},
{
"fromHours": "16:00:00",
"toHours": "23:59:59",
"operator": "Client1",
"day": "Tuesday",
"color": "#1f77b4"
},
{
"fromHours": "00:00:00",
"toHours": "17:00:00",
"operator": "Client4",
"day": "Wednesday",
"color": "#2ecc71"
},
{
"fromHours": "17:00:00",
"toHours": "23:59:59",
"operator": "Client3",
"day": "Wednesday",
"color": "#e74c3c"
}
]
};

var schedulesDataset = dataset["schedules"];
var daysDataset = dataset["days"];
dataset.layers = new Array();
var mondayData = new Array();
var tuesdayData = new Array();
var wednesdayData = new Array();
var thursdayData = new Array();
var fridayData = new Array();
var saturdayData = new Array();
var sundayData = new Array();

schedulesDataset.forEach(function(schedule) {
switch (schedule.day) {
case "Monday":
mondayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Tuesday":
tuesdayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Wednesday":
wednesdayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Thursday":
thursdayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Friday":
fridayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Saturday":
saturdayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
case "Sunday":
sundayData.push({
"fromHours": schedule.fromHours,
"toHours": schedule.toHours,
"operator": schedule.operator,
"day": schedule.day,
"color": schedule.color
});
break;
}
});

dataset.layers.push(mondayData);
dataset.layers.push(tuesdayData);
dataset.layers.push(wednesdayData);
dataset.layers.push(thursdayData);
dataset.layers.push(fridayData);
dataset.layers.push(saturdayData);
dataset.layers.push(sundayData);

var numberOfOperators = dataset["operators"].length;

var today = new Date();
today.setHours(0, 0, 0, 0);
todayMillis = today.getTime();
var layersData = dataset["layers"];
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));
})
});

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";
}
var parsedInputValue = inputValue.toString();
if (parsedInputValue.length === 1) {
return "0" + inputValue;
}
return inputValue;
}

var offsetWidth = 1000;
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 100
},
width = offsetWidth - margin.left - margin.right,
height = 600 - 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 xScale = d3.scaleTime()
.domain([new Date(), new Date()])
.nice(d3.timeDay, 1)
.range([0, width - margin.left]);

var yScale = d3.scaleBand()
.domain(dataset["days"])
.rangeRound([0, height])
.padding(.08);

var xAxis = d3.axisBottom(xScale)
.ticks(24)
.tickSize(-height)
.tickFormat(d3.timeFormat("%H"));

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) {
return d;
})
.enter()
.append("rect")
.transition()
.duration(500)
.delay(function(d, i) {
return i * 100;
})
.attr("y", function(d, i) {
return yScale(d.day) + yScale.bandwidth() / 7 * i;
})
.attr("height", yScale.bandwidth() / 7)
.transition()
.attr("x", function(d) {
return xScale(d.fromHours)
})
.attr("width", function(d) {
return xScale(Math.abs(d.toHours)) - xScale(Math.abs(d.fromHours));
})
.attr("class", "bar")
.style("fill", function(d, i) {
return d.color;
});

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

svg.select("g")
.attr("class", "y axis")
.call(yAxis);

d3.selectAll(".y.axis .tick line").each(function(){
d3.select(this).attr("transform", "translate(0," + yScale.bandwidth()/2 + ")")
});

var legend = svg.append("g")
.attr("class", "legend")

legend.selectAll('text')
.data(dataset["operators"])
.enter()
.append("rect")
.attr("x", function(d, i) {
return (i * (offsetWidth / 10)) + (width / numberOfOperators);
})
.attr("y", function(d, i) {
return height + 30;
})
.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 * (offsetWidth / 10)) + (width / numberOfOperators) + 12;
})
.attr("y", function(d, i) {
return height + 40;
})
.text(function(d) {
return d;
});

var tooltip = d3.select("body")
.append('div')
.attr('class', 'tooltip');

tooltip.append('div')
.attr('class', 'operator');
tooltip.append('div')
.attr('class', 'timeRange');

svg.selectAll("rect")
.on('mouseover', function(d, i) {
if (!d.day) return null;

tooltip.select('.operator').html("<b>" + d.operator + "</b>");
tooltip.select('.timeRange').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.day) 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>


如果您遵循这种方法,最后(星期日)行看起来不太好……但您可以简单地将其删除。

关于d3.js - 在 d3 js 中移动 y 轴刻度线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50582147/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com