xxxxxxxxxx
<meta charset="utf-8">
<script src="https://d3js.org/d3.v4.min.js"></script>
<style type="text/css">
.axis line {
stroke-width:1px;
stroke: #ccc;
stroke-dasharray: 2px 2px;
}
.axis text {
font-size: 12px;
fill: #777;
}
.axis path {
display: none;
}
.circle-group text {
fill: #aaa; /*grey out text*/
font-size: 11px;
}
/* *2* style line */
.ufoLine {
/*removes black fill*/
fill: none;
/*styles line */
stroke-width: 1.5;
stroke: darkgray;
stroke-width: 3 ;
}
/*NEW CSS GOES HERE*/
</style>
<body>
<div id='titleDiv'></div>
<div id="buttonsDiv"></div>
</body>
<script>
//NOW LET'S ADD A LINE
// *1* create line for original data
// *2* style line to remove all that black
// *3* update line in dataSwap function
// define dataSwap function
function dataSwap(datasetGroup) {
// filter data to get new data subset based on year
var thisDataGroup = data.filter(function(d) { return d.year == datasetGroup});
// define scale domains using new data, pass newly defined scales into axes, call axes for each axis group
xScale
.domain(d3.extent(thisDataGroup, function(d) { return d.date; }));
yScale
.domain(d3.extent(thisDataGroup, function(d) { return d.count; }));
xAxis.scale(xScale);
yAxis.scale(yScale);
xAxisGroup
.call(xAxis);
yAxisGroup
.transition()
.duration(transitionTime)
.call(yAxis);
// *3* update line in dataSwap function
svg.selectAll('.ufoLine')
.transition()
.ease(d3.easeElastic) //if you use the same ease here as you do with the circles, the line and circles will move together.
.duration(transitionTime)
.attr('d', lineGenerator(thisDataGroup));
// move locations of each ufo group (each of which contain a circle and text)
svg.selectAll('.ufoGroup')
.data(thisDataGroup)
.transition()
.ease(d3.easeElastic)
.duration(transitionTime)
.attr('transform', function(d) { return 'translate(' + xScale(d.date) + ',' + yScale(d.count) + ')'})
// update title
d3.select('#titleText')
.text('UFO Sightings in ' + datasetGroup);
}
// define variables, including svg, margins, etc.
var radius = 10;
var parseTime = d3.timeParse("%m/%Y");
var transitionTime = 1000
var margin = {top: 50, right: 10, bottom: 20, left: 40};
var width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
var svg = d3.select("body").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 + ")");
// Add a title. This could alternatively be done above in the html section
d3.select('#titleDiv')
.append('h1')
.attr('id', 'titleText')
.text('UFO Sightings in 2018')
// define xScale and yScale; will define domain later within ready function
var xScale = d3.scaleTime()
.range([0, width]);
var yScale = d3.scaleLinear()
.range([height, 0])
// Define xAxis and yAxis, will define associated scales inside ready function
var xAxis = d3.axisBottom()
.tickSize(-height);
var yAxis = d3.axisLeft()
.tickSize(-width);
// Define xAxisGroup and yAxisGroup. Will call the appropriate axis within ready function
var xAxisGroup = svg.append("g")
.attr("class", "x axis") //gives group the classes `x` and `axis`
.attr("transform", "translate(0," + height + ")");
var yAxisGroup = svg.append("g")
.attr("class", "y axis"); //gives group the classes `y` and `axis`
// *1* create line for original data
var lineGenerator = d3.line()
.curve(d3.curveCardinal); //makes line 'curvy'
// transforming data into json
d3.csv("ufo.csv", ready)
function ready(error, data) {
if (error) return console.warn(error);
window.data = data;
// format data
data.forEach(function(d) {
d.count = +d.count;
d.month = d.date.split('/')[0];
d.date = parseTime(d.date);
d.year = d.date.getYear() + 1900
});
// filter to define startData
var startData = data.filter(function(d) { return d.year == 2018; })
// define domain of scales, pass newly defined scales into axes, call axes for each axis group
xScale.domain(d3.extent(startData, function(d) { return d.date; }));
yScale.domain(d3.extent(startData, function(d) { return d.count; }));
xAxis.scale(xScale)
yAxis.scale(yScale)
xAxisGroup.call(xAxis);
yAxisGroup.call(yAxis);
// create buttons
var yearList = d3.set(data.map(function(d) { return d.year })).values();
d3.select('#buttonsDiv')
.selectAll('button')
.data(yearList)
.enter().append('button')
.text(function(d) { return d; })
.on('click', function(d) {
dataSwap(d)
})
// *1* Create line
lineGenerator
.x(function(d) { return xScale(d.date)})
.y(function(d) { return yScale(d.count)})
svg.append('path')
.attr('class', 'ufoLine')
.attr('d', lineGenerator(startData));
// create ufo Groups
var ufoGroup = svg.selectAll('.ufoGroup')
.data(startData).enter().append('g')
.attr('class', 'ufoGroup')
.attr('transform', function(d) { return 'translate(' + xScale(d.date) + ',' + yScale(d.count) + ')'})
.on('mouseenter', function(d) {
// define hover events
d3.select(this)
.select('text')
.transition()
.duration(0)
.style('opacity', 1)
d3.selectAll('circle')
.style('opacity', 0.5)
d3.select(this)
.select('circle')
.transition()
.ease(d3.easeElastic)
.duration(transitionTime)
.attr('r', radius*2)
.style('opacity', 1)
})
.on('mouseleave', function(d) {
// define mouseleave events
d3.select(this)
.select('text')
.transition()
.style('opacity', 0)
d3.select(this)
.select('circle')
.transition()
.ease(d3.easeElastic)
.duration(transitionTime)
.attr('r', radius)
d3.selectAll('circle')
.style('opacity', 1)
})
// append circles to ufo groups
ufoGroup.append('circle')
.attr('class', 'ufoCircle')
.style('fill', 'limegreen')
.attr('r', radius)
// append text to ufo groups
ufoGroup.append('text')
.attr('class', 'ufoText')
.attr('dx', radius)
.attr('dy', -radius)
.text(function(d) { return d.count})
.style('opacity', 0)
};
</script>
https://d3js.org/d3.v4.min.js