我有以下工作JavaScript。它的作用是取mydata
的成员并将热图制作出来。
样本
mydata={
// full data can be found here
// http://dpaste.com/1TZP3AJ.txt
"data1":[ {"timestamp": "2014-09-25T00:00:00", "value": {"PM2.5": 330.22}},
{"timestamp": "2014-09-25T01:00:00", "value": {"PM2.5": 41.61}},
{"timestamp": "2014-09-25T02:00:00", "value": {"PM2.5": 50.71}},
{"timestamp": "2014-09-25T03:00:00", "value": {"PM2.5": 57.34}},
{"timestamp": "2014-09-25T04:00:00", "value": {"PM2.5": 79.64}},
{"timestamp": "2014-09-25T05:00:00", "value": {"PM2.5": 76.93}},
{"timestamp": "2014-10-16T23:00:00", "value": {"PM2.5": 64.39}}],
"data2":[ {"timestamp": "2014-09-25T00:00:00", "value": {"PM2.5": 0.22}},
{"timestamp": "2014-09-25T01:00:00", "value": {"PM2.5": 4.1}},
{"timestamp": "2014-09-25T02:00:00", "value": {"PM2.5": 5.71}},
{"timestamp": "2014-09-25T03:00:00", "value": {"PM2.5": 257.34}},
{"timestamp": "2014-09-25T04:00:00", "value": {"PM2.5": 9.64}},
{"timestamp": "2014-09-25T05:00:00", "value": {"PM2.5": 6.3}},
{"timestamp": "2014-10-16T23:00:00", "value": {"PM2.5": 64.39}}]
}
jQuery(function($){
//console.log("HERE")
//UI configuration
var itemSize = 18,
cellSize = itemSize-1,
width = 800,
height = 800,
margin = {top:20,right:20,bottom:20,left:25};
//formats
var hourFormat = d3.time.format('%H'),
dayFormat = d3.time.format('%j'),
timeFormat = d3.time.format('%Y-%m-%dT%X'),
monthDayFormat = d3.time.format('%m.%d');
//data vars for rendering
var dateExtent = null,
data = null,
dayOffset = 0,
colorCalibration = ['#f6faaa','#FEE08B','#FDAE61','#F46D43','#D53E4F','#9E0142'],
dailyValueExtent = {};
//axises and scales
var axisWidth = 0 ,
axisHeight = itemSize*24,
xAxisScale = d3.time.scale(),
xAxis = d3.svg.axis()
.orient('top')
.ticks(d3.time.days,3)
.tickFormat(monthDayFormat),
yAxisScale = d3.scale.linear()
.range([0,axisHeight])
.domain([0,24]),
yAxis = d3.svg.axis()
.orient('left')
.ticks(5)
.tickFormat(d3.format('02d'))
.scale(yAxisScale);
initCalibration();
var svg = d3.select('[role="heatmap"]');
var heatmap = svg
.attr('width',width)
.attr('height',height)
.append('g')
.attr('width',width-margin.left-margin.right)
.attr('height',height-margin.top-margin.bottom)
.attr('transform','translate('+margin.left+','+margin.top+')');
var rect = null;
data = mydata.data1;
//data = mydata.data2;
data.forEach(function(valueObj){
valueObj['date'] = timeFormat.parse(valueObj['timestamp']);
var day = valueObj['day'] = monthDayFormat(valueObj['date']);
var dayData = dailyValueExtent[day] = (dailyValueExtent[day] || [1000,-1]);
var pmValue = valueObj['value']['PM2.5'];
dayData[0] = d3.min([dayData[0],pmValue]);
dayData[1] = d3.max([dayData[1],pmValue]);
});
dateExtent = d3.extent(data,function(d){
//console.log(d.date)
return d.date;
});
axisWidth = itemSize*(dayFormat(dateExtent[1])-dayFormat(dateExtent[0])+1);
//console.log(axisWidth)
//console.log(dayFormat(dateExtent[1]))
//console.log(dayFormat(dateExtent[0]))
//render axises
xAxis.scale(xAxisScale.range([0,axisWidth]).domain([dateExtent[0],dateExtent[1]]));
svg.append('g')
.attr('transform','translate('+margin.left+','+margin.top+')')
.attr('class','x axis')
.call(xAxis)
.append('text')
.text('date')
.attr('transform','translate('+axisWidth+',-10)');
svg.append('g')
.attr('transform','translate('+margin.left+','+margin.top+')')
.attr('class','y axis')
.call(yAxis)
.append('text')
.text('time')
.attr('transform','translate(-10,'+axisHeight+') rotate(-90)');
//render heatmap rects
dayOffset = dayFormat(dateExtent[0]);
rect = heatmap.selectAll('rect')
.data(data)
.enter().append('rect')
.attr('width',cellSize)
.attr('height',cellSize)
.attr('x',function(d){
return itemSize*(dayFormat(d.date)-dayOffset);
})
.attr('y',function(d){
return hourFormat(d.date)*itemSize;
})
.attr('fill','#ffffff');
rect.filter(function(d){ return d.value['PM2.5']>0;})
.append('title')
.text(function(d){
return monthDayFormat(d.date)+' '+d.value['PM2.5'];
});
renderColor();
//});
function initCalibration(){
d3.select('[role="calibration"] [role="example"]').select('svg')
.selectAll('rect').data(colorCalibration).enter()
.append('rect')
.attr('width',cellSize)
.attr('height',cellSize)
.attr('x',function(d,i){
return i*itemSize;
})
.attr('fill',function(d){
return d;
});
//bind click event
d3.selectAll('[role="calibration"] [name="displayType"]').on('click',function(){
renderColor();
});
}
function renderColor(){
var renderByCount = document.getElementsByName('displayType')[0].checked;
rect
.filter(function(d){
return (d.value['PM2.5']>=0);
})
.transition()
.delay(function(d){
return (dayFormat(d.date)-dayOffset)*15;
})
.duration(500)
.attrTween('fill',function(d,i,a){
//choose color dynamicly
var colorIndex = d3.scale.quantize()
.range([0,1,2,3,4,5])
.domain((renderByCount?[0,500]:dailyValueExtent[d.day]));
return d3.interpolate(a,colorCalibration[colorIndex(d.value['PM2.5'])]);
});
}
//extend frame height in `http://bl.ocks.org/`
d3.select(self.frameElement).style("height", "600px");
});
body{font-family:arial, 'Hiragino Sans GB',Tahoma, Arial, Helvetica, STHeiti;font-size: 14px;}
.days-hours-heatmap{padding: 20px 0 20px 0;width: 500px;margin: 0 auto;}
.days-hours-heatmap .calibration{margin-bottom: 15px;width:400px;}
.days-hours-heatmap .calibration .group{display: inline-block;}
.days-hours-heatmap .calibration .description{width:108px;}
.days-hours-heatmap .calibration .description>label:last-child{float:right;}
.days-hours-heatmap .calibration>.display-control{float:right;}
.days-hours-heatmap .calibration>.display-control label{vertical-align: top;}
.days-hours-heatmap .calibration>.display-control input[type='radio']{cursor: pointer;}
.days-hours-heatmap .heatmap .axis path{display: none;}
.days-hours-heatmap .heatmap .axis line{fill: none;stroke: #000;shape-rendering: crispEdges;}
.days-hours-heatmap .heatmap .axis text{font-size: 12px}
<!DOCTYPE html>
<html>
<head>
<title>Days Hours Heatmap</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<meta charset="utf-8"/>
</head>
<body>
<div class="days-hours-heatmap">
<!-- calibration and render type controller -->
<div class="calibration" role="calibration">
<div class="group" role="example">
<svg width="120" height="17">
</svg>
<div role="description" class="description">
<label>Less</label>
<label>More</label>
</div>
</div>
<div role="toggleDisplay" class="display-control">
<div>
<input type="radio" name="displayType" checked/>
<label>count</label>
</div>
<div>
<input type="radio" name="displayType"/>
<label>daily</label>
</div>
</div>
</div>
<!-- heatmap -->
<svg role="heatmap" class="heatmap"></svg>
</div>
</body>
</html>
目前,daily
单选按钮仅根据基于mydata[data1]
的{{1}}和count
按钮呈现数据。
我想要做的是根据renderByCount
和data1
呈现图片。
因此,稍后在HTML图片中,而不是data2
和count
按钮会显示daily
和data1
。我怎样才能做到这一点?
请注意,在此示例中,data2
对象仅包含两个成员mydata
。但实际上它可能不止于此。
答案 0 :(得分:0)
只需从对象中的键创建面板,就像任何其他d3层次一样:
var radios = d3.select('.display-control')
.selectAll('.radio')
.data(d3.keys(mydata))
.enter()
.append('div')
.attr('class','radio');
radios.append('input').attr({
'type': 'radio',
'name': 'displayType',
'checked': function(d, i) {
// trace the checked radio somewhere outside
return i===0 ? 'checked' : null;
}
});
radios.append('label').text(function(d) {return d;});
超快速&amp;肮脏的小提琴:http://jsfiddle.net/5bh4c6p1/