Common Time Discoveryecharts heatmap配置项内容和展示

给定一堆起止时间,交互式地选择公共时间最长且数据最多的时间区间。

配置项如下
      var gridCount = 50;
var data = [
    1478729724, 1479311478,
    1478761660, 1479307021,
    1478729885, 1479232519,
    1478732238, 1479194757,
    1478711101, 1479311996,
    1478707230, 1479307195,
    1478730048, 1479306188,
    1478707206, 1479311128,
    1479085312, 1479311271,
    1478711635, 1479311998,
    1478728498, 1479311999,
    1478731526, 1479309311,
    1478730676, 1479307276,
    1478728717, 1479297930,
    1478767403, 1479311994,
    1478818927, 1479311998,
    1478724285, 1479310387,
    1478707205, 1479311390,
    1478731145, 1479229316,
    1478775204, 1479264482,
    1478707205, 1479311879,
    1478707205, 1479311994,
    1478707206, 1479310890,
    1479003360, 1479221106,
    1478727895, 1479235223,
    1478707203, 1479307996,
    1478707201, 1479310388,
    1478724694, 1479244875,
    1478709314, 1479305480,
    1478730502, 1479311506,
    1478747274, 1479296426,
    1478707264, 1479311999,
    1478727436, 1479306982,
    1478707204, 1479311994,
    1478707206, 1479309008,
    1478707762, 1479311957,
    1478731348, 1479226004,
    1478732983, 1479311296,
    1478758006, 1479297177,
    1478732624, 1479311995,
    1478707204, 1479310260,
    1478727295, 1479311997,
    1479009556, 1479304022,
    1478728047, 1479304756,
    1478731409, 1479311994,
    1478738554, 1479305618,
    1478838482, 1479311994,
    1478707624, 1479310732,
    1478707240, 1479308394,
    1478718520, 1479304536,
    1478734323, 1479288904,
    1478707202, 1479309501,
    1478713771, 1479311859,
    1478708635, 1479311478,
    1478707202, 1479289802,
    1478731092, 1479304848,
    1478731592, 1479303829,
    1478724961, 1479309346,
    1478731196, 1479309348,
    1478707206, 1479311560,
    1478707205, 1479288653,
    1478730962, 1479199476,
    1478707204, 1479303015,
    1478731994, 1479309152,
    1478728876, 1479287088,
    1478707266, 1479300729,
    1478708111, 1479130712,
    1478731061, 1479306130,
    1478733092, 1479311651,
    1478726863, 1479309931,
    1478818445, 1479308438,
    1478818176, 1479310822,
    1478732149, 1479266358,
    1478707206, 1479308779,
    1478730323, 1479303450,
    1478728318, 1479296128,
    1478708318, 1479287815,
    1478726086, 1479311998,
    1478733362, 1479306667,
    1478846528, 1479307204,
    1478707205, 1479311971,
    1478728060, 1479212106,
    1478731436, 1479307836,
    1478723527, 1479311991,
    1478732854, 1479307296,
    1478739740, 1479311998,
    1478727046, 1479311994,
    1478707573, 1479311652,
    1478707215, 1479311986,
    1478745396, 1479276767,
    1478751561, 1479311996,
    1478708392, 1479311994,
    1478725996, 1479288990,
    1478707201, 1479311991,
    1478732584, 1479302518,
    1478708190, 1479305596,
    1478708685, 1479307847,
    1478707204, 1479309067,
    1478707206, 1479310392,
    1478845900, 1479310515
];

var startTime = [];
var endTime = [];
var heatmapData = []
var durationLenData = []
var rawData = []
var maxCount = 0;
var maxCarCount = 0;
var maxDuration = 0;
var minDuration;
var durationMap = {}

function runMe() {
    var objs = []
    for (var i = 1; i < data.length; i += 2) {
        objs.push({
            start: data[i - 1],
            end: data[i]
        })
    }
    minCount = objs.length
    

    var start = _.min(data)
    var end = _.max(data)
    var dt = parseInt((end - start) / gridCount)
    minDuration = end-start
    console.log(start, end, dt)

    for (var x = 0; x < gridCount+1; x++) {
        var tx = start + x * dt
        startTime.push(moment(tx*1000).format('YYYY/MM/DD HH:mm'))
        for (var y = 0; y < gridCount+1; y++) {
        	var ty = start + y * dt
            if (x === 0) {
                endTime.push(moment(ty*1000).format('YYYY/MM/DD HH:mm'))
            }
            if (y <= x) {
                //heatmapData.push([x, y, '-'])
            } else {
                heatmapData.push([x, y, calc(objs, tx, ty)])
                durationLenData.push([x, y, ty-tx])
                var key = x+'-'+y
                durationMap[key]=ty-tx
                if(maxDuration<ty-tx) maxDuration = ty-tx
                if(minDuration>ty-tx) minDuration = ty-tx
            }
        }
    }

    calcRaw(objs, start, dt)
    console.log(maxDuration, minDuration)
    //console.log(JSON.stringify(rawData))
    //console.log(JSON.stringify(grids));
}


function calc(objs, ts, te) {
    var coverCount = 0;
    for (var i in objs) {
        var traj = objs[i]
        if (traj.start <= ts && te <= traj.end) {
            coverCount++
        }
    }
    if(coverCount>maxCount) maxCount=coverCount;
    if(coverCount<minCount) minCount=coverCount;
    return coverCount
}

var pointMap = {}

function calcRaw(objs, start, dt){
	var m = {}
	for(var j in objs){
    	var o = objs[j]
    	var x = parseInt((o.start-start)/dt)
    	var y = parseInt((o.end - start)/dt)
    	var key = x+'-'+y
    	if(!(key in m)){
    		m[key] = [o.end - o.start, 1]
    	}else{
    		if(o.end-o.start<m[key][0]){
    			m[key][0] = o.end-o.start
    		}
    		m[key][1] = m[key][1]+1
    	}
    }
    for(var i in m){
    	var arr = i.split('-')
    	var t = moment.duration(m[i][0], 'seconds')
    	pointMap[i] = {
    	    duration:t.days()+' days '+t.hours()+' hours',
    	    carCount:m[i][1]
    	}
    	rawData.push([
    		parseInt(arr[0]),
    		parseInt(arr[1]),
    		t.days()+' days '+t.hours()+' hours'
    	])
    	if(m[i][1]>maxCarCount){
    		maxCarCount = m[i][1]
    	}
    }
}


runMe();


option = {
    legend: {
        right: 10,
        data: ['Coverage', 'Duration length','Raw']
    },
    animation: false,
    grid: {
        height: '80%',
        y: '10%',
        x: '12%'
    },
    xAxis: {
        type: 'category',
        data: startTime,
        splitArea: {
            show: true
        }
    },
    yAxis: {
        type: 'category',
        data: endTime,
        splitArea: {
            show: true
        }
    },
    tooltip: {
        position: 'right',
        formatter: function (params) {
            //console.log(params)
            var key = params.value[0]+'-'+params.value[1]
            if(params.seriesType=='heatmap'){
                if(params.seriesName=='Coverage'){
                    var du = moment.duration(durationMap[key]*1000)
                    return params.value[2] + ' cars cover '+du.days()+' days '+du.hours()+' hours ('+startTime[params.value[0]]+' - '+endTime[params.value[1]]+')';
                }else{
                    var t = moment.duration(params.value[2]*1000)
                    return t.days()+' days '+t.hours()+' hours';
                }
            }else{
                var key = params.value[0]+'-'+params.value[1]
                var p = pointMap[key]
            	return p.duration + ' ('+p.carCount+' cars. timeline ('+startTime[params.value[0]]+' - '+endTime[params.value[1]]+')';
            }
        }
    },
    visualMap: [{
        seriesIndex:0,
        min: 0,
        max: maxCount,
        calculable: true,
        orient: 'horizontal',
        left: 'center',
        bottom: '25%',
        inRange: {
            color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
        }
    },{
        seriesIndex:1,
        min: minDuration,
        max: maxDuration,
        calculable: true,
        orient: 'horizontal',
        left: 'center',
        bottom: '10%',
        inRange: {
            opacity: [0,0.3],
            color:['#000','#333']
            // color: ['#313695', '#4575b4', '#74add1', '#abd9e9', '#e0f3f8', '#ffffbf', '#fee090', '#fdae61', '#f46d43', '#d73027', '#a50026']
        },
        formatter: function (value) {
            var t = moment.duration(value*1000)
            return t.days()+' days '+t.hours()+' hours'; // 范围标签显示内容。
        }
    }],
    series: [{
        name: 'Coverage',
        type: 'heatmap',
        data: heatmapData,
        label: {
            normal: {
                show: false
            }
        },
        itemStyle: {
            emphasis: {
                shadowBlur: 10,
                shadowColor: 'rgba(0, 0, 0, 0.5)'
            }
        },
        animation: false
    },
    {
        name: 'Duration length',
        type: 'heatmap',
        data: durationLenData,
        label: {
            normal: {
                show: false
            }
        },
        itemStyle: {
            normal:{
                color:'#BCF'
            }
        }
    },
    {
        name: 'Raw',
        type: 'scatter',
        data: rawData,
        label: {
            normal: {
                show: false
            }
        },
        itemStyle: {
        	normal:{
        		color: 'rgb(0,180,20)'
        	},
            emphasis: {
                shadowBlur: 16,
                shadowColor: 'rgba(0, 0, 200, 0.5)'
            }
        },
        animation: false
    }]
}
    
截图如下