Reputation: 415
I have this line chart that works but the problem is that I'm trying to put a title on the line chart above it and it won't work because d3.js keeps appending it inside the the elements of the chart. How can I fix this? Below is the snippet of my code:
$(document).ready(() => {
// set the dimensions and margins of the graph
var margin = { top: 20, right: 20, bottom: 30, left: 50 },
width = 1000 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the date / time
var parseTime = d3.timeParse("%H:%M:%S");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// define the line
var valueline = d3.line()
.x(function (d) { return x(d.availability_time); })
.y(function (d) { return y(d.total_hour_percentage); });
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svg = d3.select("#lineChart").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 + ")");
function draw(data) {
console.log(data[0].availability_time);
// format the data
data.forEach(function (d) {
d.availability_time = (parseTime(d.availability_time));
d.total_hour_percentage = d.total_hour_percentage;
});
// sort time ascending
data.sort(function (a, b) {
return a["availability_time"] - b["availability_time"];
})
// Scale the range of the data
x.domain(d3.extent(data, function (d) {
return d.availability_time;
}));
y.domain([0, d3.max(data, function (d) {
return Math.max(d.total_hour_percentage);
})]);
// Add the valueline path.
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
// Add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(d3.timeHour.every(1)).tickFormat(d3.timeFormat('%H:%M')));
// Add the Y Axis
svg.append("g")
.call(d3.axisLeft(y));
}
svg.append('text')
.attr('class', 'title')
.attr('x', width / 2 + margin)
.attr('y', 40)
.attr('text-anchor', 'middle')
.text('Availability (%) of CAM for date: ');
// Get the data
// var perHourResult = "/perHourAvailabilities/" + defaultDate;
// console.log(perHourResult);
var perHourResult =
[
{ "id": 0, "availability_time": "00:00:00", "total_hour_percentage": 99.55 },
{ "id": 0, "availability_time": "01:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "02:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "03:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "04:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "05:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "06:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "07:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "08:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "09:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "10:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "11:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "12:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "13:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "14:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "15:00:00", "total_hour_percentage": 99.75 },
{ "id": 0, "availability_time": "16:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "17:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "18:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "19:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "20:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "21:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "22:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "23:00:00", "total_hour_percentage": 100.0 }
];
console.log(perHourResult[0].availability_time); //shows 00:00:00
draw(perHourResult);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DASHBOARD</title>
<!--Lib css-->
<!--bootstrap-->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!--fontawesome-->
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<!--jquery-->
<script src="https://code.jquery.com/jquery-3.5.0.js"
integrity="sha256-r/AaFHrszJtwpe+tHyNi/XCfMxYpbsRg2Uqn0x3s2zc=" crossorigin="anonymous"></script>
<!--own css-->
<style>
@import "https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700";
body {
font-family: 'Poppins', sans-serif;
background: #fafafa;
}
p {
font-family: 'Poppins', sans-serif;
font-size: 1.1em;
font-weight: 300;
line-height: 1.7em;
color: #999;
}
a,
a:hover,
a:focus {
color: inherit;
text-decoration: none;
transition: all 0.3s;
}
.navbar {
padding: 15px 10px;
background: #fff;
border: none;
border-radius: 0;
margin-bottom: 40px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
}
.navbar-btn {
box-shadow: none;
outline: none !important;
border: none;
}
/* ---------------------------------------------------
SIDEBAR STYLE
----------------------------------------------------- */
.wrapper {
display: flex;
width: 100%;
align-items: stretch;
}
#sidebar {
min-width: 250px;
max-width: 250px;
background: rgb(60, 95, 238);
color: #fff;
transition: all 0.3s;
}
#sidebar.active {
margin-left: -250px;
}
#sidebar .sidebar-header {
padding: 20px;
background: rgb(90, 121, 243);
}
#sidebar ul.components {
padding: 20px 0;
border-bottom: 1px solid #47748b;
}
#sidebar ul p {
color: #fff;
padding: 10px;
}
#sidebar ul li a {
padding: 10px;
font-size: 1.1em;
display: block;
}
#sidebar ul li a:hover {
color: #7386D5;
background: #fff;
}
#sidebar ul li.active>a,
a[aria-expanded="true"] {
color: #fff;
background: #6d7fcc;
}
a[data-toggle="collapse"] {
position: relative;
}
.dropdown-toggle::after {
display: block;
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
}
ul ul a {
font-size: 0.9em !important;
padding-left: 30px !important;
background: #6d7fcc;
}
ul.CTAs {
padding: 20px;
}
ul.CTAs a {
text-align: center;
font-size: 0.9em !important;
display: block;
border-radius: 5px;
margin-bottom: 5px;
}
a.download {
background: #fff;
color: #7386D5;
}
a.article,
a.article:hover {
background: #6d7fcc !important;
color: #fff !important;
}
/* ---------------------------------------------------
CONTENT STYLE
----------------------------------------------------- */
#content {
width: 100%;
padding: 20px;
min-height: 100vh;
transition: all 0.3s;
}
/* ---------------------------------------------------
MEDIAQUERIES
----------------------------------------------------- */
@media (max-width: 768px) {
#sidebar {
margin-left: -250px;
}
#sidebar.active {
margin-left: 0;
}
#sidebarCollapse span {
display: none;
}
}
/* ---------------------------------------------------
CHART STYLE
-----------------------------------------------------
/* LINE CHART STYLE */
.axis--x path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<!--lib js-->
<!--bootstrap-->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
<!--fontawesome js-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
<!--d3(chart) js-->
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<div class="wrapper">
<!-- Sidebar -->
<nav id="sidebar">
<ul class="list-unstyled components">
<li class="active">
<a href="/">DASHBOARD</a>
</li>
</ul>
<!--End of nav.sidebar-->
</nav>
<!--Page content-->
<div id="content">
<!-- navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<button type="button" id="sidebarCollapse" class="btn btn-info">
<i class="fas fa-align-justify"></i>
</button>
</div>
</nav>
<!--End of div.row-->
<div class="row">
<div class="col-12">
<div class="card shadow mb-5">
<div class="card-body">
<div id="lineChart">
</div>
</div>
</div>
</div>
</div>
<!--End of div.row-->
</div>
</div>
<!--End of div.content-->
</div>
<!--End of div.wrapper-->
<!--Lib <script>-->
<!--own <script>-->
<script src="js/script3.js"></script>
</body>
</html>
I've tried creating another element to hold the svg as a container and append the all the characteristic of the line chart below the text element that holds the title of the line chart but what happens is that it appends inside the <text>
element. Please help.
Upvotes: 0
Views: 3091
Reputation: 4282
the variable svg
is in fact the element that you appended. If you want to add the title on top the element, you need to have a variable to hold the element.
Also margin
is an object, you need reference the property that holds the value.
$(document).ready(() => {
// set the dimensions and margins of the graph
var margin = { top: 40, right: 20, bottom: 30, left: 50 },
width = 1000 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
// parse the date / time
var parseTime = d3.timeParse("%H:%M:%S");
// set the ranges
var x = d3.scaleTime().range([0, width]);
var y = d3.scaleLinear().range([height, 0]);
// define the line
var valueline = d3.line()
.x(function (d) { return x(d.availability_time); })
.y(function (d) { return y(d.total_hour_percentage); });
// append the svg obgect to the body of the page
// appends a 'group' element to 'svg'
// moves the 'group' element to the top left margin
var svgp = d3.select("#lineChart").append("svg")
.attr("width", width + margin.left + margin.right)
.attr("height", height + margin.top + margin.bottom)
var svg= svgp.append("g")
.attr("transform",
"translate(" + margin.left + "," + margin.top + ")");
function draw(data) {
console.log(data[0].availability_time);
// format the data
data.forEach(function (d) {
d.availability_time = (parseTime(d.availability_time));
d.total_hour_percentage = d.total_hour_percentage;
});
// sort time ascending
data.sort(function (a, b) {
return a["availability_time"] - b["availability_time"];
})
// Scale the range of the data
x.domain(d3.extent(data, function (d) {
return d.availability_time;
}));
y.domain([0, d3.max(data, function (d) {
return Math.max(d.total_hour_percentage);
})]);
// Add the valueline path.
svg.append("path")
.data([data])
.attr("class", "line")
.attr("d", valueline);
// Add the X Axis
svg.append("g")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(d3.timeHour.every(1)).tickFormat(d3.timeFormat('%H:%M')));
// Add the Y Axis
svg.append("g")
.call(d3.axisLeft(y));
}
svgp.append('text')
.attr('class', 'title')
.attr('x', width / 2)
.attr('y', margin.top/2)
.attr('text-anchor', 'middle')
.text('Availability (%) of CAM for date: ');
// Get the data
// var perHourResult = "/perHourAvailabilities/" + defaultDate;
// console.log(perHourResult);
var perHourResult =
[
{ "id": 0, "availability_time": "00:00:00", "total_hour_percentage": 99.55 },
{ "id": 0, "availability_time": "01:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "02:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "03:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "04:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "05:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "06:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "07:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "08:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "09:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "10:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "11:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "12:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "13:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "14:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "15:00:00", "total_hour_percentage": 99.75 },
{ "id": 0, "availability_time": "16:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "17:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "18:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "19:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "20:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "21:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "22:00:00", "total_hour_percentage": 100.0 },
{ "id": 0, "availability_time": "23:00:00", "total_hour_percentage": 100.0 }
];
console.log(perHourResult[0].availability_time); //shows 00:00:00
draw(perHourResult);
});
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DASHBOARD</title>
<!--Lib css-->
<!--bootstrap-->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<!--fontawesome-->
<link href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"
integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<!--jquery-->
<script src="https://code.jquery.com/jquery-3.5.0.js"
integrity="sha256-r/AaFHrszJtwpe+tHyNi/XCfMxYpbsRg2Uqn0x3s2zc=" crossorigin="anonymous"></script>
<!--own css-->
<style>
@import "https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700";
body {
font-family: 'Poppins', sans-serif;
background: #fafafa;
}
p {
font-family: 'Poppins', sans-serif;
font-size: 1.1em;
font-weight: 300;
line-height: 1.7em;
color: #999;
}
a,
a:hover,
a:focus {
color: inherit;
text-decoration: none;
transition: all 0.3s;
}
.navbar {
padding: 15px 10px;
background: #fff;
border: none;
border-radius: 0;
margin-bottom: 40px;
box-shadow: 1px 1px 3px rgba(0, 0, 0, 0.1);
}
.navbar-btn {
box-shadow: none;
outline: none !important;
border: none;
}
/* ---------------------------------------------------
SIDEBAR STYLE
----------------------------------------------------- */
.wrapper {
display: flex;
width: 100%;
align-items: stretch;
}
#sidebar {
min-width: 250px;
max-width: 250px;
background: rgb(60, 95, 238);
color: #fff;
transition: all 0.3s;
}
#sidebar.active {
margin-left: -250px;
}
#sidebar .sidebar-header {
padding: 20px;
background: rgb(90, 121, 243);
}
#sidebar ul.components {
padding: 20px 0;
border-bottom: 1px solid #47748b;
}
#sidebar ul p {
color: #fff;
padding: 10px;
}
#sidebar ul li a {
padding: 10px;
font-size: 1.1em;
display: block;
}
#sidebar ul li a:hover {
color: #7386D5;
background: #fff;
}
#sidebar ul li.active>a,
a[aria-expanded="true"] {
color: #fff;
background: #6d7fcc;
}
a[data-toggle="collapse"] {
position: relative;
}
.dropdown-toggle::after {
display: block;
position: absolute;
top: 50%;
right: 20px;
transform: translateY(-50%);
}
ul ul a {
font-size: 0.9em !important;
padding-left: 30px !important;
background: #6d7fcc;
}
ul.CTAs {
padding: 20px;
}
ul.CTAs a {
text-align: center;
font-size: 0.9em !important;
display: block;
border-radius: 5px;
margin-bottom: 5px;
}
a.download {
background: #fff;
color: #7386D5;
}
a.article,
a.article:hover {
background: #6d7fcc !important;
color: #fff !important;
}
/* ---------------------------------------------------
CONTENT STYLE
----------------------------------------------------- */
#content {
width: 100%;
padding: 20px;
min-height: 100vh;
transition: all 0.3s;
}
/* ---------------------------------------------------
MEDIAQUERIES
----------------------------------------------------- */
@media (max-width: 768px) {
#sidebar {
margin-left: -250px;
}
#sidebar.active {
margin-left: 0;
}
#sidebarCollapse span {
display: none;
}
}
/* ---------------------------------------------------
CHART STYLE
-----------------------------------------------------
/* LINE CHART STYLE */
.axis--x path {
display: none;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
<!--lib js-->
<!--bootstrap-->
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js"
integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6"
crossorigin="anonymous"></script>
<!--fontawesome js-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/js/all.min.js"></script>
<!--d3(chart) js-->
<script src="https://d3js.org/d3.v5.min.js"></script>
</head>
<body>
<div class="wrapper">
<!-- Sidebar -->
<nav id="sidebar">
<ul class="list-unstyled components">
<li class="active">
<a href="/">DASHBOARD</a>
</li>
</ul>
<!--End of nav.sidebar-->
</nav>
<!--Page content-->
<div id="content">
<!-- navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container-fluid">
<button type="button" id="sidebarCollapse" class="btn btn-info">
<i class="fas fa-align-justify"></i>
</button>
</div>
</nav>
<!--End of div.row-->
<div class="row">
<div class="col-12">
<div class="card shadow mb-5">
<div class="card-body">
<div id="lineChart">
</div>
</div>
</div>
</div>
</div>
<!--End of div.row-->
</div>
</div>
<!--End of div.content-->
</div>
<!--End of div.wrapper-->
<!--Lib <script>-->
<!--own <script>-->
<script src="js/script3.js"></script>
</body>
</html>
Upvotes: 1