Reputation: 415
I'm currently studying on how to create a pie-chart with a legend. But the thing is while i'm trying to re-code the program I encountered this error:
As per checking the code error: var color = d3.scaleOrdinal(d3.schemeCategory20c);
i don't know why this became an error since it's usually working.
The code snippet is my code below:
// define data
var dataset = [
{label: "Assamese", count: 100},
{label: "Bengali", count: 83},
{label: "Bodo", count: 1.4},
{label: "Dogri", count: 2.3},
{label: "Gujarati", count: 46},
{label: "Hindi", count: 300},
{label: "Kannada", count: 38},
{label: "Kashmiri", count: 5.5},
{label: "Konkani", count: 5},
{label: "Maithili", count: 20},
{label: "Malayalam", count: 33},
{label: "Manipuri", count: 1.5},
{label: "Marathi", count: 72},
{label: "Nepali", count: 2.9},
{label: "Oriya", count: 33},
{label: "Punjabi", count: 29},
{label: "Sanskrit", count: 0.01},
{label: "Santhali", count: 6.5},
{label: "Sindhi", count: 2.5},
{label: "Tamil", count: 61},
{label: "Telugu", count: 74},
{label: "Urdu", count: 52}
];
// chart dimensions
var width = 1200;
var height = 800;
// a circle chart needs a radius
var radius = Math.min(width, height) / 2;
// legend dimensions
var legendRectSize = 25; // defines the size of the colored squares in legend
var legendSpacing = 6; // defines spacing between squares
// define color scale
var color = d3.scaleOrdinal(d3.schemeCategory20c);
// more color scales: https://bl.ocks.org/pstuffa/3393ff2711a53975040077b7453781a9
var svg = d3.select('#pieChart') // select element in the DOM with id 'chart'
.append('svg') // append an svg element to the element we've selected
.attr('width', width) // set the width of the svg element we just added
.attr('height', height) // set the height of the svg element we just added
.append('g') // append 'g' element to the svg element
.attr('transform', 'translate(' + (width / 2) + ',' + (height / 2) + ')'); // our reference is now to the 'g' element. centerting the 'g' element to the svg element
var arc = d3.arc()
.innerRadius(0) // none for pie chart
.outerRadius(radius); // size of overall chart
var pie = d3.pie() // start and end angles of the segments
.value(function(d) { return d.count; }) // how to extract the numerical data from each entry in our dataset
.sort(null); // by default, data sorts in oescending value. this will mess with our animation so we set it to null
// define tooltip
var tooltip = d3.select('#pieChart') // select element in the DOM with id 'chart'
.append('div') // append a div element to the element we've selected
.attr('class', 'tooltip'); // add class 'tooltip' on the divs we just selected
tooltip.append('div') // add divs to the tooltip defined above
.attr('class', 'label'); // add class 'label' on the selection
tooltip.append('div') // add divs to the tooltip defined above
.attr('class', 'count'); // add class 'count' on the selection
tooltip.append('div') // add divs to the tooltip defined above
.attr('class', 'percent'); // add class 'percent' on the selection
// Confused? see below:
// <div id="chart">
// <div class="tooltip">
// <div class="label">
// </div>
// <div class="count">
// </div>
// <div class="percent">
// </div>
// </div>
// </div>
dataset.forEach(function(d) {
d.count = +d.count; // calculate count as we iterate through the data
d.enabled = true; // add enabled property to track which entries are checked
});
// creating the chart
var path = svg.selectAll('path') // select all path elements inside the svg. specifically the 'g' element. they don't exist yet but they will be created below
.data(pie(dataset)) //associate dataset wit he path elements we're about to create. must pass through the pie function. it magically knows how to extract values and bakes it into the pie
.enter() //creates placeholder nodes for each of the values
.append('path') // replace placeholders with path elements
.attr('d', arc) // define d attribute with arc function above
.attr('fill', function(d) { return color(d.data.label); }) // use color scale to define fill of each label in dataset
.each(function(d) { this._current - d; }); // creates a smooth animation for each track
// mouse event handlers are attached to path so they need to come after its definition
path.on('mouseover', function(d) { // when mouse enters div
var total = d3.sum(dataset.map(function(d) { // calculate the total number of tickets in the dataset
return (d.enabled) ? d.count : 0; // checking to see if the entry is enabled. if it isn't, we return 0 and cause other percentages to increase
}));
var percent = Math.round(1000 * d.data.count / total) / 10; // calculate percent
tooltip.select('.label').html(d.data.label); // set current label
tooltip.select('.count').html('$' + d.data.count); // set current count
tooltip.select('.percent').html(percent + '%'); // set percent calculated above
tooltip.style('display', 'block'); // set display
});
path.on('mouseout', function() { // when mouse leaves div
tooltip.style('display', 'none'); // hide tooltip for that element
});
path.on('mousemove', function(d) { // when mouse moves
tooltip.style('top', (d3.event.layerY + 10) + 'px') // always 10px below the cursor
.style('left', (d3.event.layerX + 10) + 'px'); // always 10px to the right of the mouse
});
// define legend
var legend = svg.selectAll('.legend') // selecting elements with class 'legend'
.data(color.domain()) // refers to an array of labels from our dataset
.enter() // creates placeholder
.append('g') // replace placeholders with g elements
.attr('class', 'legend') // each g is given a legend class
.attr('transform', function(d, i) {
var height = legendRectSize + legendSpacing; // height of element is the height of the colored square plus the spacing
var offset = height * color.domain().length / 2; // vertical offset of the entire legend = height of a single element & half the total number of elements
var horz = 18 * legendRectSize; // the legend is shifted to the left to make room for the text
var vert = i * height - offset; // the top of the element is hifted up or down from the center using the offset defiend earlier and the index of the current element 'i'
return 'translate(' + horz + ',' + vert + ')'; //return translation
});
// adding colored squares to legend
legend.append('rect') // append rectangle squares to legend
.attr('width', legendRectSize) // width of rect size is defined above
.attr('height', legendRectSize) // height of rect size is defined above
.style('fill', color) // each fill is passed a color
.style('stroke', color) // each stroke is passed a color
.on('click', function(label) {
var rect = d3.select(this); // this refers to the colored squared just clicked
var enabled = true; // set enabled true to default
var totalEnabled = d3.sum(dataset.map(function(d) { // can't disable all options
return (d.enabled) ? 1 : 0; // return 1 for each enabled entry. and summing it up
}));
if (rect.attr('class') === 'disabled') { // if class is disabled
rect.attr('class', ''); // remove class disabled
} else { // else
if (totalEnabled < 2) return; // if less than two labels are flagged, exit
rect.attr('class', 'disabled'); // otherwise flag the square disabled
enabled = false; // set enabled to false
}
pie.value(function(d) {
if (d.label === label) d.enabled = enabled; // if entry label matches legend label
return (d.enabled) ? d.count : 0; // update enabled property and return count or 0 based on the entry's status
});
path = path.data(pie(dataset)); // update pie with new data
path.transition() // transition of redrawn pie
.duration(750) //
.attrTween('d', function(d) { // 'd' specifies the d attribute that we'll be animating
var interpolate = d3.interpolate(this._current, d); // this = current path element
this._current = interpolate(0); // interpolate between current value and the new value of 'd'
return function(t) {
return arc(interpolate(t));
};
});
});
// adding text to legend
legend.append('text')
.attr('x', legendRectSize + legendSpacing)
.attr('y', legendRectSize - legendSpacing)
.text(function(d) { return d; }); // return label
<!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
-----------------------------------------------------
body {
font-family: 'Open Sans', sans-serif;
}
.title-holder {
text-align: center;
}
.title {
font-family: 'Lato', sans-serif;
}
.subtitle {
font-size: 20px;
}
.font {
font-size: 18px;
}
/* legend */
.title-holder {
text-align: center;
}
.title {
font-family: 'Lato', sans-serif;
}
.subtitle {
font-size: 20px;
}
.font {
font-size: 18px;
}
.legend {
font-size: 14px;
}
rect {
cursor: pointer;
stroke-width: 2;
}
rect.disabled {
fill: transparent !important;
}
/* chart */
#pieChart {
height: 800px;
margin: 0 auto;
position: relative;
display: block;
width: 1200px;
}
/* tooltip */
.tooltip {
background: #eee;
box-shadow: 0 0 5px #999999;
color: #333;
display: none;
font-size: 18px;
left: 130px;
padding: 10px;
position: absolute;
text-align: center;
top: 95px;
width: 80px;
z-index: 10;
}
.footer {
padding-top: 50px;
text-align: center;
list-style-type: none;
}
</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="title-holder">
<h1 class="title">Language Use in India</h1>
<p class="subtitle">Calculated in the Millions</p>
<p class="font">Uncheck labels to recalculate.</p>
</div>
<div class="card-body">
<div id="pieChart">
</div>
</div>
<footer>
<ul class="footer">
<li><a href="http://www.censusindia.gov.in/Census_Data_2001/Census_Data_Online/Language/Statement5.aspx"
target="_blank">Data Source</a></li>
<li><a href="www.lisaofalltrades.com" target="_blank">lisaofalltrades.com</a></li>
</ul>
</footer>
</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/script.js"></script>
</body>
</html>
I've researched on how to use the d3.schemeCategorry20c
it seems there is no problem in the way I used it. What could be the problem?
Upvotes: 0
Views: 907
Reputation: 740
Change var color = d3.scaleOrdinal(d3.schemeCategory20c);
to var color = d3.scaleOrdinal(d3.schemeCategory10);
and error should be gone for you
There is no more schemeCategory20c in d3.v5
Upvotes: 2