I have to draw a set of rect that represent the range of a day in the month.
svg.selectAll(".month")
.data(function() { return getMonths(year); })
.enter().append("path")
.attr("class", "month")
.attr("d", monthPath);
My function is:
function getMonths(year){
var months = d3.time.months(new Date(year, 0, 1), new Date(year + 1, 0, 1));
return months;
}
This function is called for a set of year like [2003,2004,2005 and so on..]
If I call my function for a set of year it doesn't work, instead if I call this function in this way for all years:
function getMonths(year){
var months = d3.time.months(new Date(2012, 0, 1), new Date(2012 + 1, 0, 1));
return months;
}
it works.
Why I have this problem?
Thanks.
Related
been stuck on this all morning. I've been following this example
I've been trying to get this to work in React but sadly no luck. I was able to read the csv in before and console log the data so I know it's finding the right file. What am I missing here?
class Linegraph extends Component {
componentDidMount() {
var parseDate = d3.timeParse("%m/%d/%Y");
var margin = { left: 50, right: 20, top: 20, bottom: 50 };
var width = 960 - margin.left - margin.right;
var height = 500 - margin.top - margin.bottom;
var max = 0;
var xNudge = 50;
var yNudge = 20;
var minDate = new Date();
var maxDate = new Date();
d3.csv("MOCK_DATA.csv")
.row(function(d) {
return {
month: parseDate(d.month),
price: Number(d.price.trim().slice(1))
};
})
.get(function(error, rows) {
max = d3.max(rows, function(d) {
return d.price;
});
minDate = d3.min(rows, function(d) {
return d.month;
});
maxDate = d3.max(rows, function(d) {
return d.month;
});
.................
(note: this question is not a duplicate of the existing Q/A about the new d3.fetch module because it uses a row function, not covered on those Q/A)
Since you are using D3 v5, you have to change the XmlHttpRequest pattern of v4 to the new Promises pattern of v5 (see the documentation here).
So, your code should be:
d3.csv("MOCK_DATA.csv", function(d) {
return {
month: parseDate(d.month),
price: Number(d.price.trim().slice(1))
};
})
.then(function(rows) {
//etc...
});
Pay attention to the fact that the row function goes inside the d3.csv function, as the second argument.
I have to create a chart by our website visitor numbers (preferably similar to those of Analytics by Google).
I got a text file filled with the time of visits in milliseconds like this:
[1505385301633, 0][1505219341916, 0][1504999958757,
0][1504854145481, 0][1504601608015, 0][1504385667271,
0][1504380372409, 0][1504112805811, 0][1503866251230,
0][1503865512105, 0]...
This is what I got so far working with Google Charts:
https://jsfiddle.net/2djpec3s/
Controls: drag to zoom, right-click to reset
<head>
<script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
<script type="text/javascript">
google.charts.load('current', {'packages':['corechart'], 'language':'de'});
google.charts.setOnLoadCallback(drawChart);
// not in use yet
/* var date = new Date(1507130849370);
date = msToDate(date);
function msToDate(date) // milliseconds to year, month, day
{
var year = date.getFullYear();
var month = date.getMonth();
var date = date.getDate(); // day
return new Date(year, month, date);
} */
function drawChart() {
var data = google.visualization.arrayToDataTable([
['Date', 'Visitors'],
[new Date(1507130849370), 1],
[new Date(1507149651188), 1],
[new Date(1507191655367), 1],
[new Date(1507212560124), 1],
[new Date(1507231742263), 1],
[new Date(1507305748865), 1],
[new Date(1507455848163), 1],
[new Date(1507612393800), 1],
[new Date(1507825666582), 1],
[new Date(1507881840738), 1],
[new Date(1507921803759), 1],
[new Date(1508001467740), 1]
]);
var options = {
title: 'Statistics',
explorer: {
actions: [
'dragToZoom',
'rightClickToReset'
],
maxZoomIn: 0.001
},
hAxis: {
gridlines: {
units: {
years: {format: ['y']},
months: {format: ['MMMM']},
days: {format: ['E, d. MMM']},
hours: {format: ["HH:mm 'Uhr'"]},
minutes: {format: ["HH:mm 'Uhr'"]}
}
},
minorGridlines: {
units: {
days: {format: ['d. MMM']},
hours: {format: ["H 'Uhr'"]},
minutes: {format: ['HH:mm']}
}
}
},
legend: { position: 'bottom' }
};
var chart = new google.visualization.LineChart(document.getElementById('curve_chart'));
chart.draw(data, options);
}
</script>
</head>
<body>
<div id="curve_chart" style="width: 900px; height: 500px"></div>
</body>
The problem is I just can't figure out, if or how the data can be joined/stacked in an specific zoom level.
An alternative way I'd like to avoid is to create up to 4 charts for year, month, day and hour and let them visually be swappable by using a selection box.
One way you can do this is to have your zoom level be how many datapoints you want to show per pixel. The following examples uses the average in the sample range but you could take peak value or whatever works for your application.
This scales well to huge arrays as the number of data points you have is always equal to width and maximum complexity is width * resolution. If you always want to take all the datapoints just set resolution to a high number (or leave it out)
function getSampledData(data, zoomLevel, scrollPosition, width, resolution) {
const sampledData = [];
const skip = Math.max(1, zoomLevel / resolution);
// iterate over each pixel of chart width
for(let i = 0; i < width; i++) {
let total = 0;
// scrollPosition is the start pixel position of virtual scroll
let startPoint = (i * zoomLevel) + (scrollPosition * zoomLevel);
// zoom level is how many data points you want to show per pixel
for(let j = startPoint; j < startPoint + zoomLevel && j < data.length; j += skip) {
total += data[j];
}
sampledData.push(total / resolution);
}
return sampledData;
}
I need help with Flipclock.js I have no knowledge of Jquery and this plugin is driving me nuts. I just need to change the date to 11/23/2014 at 6pm but I can not seem to able to figure that out.
Here is my code
var clock;
$(document).ready(function() {
// Grab the current date
var currentDate = new Date();
// Set some date in the future. In this case, it's always Jan 1
var futureDate = new Date(currentDate.getFullYear() + 1, 0, 1);
// Calculate the difference in seconds between the future and current date
var diff = futureDate.getTime() / 1000 - currentDate.getTime() / 1000;
// Instantiate a coutdown FlipClock
clock = $('.clock').FlipClock(diff, {
clockFace: 'DailyCounter',
countdown: true
});
});
Where you are setting 'futureDate' instead of adding 1 year set the finish time using:
new Date(year, month, day, hour, minute, second, millisecond);
mdn documentation for date
var clock;
$(document).ready(function() {
// Grab the current date
var currentDate = new Date();
// Set some date in the future. ***change to desired date***
//var futureDate = new Date(2014, 11, 23, 6, 0, 0);
var futureDate = new Date(2014, 10, 23, 18, 0, 0); //fixed as per comments
// Calculate the difference in seconds between the future and current date
var diff = futureDate.getTime() / 1000 - currentDate.getTime() / 1000;
// Instantiate a coutdown FlipClock
clock = $('.clock').FlipClock(diff, { clockFace: 'DailyCounter', countdown: true });
});
I'm working with Nvd3 charts from the examples from their official website. Now I want a line chart to update periodically based on data sent from server but I couldn't found any useful Example for this on internet.
I have created a function which re-draws the chart when new data is arrived but i want to append every new point to the existing chart (like we can do in highcharts) but i'm stuck.
Here is the code I'm using for Updating the chart.
var data = [{
"key" : "Long",
"values" : getData()
}];
var chart;
function redraw() {
nv.addGraph(function() {
var chart = nv.models.lineChart().margin({
left : 100
})
//Adjust chart margins to give the x-axis some breathing room.
.useInteractiveGuideline(true) //We want nice looking tooltips and a guideline!
.transitionDuration(350) //how fast do you want the lines to transition?
.showLegend(true) //Show the legend, allowing users to turn on/off line series.
.showYAxis(true) //Show the y-axis
.showXAxis(true);
//Show the x-axis
chart.xAxis.tickFormat(function(d) {
return d3.time.format('%x')(new Date(d))
});
chart.yAxis.tickFormat(d3.format(',.1%'));
d3.select('#chart svg').datum(data)
//.transition().duration(500)
.call(chart);
nv.utils.windowResize(chart.update);
return chart;
});
}
function getData() {
var arr = [];
var theDate = new Date(2012, 01, 01, 0, 0, 0, 0);
for (var x = 0; x < 30; x++) {
arr.push({
x : new Date(theDate.getTime()),
y : Math.random() * 100
});
theDate.setDate(theDate.getDate() + 1);
}
return arr;
}
setInterval(function() {
var long = data[0].values;
var next = new Date(long[long.length - 1].x);
next.setDate(next.getDate() + 1)
long.shift();
long.push({
x : next.getTime(),
y : Math.random() * 100
});
redraw();
}, 1500);
I am attempting to map an array index to a time range in d3.js as I do not have individual dates for the array - I just know the values are between 1900 and 2000.
var data = [45,678,490...]; // length 820
var x = d3.time.scale().range([0, width]).domain([new Date(1900, 0, 0), new Date(2000, 0, 0)]);
// line function
var line = d3.svg.line()
.x(function(d,i) {
// here map i to date between domain min / max
return x(i);
})
.y(function(d) {
return y(d);
});
Is there a smarter way of doing this than manually calculating a date for each array value? Perhaps calculating the step and incrementing?
Use another scale to map from the index value to date:
var arrayScale = d3.time.scale()
.domain([0, data.length])
.range([new Date(1900, 0, 0), new Date(2000, 0, 0)]);