简体   繁体   English

使用日历热图。 不显示月份或图例

[英]Using Calendar Heat Map. Not showing month or legend

I am using this to create a heatmap. 我正在用来创建一个热图。 However the names of the months are getting hidden. 但是,这些月份的名称已被隐藏。 When I do a browser search, it is finding the month name but not showing it on the browser. 当我执行浏览器搜索时,它会找到月份名称,但未在浏览器中显示。

 function calendarHeatmap() { // defaults var width = 750; var height = 110; var legendWidth = 150; var selector = 'body'; var SQUARE_LENGTH = 11; var SQUARE_PADDING = 2; var MONTH_LABEL_PADDING = 6; var now = moment().endOf('day').toDate(); var yearAgo = moment().startOf('day').subtract(1, 'year').toDate(); var startDate = null; var data = []; var max = null; var colorRange = ['#D8E6E7', '#218380']; var tooltipEnabled = true; var tooltipUnit = 'contribution'; var legendEnabled = true; var onClick = null; var weekStart = 0; //0 for Sunday, 1 for Monday var locale = { months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], No: 'No', on: 'on', Less: 'Less', More: 'More' }; // setters and getters chart.data = function (value) { if (!arguments.length) { return data; } data = value; return chart; }; chart.max = function (value) { if (!arguments.length) { return max; } max = value; return chart; }; chart.selector = function (value) { if (!arguments.length) { return selector; } selector = value; return chart; }; chart.startDate = function (value) { if (!arguments.length) { return startDate; } yearAgo = value; now = moment(value).endOf('day').add(1, 'year').toDate(); return chart; }; chart.colorRange = function (value) { if (!arguments.length) { return colorRange; } colorRange = value; return chart; }; chart.tooltipEnabled = function (value) { if (!arguments.length) { return tooltipEnabled; } tooltipEnabled = value; return chart; }; chart.tooltipUnit = function (value) { if (!arguments.length) { return tooltipUnit; } tooltipUnit = value; return chart; }; chart.legendEnabled = function (value) { if (!arguments.length) { return legendEnabled; } legendEnabled = value; return chart; }; chart.onClick = function (value) { if (!arguments.length) { return onClick(); } onClick = value; return chart; }; chart.locale = function (value) { if (!arguments.length) { return locale; } locale = value; return chart; }; function chart() { d3.select(chart.selector()).selectAll('svg.calendar-heatmap').remove(); // remove the existing chart, if it exists var dateRange = d3.time.days(yearAgo, now); // generates an array of date objects within the specified range var monthRange = d3.time.months(moment(yearAgo).startOf('month').toDate(), now); // it ignores the first month if the 1st date is after the start of the month var firstDate = moment(dateRange[0]); if (max === null) { max = d3.max(chart.data(), function (d) { return d.count; }); } // max data value // color range var color = d3.scale.linear() .range(chart.colorRange()) .domain([0, max]); var tooltip; var dayRects; drawChart(); function drawChart() { var svg = d3.select(chart.selector()) .style('position', 'relative') .append('svg') .attr('width', width) .attr('class', 'calendar-heatmap') .attr('height', height) .style('padding', '36px'); dayRects = svg.selectAll('.day-cell') .data(dateRange); // array of days for the last yr dayRects.enter().append('rect') .attr('class', 'day-cell') .attr('width', SQUARE_LENGTH) .attr('height', SQUARE_LENGTH) .attr('fill', function(d) { return color(countForDate(d)); }) .attr('x', function (d, i) { var cellDate = moment(d); var result = cellDate.week() - firstDate.week() + (firstDate.weeksInYear() * (cellDate.weekYear() - firstDate.weekYear())); return result * (SQUARE_LENGTH + SQUARE_PADDING); }) .attr('y', function (d, i) { return MONTH_LABEL_PADDING + formatWeekday(d.getDay()) * (SQUARE_LENGTH + SQUARE_PADDING); }); if (typeof onClick === 'function') { dayRects.on('click', function (d) { var count = countForDate(d); onClick({ date: d, count: count}); }); } if (chart.tooltipEnabled()) { dayRects.on('mouseover', function (d, i) { tooltip = d3.select(chart.selector()) .append('div') .attr('class', 'day-cell-tooltip') .html(tooltipHTMLForDate(d)) .style('left', function () { return Math.floor(i / 7) * SQUARE_LENGTH + 'px'; }) .style('top', function () { return formatWeekday(d.getDay()) * (SQUARE_LENGTH + SQUARE_PADDING) + MONTH_LABEL_PADDING * 2 + 'px'; }); }) .on('mouseout', function (d, i) { tooltip.remove(); }); } if (chart.legendEnabled()) { var colorRange = [color(0)]; for (var i = 3; i > 0; i--) { colorRange.push(color(max / i)); } var legendGroup = svg.append('g'); legendGroup.selectAll('.calendar-heatmap-legend') .data(colorRange) .enter() .append('rect') .attr('class', 'calendar-heatmap-legend') .attr('width', SQUARE_LENGTH) .attr('height', SQUARE_LENGTH) .attr('x', function (d, i) { return (width - legendWidth) + (i + 1) * 13; }) .attr('y', height + SQUARE_PADDING) .attr('fill', function (d) { return d; }); legendGroup.append('text') .attr('class', 'calendar-heatmap-legend-text calendar-heatmap-legend-text-less') .attr('x', width - legendWidth - 13) .attr('y', height + SQUARE_LENGTH) .text(locale.Less); legendGroup.append('text') .attr('class', 'calendar-heatmap-legend-text calendar-heatmap-legend-text-more') .attr('x', (width - legendWidth + SQUARE_PADDING) + (colorRange.length + 1) * 13) .attr('y', height + SQUARE_LENGTH) .text(locale.More); } dayRects.exit().remove(); var monthLabels = svg.selectAll('.month') .data(monthRange) .enter().append('text') .attr('class', 'month-name') .style() .text(function (d) { return locale.months[d.getMonth()]; }) .attr('x', function (d, i) { var matchIndex = 0; dateRange.find(function (element, index) { matchIndex = index; return moment(d).isSame(element, 'month') && moment(d).isSame(element, 'year'); }); return Math.floor(matchIndex / 7) * (SQUARE_LENGTH + SQUARE_PADDING); }) .attr('y', 0); // fix these to the top locale.days.forEach(function (day, index) { index = formatWeekday(index); if (index % 2) { svg.append('text') .attr('class', 'day-initial') .attr('transform', 'translate(-8,' + (SQUARE_LENGTH + SQUARE_PADDING) * (index + 1) + ')') .style('text-anchor', 'middle') .attr('dy', '2') .text(day); } }); } function pluralizedTooltipUnit (count) { if ('string' === typeof tooltipUnit) { return (tooltipUnit + (count === 1 ? '' : 's')); } for (var i in tooltipUnit) { var _rule = tooltipUnit[i]; var _min = _rule.min; var _max = _rule.max || _rule.min; _max = _max === 'Infinity' ? Infinity : _max; if (count >= _min && count <= _max) { return _rule.unit; } } } function tooltipHTMLForDate(d) { var dateStr = moment(d).format('ddd, MMM Do YYYY'); var count = countForDate(d); return '<span><strong>' + (count ? count : locale.No) + ' ' + pluralizedTooltipUnit(count) + '</strong> ' + locale.on + ' ' + dateStr + '</span>'; } function countForDate(d) { var count = 0; var match = chart.data().find(function (element, index) { return moment(element.date).isSame(d, 'day'); }); if (match) { count = match.count; } return count; } function formatWeekday(weekDay) { if (weekStart === 1) { if (weekDay === 0) { return 6; } else { return weekDay - 1; } } return weekDay; } var daysOfChart = chart.data().map(function (day) { return day.date.toDateString(); }); dayRects.filter(function (d) { return daysOfChart.indexOf(d.toDateString()) > -1; }).attr('fill', function (d, i) { return color(chart.data()[i].count); }); } return chart; } // polyfill for Array.find() method /* jshint ignore:start */ if (!Array.prototype.find) { Array.prototype.find = function (predicate) { if (this === null) { throw new TypeError('Array.prototype.find called on null or undefined'); } if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } var list = Object(this); var length = list.length >>> 0; var thisArg = arguments[1]; var value; for (var i = 0; i < length; i++) { value = list[i]; if (predicate.call(thisArg, value, i, list)) { return value; } } return undefined; }; } var now = moment().endOf('day').toDate(); var yearAgo = moment().startOf('day').subtract(1, 'year').toDate(); var chartData = d3.time.days(yearAgo, now).map(function (dateElement) { return { date: dateElement, count: (dateElement.getDay() !== 0 && dateElement.getDay() !== 6) ? Math.floor(Math.random() * 60) : Math.floor(Math.random() * 10) }; }); var heatmap = calendarHeatmap() .data(chartData) .selector('.container') .tooltipEnabled(true) .colorRange(['#f4f7f7', '#79a8a9']) .onClick(function (data) { console.log('data', data); }); heatmap(); // render the chart 
 text.month-name, text.calendar-heatmap-legend-text, text.day-initial { font-size: 10px; fill: inherit; font-family: Helvetica, arial, 'Open Sans', sans-serif; } rect.day-cell:hover { stroke: #555555; stroke-width: 1px; } .day-cell-tooltip { position: absolute; z-index: 999999; padding: 5px 9px; color: #bbbbbb; font-size: 12px; background: rgba(0, 0, 0, 0.85); border-radius: 3px; text-align: center; } .day-cell-tooltip > span { font-family: Helvetica, arial, 'Open Sans', sans-serif } .calendar-heatmap { box-sizing: initial; } 
 <div class="container"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js" charset="utf-8"></script> <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> 

Here is plunker: http://plnkr.co/edit/JUBIs2IzHA9i5V8N1WMv?p=preview 这是pl客: http ://plnkr.co/edit/JUBIs2IzHA9i5V8N1WMv? p =preview

var heatmap = calendarHeatmap()
                  .data(chartData)
                  .selector('.container')
                  .tooltipEnabled(true)
                  .colorRange(['#f4f7f7', '#79a8a9'])
                  .onClick(function (data) {
                    console.log('data', data);
                  });

I haven't made any changes to the original source code. 我没有对原始源代码进行任何更改。

 function calendarHeatmap() { // defaults var width = 750; var height = 110; var legendWidth = 150; var selector = 'body'; var SQUARE_LENGTH = 11; var SQUARE_PADDING = 2; var MONTH_LABEL_PADDING = 6; var now = moment().endOf('day').toDate(); var yearAgo = moment().startOf('day').subtract(1, 'year').toDate(); var startDate = null; var data = []; var max = null; var colorRange = ['#D8E6E7', '#218380']; var tooltipEnabled = true; var tooltipUnit = 'contribution'; var legendEnabled = true; var onClick = null; var weekStart = 0; //0 for Sunday, 1 for Monday var locale = { months: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], days: ['S', 'M', 'T', 'W', 'T', 'F', 'S'], No: 'No', on: 'on', Less: 'Less', More: 'More' }; // setters and getters chart.data = function (value) { if (!arguments.length) { return data; } data = value; return chart; }; chart.max = function (value) { if (!arguments.length) { return max; } max = value; return chart; }; chart.selector = function (value) { if (!arguments.length) { return selector; } selector = value; return chart; }; chart.startDate = function (value) { if (!arguments.length) { return startDate; } yearAgo = value; now = moment(value).endOf('day').add(1, 'year').toDate(); return chart; }; chart.colorRange = function (value) { if (!arguments.length) { return colorRange; } colorRange = value; return chart; }; chart.tooltipEnabled = function (value) { if (!arguments.length) { return tooltipEnabled; } tooltipEnabled = value; return chart; }; chart.tooltipUnit = function (value) { if (!arguments.length) { return tooltipUnit; } tooltipUnit = value; return chart; }; chart.legendEnabled = function (value) { if (!arguments.length) { return legendEnabled; } legendEnabled = value; return chart; }; chart.onClick = function (value) { if (!arguments.length) { return onClick(); } onClick = value; return chart; }; chart.locale = function (value) { if (!arguments.length) { return locale; } locale = value; return chart; }; function chart() { d3.select(chart.selector()).selectAll('svg.calendar-heatmap').remove(); // remove the existing chart, if it exists var dateRange = d3.time.days(yearAgo, now); // generates an array of date objects within the specified range var monthRange = d3.time.months(moment(yearAgo).startOf('month').toDate(), now); // it ignores the first month if the 1st date is after the start of the month var firstDate = moment(dateRange[0]); if (max === null) { max = d3.max(chart.data(), function (d) { return d.count; }); } // max data value // color range var color = d3.scale.linear() .range(chart.colorRange()) .domain([0, max]); var tooltip; var dayRects; drawChart(); function drawChart() { var svg = d3.select(chart.selector()) .style('position', 'relative') .append('svg') .attr('width', width) .attr('class', 'calendar-heatmap') .attr('height', height+SQUARE_LENGTH+SQUARE_LENGTH) .style('padding', '36px') .attr("transform","translate("+(SQUARE_LENGTH+4)+","+(SQUARE_LENGTH)+")"); dayRects = svg.selectAll('.day-cell') .data(dateRange); // array of days for the last yr dayRects.enter().append('rect') .attr('class', 'day-cell') .attr('width', SQUARE_LENGTH) .attr('height', SQUARE_LENGTH) .attr('fill', function(d) { return color(countForDate(d)); }) .attr('x', function (d, i) { var cellDate = moment(d); var result = cellDate.week() - firstDate.week() + (firstDate.weeksInYear() * (cellDate.weekYear() - firstDate.weekYear())); return result * (SQUARE_LENGTH + SQUARE_PADDING); }) .attr('y', function (d, i) { return MONTH_LABEL_PADDING + formatWeekday(d.getDay()) * (SQUARE_LENGTH + SQUARE_PADDING); }); if (typeof onClick === 'function') { dayRects.on('click', function (d) { var count = countForDate(d); onClick({ date: d, count: count}); }); } if (chart.tooltipEnabled()) { dayRects.on('mouseover', function (d, i) { tooltip = d3.select(chart.selector()) .append('div') .attr('class', 'day-cell-tooltip') .html(tooltipHTMLForDate(d)) .style('left', function () { return Math.floor(i / 7) * SQUARE_LENGTH + 'px'; }) .style('top', function () { return formatWeekday(d.getDay()) * (SQUARE_LENGTH + SQUARE_PADDING) + MONTH_LABEL_PADDING * 2 + 'px'; }); }) .on('mouseout', function (d, i) { tooltip.remove(); }); } if (chart.legendEnabled()) { var colorRange = [color(0)]; for (var i = 3; i > 0; i--) { colorRange.push(color(max / i)); } var legendGroup = svg.append('g'); legendGroup.selectAll('.calendar-heatmap-legend') .data(colorRange) .enter() .append('rect') .attr('class', 'calendar-heatmap-legend') .attr('width', SQUARE_LENGTH) .attr('height', SQUARE_LENGTH) .attr('x', function (d, i) { return (width - legendWidth) + (i + 1) * 13; }) .attr('y', height + SQUARE_PADDING) .attr('fill', function (d) { return d; }); legendGroup.append('text') .attr('class', 'calendar-heatmap-legend-text calendar-heatmap-legend-text-less') .attr('x', width - legendWidth - 13) .attr('y', height + SQUARE_LENGTH) .text(locale.Less); legendGroup.append('text') .attr('class', 'calendar-heatmap-legend-text calendar-heatmap-legend-text-more') .attr('x', (width - legendWidth + SQUARE_PADDING) + (colorRange.length + 1) * 13) .attr('y', height + SQUARE_LENGTH) .text(locale.More); } dayRects.exit().remove(); var monthLabels = svg.selectAll('.month') .data(monthRange) .enter().append('text') .attr('class', 'month-name') .style() .text(function (d) { return locale.months[d.getMonth()]; }) .attr('x', function (d, i) { var matchIndex = 0; dateRange.find(function (element, index) { matchIndex = index; return moment(d).isSame(element, 'month') && moment(d).isSame(element, 'year'); }); return Math.floor(matchIndex / 7) * (SQUARE_LENGTH + SQUARE_PADDING); }) .attr('y', 0); // fix these to the top locale.days.forEach(function (day, index) { index = formatWeekday(index); if (index % 2) { svg.append('text') .attr('class', 'day-initial') .attr('transform', 'translate(-8,' + (SQUARE_LENGTH + SQUARE_PADDING) * (index + 1) + ')') .style('text-anchor', 'middle') .attr('dy', '2') .text(day); } }); } function pluralizedTooltipUnit (count) { if ('string' === typeof tooltipUnit) { return (tooltipUnit + (count === 1 ? '' : 's')); } for (var i in tooltipUnit) { var _rule = tooltipUnit[i]; var _min = _rule.min; var _max = _rule.max || _rule.min; _max = _max === 'Infinity' ? Infinity : _max; if (count >= _min && count <= _max) { return _rule.unit; } } } function tooltipHTMLForDate(d) { var dateStr = moment(d).format('ddd, MMM Do YYYY'); var count = countForDate(d); return '<span><strong>' + (count ? count : locale.No) + ' ' + pluralizedTooltipUnit(count) + '</strong> ' + locale.on + ' ' + dateStr + '</span>'; } function countForDate(d) { var count = 0; var match = chart.data().find(function (element, index) { return moment(element.date).isSame(d, 'day'); }); if (match) { count = match.count; } return count; } function formatWeekday(weekDay) { if (weekStart === 1) { if (weekDay === 0) { return 6; } else { return weekDay - 1; } } return weekDay; } var daysOfChart = chart.data().map(function (day) { return day.date.toDateString(); }); dayRects.filter(function (d) { return daysOfChart.indexOf(d.toDateString()) > -1; }).attr('fill', function (d, i) { return color(chart.data()[i].count); }); } return chart; } // polyfill for Array.find() method /* jshint ignore:start */ if (!Array.prototype.find) { Array.prototype.find = function (predicate) { if (this === null) { throw new TypeError('Array.prototype.find called on null or undefined'); } if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } var list = Object(this); var length = list.length >>> 0; var thisArg = arguments[1]; var value; for (var i = 0; i < length; i++) { value = list[i]; if (predicate.call(thisArg, value, i, list)) { return value; } } return undefined; }; } var now = moment().endOf('day').toDate(); var yearAgo = moment().startOf('day').subtract(1, 'year').toDate(); var chartData = d3.time.days(yearAgo, now).map(function (dateElement) { return { date: dateElement, count: (dateElement.getDay() !== 0 && dateElement.getDay() !== 6) ? Math.floor(Math.random() * 60) : Math.floor(Math.random() * 10) }; }); var heatmap = calendarHeatmap() .data(chartData) .selector('.container') .tooltipEnabled(true) .colorRange(['#f4f7f7', '#79a8a9']) .onClick(function (data) { console.log('data', data); }); heatmap(); // render the chart 
 text.month-name, text.calendar-heatmap-legend-text, text.day-initial { font-size: 10px; fill: inherit; font-family: Helvetica, arial, 'Open Sans', sans-serif; } rect.day-cell:hover { stroke: #555555; stroke-width: 1px; } .day-cell-tooltip { position: absolute; z-index: 999999; padding: 5px 9px; color: #bbbbbb; font-size: 12px; background: rgba(0, 0, 0, 0.85); border-radius: 3px; text-align: center; } .day-cell-tooltip > span { font-family: Helvetica, arial, 'Open Sans', sans-serif } .calendar-heatmap { box-sizing: initial; } 
 <div class="container"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js" charset="utf-8"></script> <script src="https://d3js.org/d3.v3.min.js" charset="utf-8"></script> 
After analyzing here and there I figured it out why we are unable to see the legends and Month Lables, I'll explain below, there is a problem with svg height and we need to move svg a little, the code change I've done is 在这里和那里分析之后,我弄清楚了为什么我们看不到图例和Month Lables,我将在下面解释,svg高度存在问题,我们需要稍微移动svg,完成代码更改是

 var svg = d3.select(chart.selector()) .style('position', 'relative') .append('svg') .attr('width', width) .attr('class', 'calendar-heatmap') .attr('height', height+SQUARE_LENGTH+SQUARE_LENGTH) .style('padding', '36px') .attr("transform","translate("+(SQUARE_LENGTH+4)+","+(SQUARE_LENGTH)+")"); 

Month lables are rendering but they are at some other point of svg, so I'm moving whole svg a little in calendar-heatmap.js while creating svg. 一个月的标签正在渲染,但是它们处于svg的其他位置,因此在创建svg时,我将整个svg移到了calendar-heatmap.js中。 This is the actual problem. 这是实际问题。 Initially I was also struggled to figure it out.well We solved it. 最初我也很难弄清楚。好了,我们解决了。 :D :D

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM