Integrated Calendar View and Day Hour Heat Map in one chart.
Last active
September 13, 2019 10:13
-
-
Save arpitnarechania/e88897848232986b1164ae47e7d97150 to your computer and use it in GitHub Desktop.
Calendar View + Day Hour Heat Map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| scrolling:yes |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| .d3-tip { | |
| line-height: 1; | |
| font-weight: bold; | |
| padding: 12px; | |
| background: rgba(0, 0, 0, 0.8); | |
| color: #fff; | |
| border-radius: 2px; | |
| } | |
| /* Creates a small triangle extender for the tooltip */ | |
| .d3-tip:after { | |
| box-sizing: border-box; | |
| display: inline; | |
| font-size: 10px; | |
| width: 100%; | |
| line-height: 1; | |
| color: rgba(0, 0, 0, 0.8); | |
| content: "\25BC"; | |
| position: absolute; | |
| text-align: center; | |
| } | |
| /* Style northward tooltips differently */ | |
| .d3-tip.n:after { | |
| margin: -1px 0 0 0; | |
| top: 100%; | |
| left: 0; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <title>Calendar Heatmap</title> | |
| <!-- JavaScript Libraries //--> | |
| <script src="http://d3js.org/d3.v3.min.js"></script> | |
| <!-- CSS Style //--> | |
| <link href="style.css" rel="stylesheet" type="text/css"> | |
| <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.7.1/d3-tip.min.js"></script> | |
| <link href="d3-tip.css" rel="stylesheet" type="text/css"> | |
| <script type="text/javascript" src="main.js"></script> | |
| </head> | |
| <body> | |
| <div id="calendarView"></div> | |
| <div id="dayHourChart"></div> | |
| </body> | |
| <script> | |
| var defaultColorScheme = ["#E57373","#BA68C8","#7986CB","#A1887F","#90A4AE","#AED581","#9575CD","#FF8A65","#4DB6AC","#FFF176","#64B5F6","#00E676"]; | |
| var colorSchemeNeutralDayHourMap = ["white","#b3e5fc","#81d4fa","#4fc3f7","#29b6f6","#03a9f4","#039be5","#0288d1","#0277bd","#01579b"]; | |
| var dataset = []; | |
| dataset.push({month:1 , year: 2017, day_segment_id: 1, month_segment_id: 1,weekday_id: 1,amount:132, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 2, month_segment_id: 1,weekday_id: 2,amount:21, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 3, month_segment_id: 1,weekday_id: 3,amount:142, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 4, month_segment_id: 1,weekday_id: 4,amount:122, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 5, month_segment_id: 1,weekday_id: 5,amount:242, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 6, month_segment_id: 2,weekday_id: 1,amount:12, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 1, month_segment_id: 2,weekday_id: 2,amount:322, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 2, month_segment_id: 2,weekday_id: 3,amount:143, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 3, month_segment_id: 2,weekday_id: 4,amount:165, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 4, month_segment_id: 2,weekday_id: 5,amount:142, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 5, month_segment_id: 3,weekday_id: 1,amount:112, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 6, month_segment_id: 3,weekday_id: 2,amount:54, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 1, month_segment_id: 3,weekday_id: 3,amount:242, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 2, month_segment_id: 3,weekday_id: 4,amount:41, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 3, month_segment_id: 3,weekday_id: 5,amount:232, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 4, month_segment_id: 4,weekday_id: 1,amount:18, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 5, month_segment_id: 4,weekday_id: 2,amount:85, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 6, month_segment_id: 4,weekday_id: 3,amount:194, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 1, month_segment_id: 4,weekday_id: 4,amount:23, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| dataset.push({month:1 , year: 2017, day_segment_id: 2, month_segment_id: 4,weekday_id: 5,amount:13, meta_numsegs_month:4,meta_numsegs_day: 24}); | |
| var dom_elements = [{data:dataset,primary:"#calendarView",secondary:"#dayHourChart",categoryName:"amount",isForwarUnit:true,unitName:"rs",colorSchemeDayHourMap:colorSchemeNeutralDayHourMap,colorScheme:[colorSchemeNeutralDayHourMap[0],colorSchemeNeutralDayHourMap[colorSchemeNeutralDayHourMap.length - 1]]}]; | |
| var timeTicksInDay = ["12:30am","1:30am","2:30am","3:30am","4:30am","5:30am","6:30am","7:30am","8:30am","9:30am","10:30am","11:30am","12:30pm","1:30pm","2:30pm","3:30pm","4:30pm","5:30pm","6:30pm","7:30pm","8:30pm","9:30pm","10:30pm","11:30pm"]; | |
| var monthsFullName = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']; | |
| calendarViewHeatMap (dom_elements, 2017, 0, timeTicksInDay, monthsFullName); | |
| </script> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* Function : loadDayHourHeatmap | |
| * called from loadDayHourHeatGraph, all the params are passed from the parent function taken from the 'dom_elements' array of object | |
| * with the corresponding index of object according to which the graph has to be plotted, | |
| * css of the graph is included int the 'css/calendarView.css ' | |
| */ | |
| function loadDayHourHeatmap (dom_elements,inputData, totalDaysInMonth, index, month, | |
| cellSize, defaultWidth, timeTicksInDay,containsDataFlag, monthsFullName){ | |
| var dom_element_to_append_to = dom_elements[index].secondary; | |
| var colorScheme = dom_elements[index].colorSchemeDayHourMap; | |
| var margin = { top: 50, right: 0, bottom: 150, left: 120 }, | |
| width = defaultWidth, //$(dom_element_to_append_to).parent().width() - margin.left - margin.right, | |
| gridSize = Math.floor(width / 40), | |
| height = (gridSize * 24) + margin.top + margin.bottom - 170, | |
| legendElementWidth = gridSize*2.5, | |
| padding = 150, | |
| buckets = 9, | |
| colors = colorScheme, | |
| yAxis = [], | |
| xAxis = timeTicksInDay; | |
| for(var i=1; i<=totalDaysInMonth; ++i) | |
| yAxis.push(i.toString()); | |
| if(!containsDataFlag) | |
| colors = ["white", "white"]; | |
| var svg = d3.select(dom_element_to_append_to).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 dayLabels = svg.selectAll(".dayLabel") | |
| .data(xAxis) | |
| .enter().append("text") | |
| .text(function (d) { return d; }) | |
| .attr("x", 0) | |
| .attr("y", function (d, i) { return i * gridSize; }) | |
| .style("text-anchor", "end") | |
| .attr("transform", "translate(-6," + gridSize / 1.5 + ")") | |
| .attr("class", function (d, i) { return ((i >= 0 && i <= 4) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); }); | |
| var timeLabels = svg.selectAll(".timeLabel") | |
| .data(yAxis) | |
| .enter().append("text") | |
| .text(function(d) { return d; }) | |
| .attr("x", function(d, i) { return i * gridSize; }) | |
| .attr("y", 0) | |
| .style("text-anchor", "middle") | |
| .attr("transform", "translate(" + gridSize / 2 + ", -6)") | |
| .attr("class", function(d, i) { return ((i >= 7 && i <= 16) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); }); | |
| var tip = d3.tip() | |
| .attr('class', 'd3-tip') | |
| .offset([-10, 0]) | |
| .html(function(d) { | |
| if(dom_elements[index]['isForwardUnit']) | |
| return "<div><span>Day:</span> <span style='color:white'>" + d.day + " <span>Hour:</span> <span style='color:white'>" + d.hour + "</span></div>" + | |
| "<div><span>Value:</span> <span style='color:white'><span>" + dom_elements[index]['unitName'] + "</span>" + d3.format(",")(d.value) + "</span></div>"; | |
| else | |
| return "<div><span>Day:</span> <span style='color:white'>" + d.day + " <span>Hour:</span> <span style='color:white'>" + d.hour + "</span></div>" + | |
| "<div><span>Value:</span> <span style='color:white'>" + d3.format(",")(d.value) + "<span> " + dom_elements[index]['unitName'] + "</span>" + "</span></div>"; | |
| }) | |
| svg.call(tip); | |
| svg.append("text") | |
| .attr("transform", | |
| "translate(" + (width/3) + " ," + | |
| (0-margin.top/2) + ")") | |
| .style("text-anchor", "middle") | |
| .style("font-size", gridSize) | |
| .text(monthsFullName[month-1]); | |
| svg.append("text") | |
| .attr("transform", "rotate(-90)") | |
| .attr("y", 0 - 90) | |
| .attr("x",0 - (height / 2)) | |
| .attr("dy", "1em") | |
| .style("text-anchor", "middle") | |
| .style("font-size", gridSize) | |
| .text("Time of Day"); | |
| var heatmapChart = function(data) { | |
| var colorScale = d3.scale.quantile() | |
| .domain([0, buckets - 1, d3.max(data, function (d) { return d.value; })]) | |
| .range(colors); | |
| var cards = svg.selectAll(".hour") | |
| .data(data, function(d) {return d.day+':'+d.hour;}); | |
| cards.append("title"); | |
| cards.enter().append("rect") | |
| .attr("y", 0) | |
| .attr("x", 0) | |
| .attr("height", gridSize * 24) | |
| .attr("width", gridSize * totalDaysInMonth) | |
| .attr("class", "border") | |
| .style("stroke","#000") | |
| .style("stroke-width", "4.5px") | |
| .style("z-index", -10); | |
| cards.enter().append("rect") | |
| .attr("y", function(d) { return (d.hour - 1) * gridSize; }) | |
| .attr("x", function(d) { return (d.day - 1) * gridSize; }) | |
| .attr("class", "hour ") | |
| .attr("width", gridSize) | |
| .attr("height", gridSize) | |
| .style("fill", colors[0]) | |
| .style("stroke", "#000") | |
| .style("stroke-width", "1px") | |
| .on('mouseover', tip.show) | |
| .on('mouseout', tip.hide); | |
| cards.transition().duration(1000) | |
| .style("fill", function(d) { return colorScale(d.value); }); | |
| cards.select("title").text(function(d) { return d.value; }); | |
| cards.exit().remove(); | |
| var legend = svg.selectAll(".legend") | |
| .data([0].concat(colorScale.quantiles()), function(d) { return d; }); | |
| legend.enter().append("g") | |
| .attr("class", "legend"); | |
| legend.append("rect") | |
| .attr("x", function(d, i) { return legendElementWidth * i; }) | |
| .attr("y", height + 30) | |
| .attr("width", legendElementWidth) | |
| .attr("height", gridSize / 2) | |
| .style("fill", function(d, i) { return colors[i]; }); | |
| legend.append("text") | |
| .attr("class", "mono") | |
| .text(function(d) { return "≥ " + Math.round(d); }) | |
| .attr("x", function(d, i) { return legendElementWidth * i; }) | |
| .attr("y", height + gridSize*1.3); | |
| legend.exit().remove(); | |
| }; | |
| heatmapChart(inputData); | |
| }; | |
| /* Function : loadDayHourHeatGraph | |
| * Variables : | |
| * * year and month:- year and month selected by the user for the calendarView graph | |
| * * val :- index position of the objects placed in the 'dom_elements' which is currently used for plotting the graph | |
| * * containsDataFlag :- variable is used as a flag, set it 'true' when there is no data in the object passed, | |
| * Description : | |
| * Internally called by loadMonthWeekHeatMap function when a particular month path is clicked, to plot heatMap corresponding to data related to month | |
| */ | |
| function loadDayHourHeatGraph (dom_elements, year, month, val, cellSize, defaultWidth, timeTicksInDay, monthsFullName) { | |
| $(dom_elements[val].secondary).empty(); | |
| var totalDays = parseInt(new Date(year, month, 0).getDate()); | |
| var obj = {containsDataFlag: false}; | |
| var convertedDataMonthly = convertDataMonthly(dom_elements[val].data,month,year, | |
| dom_elements[val]['data'][0]['meta_numsegs_month'], dom_elements[val]['data'][0]['meta_numsegs_day'], | |
| totalDays , dom_elements[val].categoryName,obj, true); | |
| var containsDataFlag = obj.containsDataFlag; | |
| loadDayHourHeatmap(dom_elements, convertedDataMonthly,totalDays, val, month, cellSize, defaultWidth, timeTicksInDay, containsDataFlag, monthsFullName); | |
| }; | |
| /* Function : convertDataYearly | |
| * Expected Input: Array of objects with properties of whole year selected by user {month: , year: , day_segment_id: , month_segment_id: ,weekday_id: ,categoryName: } | |
| * Variables passed | |
| * * inputData: contains array of objects as shown above, | |
| * * valueCategoryName: it is the name of the object property which is plotted on the graph | |
| * * convertedDataYearly : it is an array which contains the output of the function | |
| * Expected Output : Array of objects with properties like { date: , value: }. | |
| * This function is only used for converting data passed from user to format accepted by the loadDayHourHeatMap function and loadMonthWeekHeatMap Function | |
| */ | |
| function convertDataYearly (inputData, valueCategoryName, year, monthSegments, daySegments) { | |
| var convertedDataYearly = []; | |
| var convertedDataMonthly = []; | |
| //var year = $rootScope.queryYearSelected['name']; | |
| var totalDays; | |
| if((year%4==0 && year%100!=0) || year%400==0) | |
| totalDays = 366; | |
| else totalDays = 365; | |
| var date; | |
| for(var i=1; i<=totalDays; ++i) { | |
| date = new Date(year,0); | |
| date = new Date(date.setDate(i)); | |
| var day = date.getDate(); | |
| var month = date.getMonth() + 1; | |
| if (month< 10) month = '0' + month; | |
| if (day < 10) day = '0' + day; | |
| date = year + "" + month + "" + day; | |
| date = parseInt(date); | |
| convertedDataYearly.push({Date: date, value: 0}); | |
| } | |
| var count = -1; | |
| var extraVariable = {containsDataFlag:false}; //Not required in calendar View Graph | |
| for(var i=1; i<=12; ++i) { | |
| var totalDaysInMonth = parseInt(new Date(year, i, 0).getDate()); | |
| convertedDataMonthly = convertDataMonthly(inputData, i,year, monthSegments, daySegments,totalDaysInMonth , valueCategoryName , extraVariable, false); | |
| for(var j=0; j<totalDaysInMonth; ++j) { | |
| ++count; | |
| var total = 0; | |
| for(var k=j*24;k<j*24+24 ;++k) | |
| total += convertedDataMonthly[k]['value']; | |
| //here 4 is daySegments change it if you change number of day segments | |
| convertedDataYearly[count]['value'] = total; | |
| } | |
| } | |
| return convertedDataYearly; | |
| }; | |
| /* Function : convertDataMonthly | |
| * Expected Input: Array of objects such as {month: , year: , day_segment_id: , month_segment_id: ,weekday_id: ,valueCategoryName: } | |
| * Variables passed | |
| * * inputData: contains array of objects as shown above, | |
| * * valueCategoryName: it is the name of the object property which is plotted on the graph | |
| * * convertedData : it is variable which contains the output of the function | |
| * Expected Output : Array of objects with properties like { day: , hour: , value }. | |
| * This function is only used for converting data passed from user to format accepted by the loadDayHourHeatMap function and loadMonthWeekHeatMap Function | |
| * Computation of tempData should be done only to render the dayHourHeatMap, It is necessary over there that's why | |
| * set the flag to true when rendering dayHourHeatMap in the function loaddayhourHeatMap and set it false everywhere like | |
| * in the convertDataYearly function | |
| */ | |
| function convertDataMonthly (inputData, month, year, monthSegments, daySegments, totalDaysInMonth, valueCategoryName,obj, flag) { | |
| var convertedDataMonthly = []; | |
| var tempData = []; | |
| var currentDay = 0; | |
| var currentHour = 0; | |
| var daysInSegment = totalDaysInMonth / monthSegments; | |
| daysInSegment = Math.floor(daysInSegment); | |
| var hoursInSegment = 24 / daySegments ; | |
| hoursInSegment = Math.floor(hoursInSegment); | |
| var date = new Date(); | |
| var firstDay = new Date(date.getFullYear(), date.getMonth(), 1); | |
| var startHourUTC = (new Date(firstDay)).getUTCHours() ; | |
| for(var i=1; i<=totalDaysInMonth; ++i) { | |
| for(var j =1; j<=24; ++j) { | |
| convertedDataMonthly.push({day:i, hour: j, value: 0}); | |
| } | |
| } | |
| for(var i=0 ; i<inputData.length; ++i) { | |
| if(inputData[i]['year']!=year) | |
| continue; | |
| if(inputData[i]['month']!=month) | |
| continue; | |
| currentDay = (inputData[i]['month_segment_id'] - 1 ) * daysInSegment + inputData[i]['weekday_id']; | |
| currentHour = (inputData[i]['day_segment_id'] - 1 ) * hoursInSegment ; | |
| for(var j = currentHour ; j< currentHour + hoursInSegment; ++j ) { | |
| convertedDataMonthly[(currentDay - 1 )*24 + j]['value'] = inputData[i][valueCategoryName]/hoursInSegment; | |
| if(inputData[i][valueCategoryName]) | |
| obj.containsDataFlag = true; | |
| } | |
| } | |
| if(flag) { | |
| var count = 1; | |
| for(var i = 0; i<totalDaysInMonth; ++i) { | |
| count = 1; | |
| for(var j = startHourUTC+1; j<24; ++j,++count ) | |
| tempData.push({day: i+1, hour: count, value: convertedDataMonthly[i*24 + j]['value']}); | |
| for(var j = 0; j<=startHourUTC; ++j,++count) | |
| tempData.push({day: i+1, hour: count, value: convertedDataMonthly[i*24 + j]['value']}); | |
| } | |
| return tempData; | |
| } | |
| return convertedDataMonthly; | |
| }; | |
| /* Function: calendarViewHeatMap | |
| * Variable: | |
| * * year: selected year by the user | |
| * * varID: index position of the current object of 'dom_elements' variable | |
| * * dom_elements: | |
| * contains several objects, only single object is used at a time to plot a graph, use a loop at | |
| * the time of calling the function to plot several functions in a single page like the cashflow-rollup section | |
| * pass only single object if you want to plot a single graph in a page like the call section | |
| * object should contains the following properties:- | |
| * * primary: dom_element(string) of the calendarView Heatmap | |
| * * secondary: dom_element(string) of the dayHourHeatmap graph | |
| * * data: JSON data passed from user | |
| * it contains several objects in the format {month: , year: , day_segment_id: , month_segment_id: ,weekday_id: ,categoryName: } | |
| * * categoryName: name of the property of variable data according to which the graph has to be plotted | |
| * * isForwarUnit: set it 'true' if passed unit is to be placed at the forward of the vaule else false if to be placed at the backwards , else if no value passed then it can be set either true or false | |
| * * unitName: name of the unit to be placed in the graph, set it "" if no unit is required | |
| * * colorSchemeDayHourMap: color scheme of dayHourHeatMap plot | |
| * * colorScheme: color scheme of calendar view heatMap | |
| * * load the css file 'css/calendarView.css' at the top of html page where the graph has to be appended | |
| * | |
| */ | |
| function calendarViewHeatMap (dom_elements, year, varID, timeTicksInDay, monthsFullName) { | |
| if(dom_elements[varID]['data'].length == 0) { | |
| dom_elements[varID]['data'].push({year: year, month_segment_id : 4, weekday_id: 2, day_segment_id:2,meta_numsegs_month:4,meta_numsegs_day: 24, amount : 0}); | |
| dom_elements[varID]['categoryName'] = 'amount'; | |
| } | |
| var dom_element = dom_elements[varID]; | |
| var valueCategoryName = dom_element.categoryName; | |
| var dom_element_to_append_to = dom_element.primary; | |
| var inputData = convertDataYearly(dom_element.data,valueCategoryName, year,dom_elements[varID]['data'][0]['meta_numsegs_month'], dom_elements[varID]['data'][0]['meta_numsegs_day']); | |
| var margin = { top: 20, right: 60, bottom: 20, left: 120 }, | |
| width = 900 - margin.left - margin.right, | |
| cellSize = Math.floor(width/52), | |
| height = cellSize * 7 + margin.top + margin.bottom , | |
| week_days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'], | |
| month = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; | |
| var defaultWidth = width; | |
| var defaultCellSize = cellSize; | |
| var day = d3.time.format("%w"), | |
| week = d3.time.format("%U"), | |
| percent = d3.format(".1%"), | |
| format = d3.time.format("%Y%m%d"), | |
| parseDate = d3.time.format("%Y%m%d").parse; | |
| var color = d3.scale.linear().range(dom_element.colorScheme) | |
| .domain([0, 1]); | |
| var svg = d3.select(dom_element_to_append_to).selectAll("svg") | |
| .data(d3.range(year, year+1)) | |
| .enter().append("svg") | |
| .attr("width", width + margin.left + margin.right) | |
| .attr("height", height) | |
| .attr("data-height", '0.5678') | |
| .attr("class", "RdYlGn") | |
| .append("g") | |
| .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); | |
| svg.append("text") | |
| .attr("transform", "translate(-38," + cellSize * 3.5 + ")rotate(-90)") | |
| .style("text-anchor", "middle") | |
| .style("font-size",cellSize*1.2) | |
| .text(function(d) { return d; }); | |
| for (var i=0; i<7; i++) | |
| { | |
| svg.append("text") | |
| .attr("transform", "translate(-5," + cellSize*(i+1) + ")") | |
| .style("text-anchor", "end") | |
| .attr("dy", "-.25em") | |
| .text(function(d) { return week_days[i]; }); | |
| } | |
| var rect = svg.selectAll(".day") | |
| .data(function(d) { return d3.time.days(new Date(d, 0, 1), new Date(d + 1, 0, 1)); }) | |
| .enter() | |
| .append("rect") | |
| .attr("class", "day") | |
| .attr("width", cellSize) | |
| .attr("height", cellSize) | |
| .attr("x", function(d) { return week(d) * cellSize; }) | |
| .attr("y", function(d) { return day(d) * cellSize; }) | |
| .attr("fill",'#fff') | |
| .datum(format); | |
| var legend = svg.selectAll(".legend") | |
| .data(month) | |
| .enter().append("g") | |
| .attr("class", "legend") | |
| .attr("transform", function(d, i) { return "translate(" + (((i+1) * cellSize*4.33)) + ",0)"; }); | |
| legend.append("text") | |
| .attr("class", function(d,i){ return month[i] }) | |
| .style("text-anchor", "end") | |
| .attr("dy", "-.25em") | |
| .style("font-size",cellSize*1.2) | |
| .text(function(d,i){ return month[i] }); | |
| svg.selectAll(".month") | |
| .data(function(d) { return d3.time.months(new Date(d, 0, 1), new Date(d + 1, 0, 1)); }) | |
| .enter().append("path") | |
| .attr("class", "month") | |
| .attr("id", function(d,i){ return month[i] + "" + varID }) | |
| .attr("d", monthPath); | |
| var Comparison_Type_Max = d3.max(inputData, function(d) { return d.value; }); | |
| Comparison_Type_Max = Comparison_Type_Max == 0 ? 1 : Comparison_Type_Max; | |
| dom_elements[varID].maxVal = Comparison_Type_Max; | |
| var data = d3.nest() | |
| .key(function(d) { return d.Date; }) | |
| .rollup(function(d) { return (d[0].value ); }) | |
| .map(inputData); | |
| var tip = d3.tip() | |
| .attr('class', 'd3-tip') | |
| .offset([-10, 0]) | |
| .html(function(d) { | |
| var year = d/10000; | |
| year = Math.floor(year); | |
| var month = d/100; | |
| month = Math.floor(month % 100); | |
| var day = d % 100; | |
| if(day<10) day = "0" + day; | |
| if(month < 10) month = "0" + month; | |
| if(dom_element['isForwardUnit']) | |
| return "<div><span>Date:</span> <span style='color:white'>" + day + "/" + month + "/" + year + "</span></div>" + | |
| "<div><span>Value:</span> <span style='color:white'><span>" + dom_element['unitName'] + "</span>" + d3.format(",")(data[d]) + "</span></div>"; | |
| else | |
| return "<div><span>Date:</span> <span style='color:white'>" + day + "/" + month + "/" + year + "</span></div>" + | |
| "<div><span>Value:</span> <span style='color:white'>" + d3.format(",")(data[d]) + "<span> " + dom_element['unitName'] + "</span>" + "</span></div>"; | |
| }); | |
| svg.call(tip); | |
| var currentPathId; | |
| rect.filter(function(d) { return d in data; }) | |
| .on("click", function(d){ | |
| var year = d/10000; | |
| year = Math.floor(year); | |
| var monthInt = d/100; | |
| var val = 0,id; | |
| for(var itr=0; itr<dom_elements.length; ++itr) { | |
| if(dom_element_to_append_to == dom_elements[itr].primary) { | |
| val = itr; | |
| break; | |
| } | |
| } | |
| monthInt = Math.floor(monthInt % 100); | |
| for (var itr = 0; itr<12; ++itr) { | |
| id = month[itr] + "" + varID; | |
| $('#' + id).css("z-index",0); | |
| $('#' + id).css("stroke","#000"); | |
| $('#' + id).css("stroke-width", "2.5px"); | |
| } | |
| id = month[monthInt-1] + "" + varID; | |
| currentPathId = id; | |
| $('#' + id).css("stroke","orange"); | |
| $('#' + id).css("position","relative"); | |
| $('#' + id).css("z-index",1000); | |
| $('#' + id).css("stroke-width", "4.5px"); | |
| loadDayHourHeatGraph(dom_elements, year, monthInt , val, defaultCellSize, defaultWidth, timeTicksInDay, monthsFullName); | |
| }) | |
| .attr("fill", function(d) { return color(Math.sqrt(data[d] / Comparison_Type_Max )); }) | |
| .on('mouseover', function(d) { | |
| tip.show(d); | |
| var year = d/10000; | |
| year = Math.floor(year); | |
| var monthInt = d/100; | |
| monthInt = Math.floor(monthInt % 100); | |
| var id = month[monthInt-1] + "" + varID; | |
| if(id!=currentPathId) { | |
| $('#' + id).css("stroke","orange"); | |
| $('#' + id).css("position","relative"); | |
| $('#' + id).css("z-index",-1000); | |
| $('#' + id).css("stroke-width", "4.5px"); | |
| } | |
| }) | |
| .on('mouseout', function(d) { | |
| tip.hide(d); | |
| var year = d/10000; | |
| year = Math.floor(year); | |
| var monthInt = d/100; | |
| monthInt = Math.floor(monthInt % 100); | |
| var id = month[monthInt-1] + "" + varID; | |
| if(id != currentPathId) { | |
| $('#' + id).css("z-index",-1000); | |
| $('#' + id).css("stroke","#000"); | |
| $('#' + id).css("stroke-width", "2.5px"); | |
| } | |
| }); | |
| function numberWithCommas(x) { | |
| x = x.toString(); | |
| var pattern = /(-?\d+)(\d{3})/; | |
| while (pattern.test(x)) | |
| x = x.replace(pattern, "$1,$2"); | |
| return x; | |
| } | |
| function monthPath(t0) { | |
| var t1 = new Date(t0.getFullYear(), t0.getMonth() + 1, 0), | |
| d0 = +day(t0), w0 = +week(t0), | |
| d1 = +day(t1), w1 = +week(t1); | |
| return "M" + (w0 + 1) * cellSize + "," + d0 * cellSize | |
| + "H" + w0 * cellSize + "V" + 7 * cellSize | |
| + "H" + w1 * cellSize + "V" + (d1 + 1) * cellSize | |
| + "H" + (w1 + 1) * cellSize + "V" + 0 | |
| + "H" + (w0 + 1) * cellSize + "Z"; | |
| } | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| rect { | |
| stroke: #E6E6E6; | |
| stroke-width: 1.5px; | |
| } | |
| .axis text { | |
| font-size: 9pt; | |
| font-family: Consolas, courier; | |
| fill: #000; | |
| } | |
| .axis path, | |
| .axis line { | |
| fill: none; | |
| stroke: none; | |
| } | |
| .d3-tip { | |
| line-height: 1; | |
| font: 14px sans-serif; | |
| padding: 12px; | |
| background: rgba(0, 0, 0, 0.8); | |
| color: rgb(185, 185, 185); | |
| border-radius: 2px; | |
| } | |
| /* Creates a small triangle extender for the tooltip */ | |
| .d3-tip:after { | |
| box-sizing: border-box; | |
| display: inline; | |
| font-size: 10px; | |
| width: 100%; | |
| line-height: 1; | |
| color: rgba(0, 0, 0, 0.8); | |
| content: "\25BC"; | |
| position: absolute; | |
| text-align: center; | |
| } | |
| /* Style northward tooltips differently */ | |
| .d3-tip.n:after { | |
| margin: -1px 0 0 0; | |
| top: 100%; | |
| left: 0; | |
| } | |
| #chart { | |
| width: 100%; | |
| height: 100%; | |
| min-width: 500px; | |
| min-height: 500px; | |
| position: absolute; | |
| } | |
| .day { | |
| stroke: #666; | |
| } | |
| .month { | |
| fill: none; | |
| stroke: #000; | |
| stroke-width: 2.5px; | |
| } | |
| .RdYlGn .q0-11{fill:rgb(165,0,38)} | |
| .RdYlGn .q1-{fill:rgb(215,48,39)} | |
| .RdYlGn .q2-11{fill:rgb(244,109,67)} | |
| .RdYlGn .q3-11{fill:rgb(253,174,97)} | |
| .RdYlGn .q4-11{fill:rgb(254,224,139)} | |
| .RdYlGn .q5-11{fill:rgb(255,255,191)} | |
| .RdYlGn .q6-11{fill:rgb(217,239,139)} | |
| .RdYlGn .q7-11{fill:rgb(166,217,106)} | |
| .RdYlGn .q8-11{fill:rgb(102,189,99)} | |
| .RdYlGn .q9-11{fill:rgb(26,152,80)} | |
| .RdYlGn .q10-11{fill:rgb(0,104,55)} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment