我们正在使用AmCharts的股票图表,其中多个DataSet通过ajax异步加载。
不幸的是,它看起来像整个图表的日期范围,我的意思是“From”和“To”仅从添加到所有DataSet的数组中的第一个设置。
想象一下你有3个DataSet的情况,每个DataSet都有完全不同的开始和结束日期:
<script id="data-set-1" type="application/json">
[
{"date": "2016-10-02T10:00:00", "value": 23.8},
{"date": "2016-10-02T10:05:00", "value": 16.8},
{"date": "2016-10-02T10:10:00", "value": 20.5}
]
</script>
<!-- This dataset has max end date from all 3 datasets -->
<script id="data-set-2" type="application/json">
[
{"date": "2016-10-02T10:00:00", "value": 15.2},
{"date": "2016-10-02T10:05:00", "value": 21.4},
{"date": "2016-10-02T10:15:00", "value": 18.1}
]
</script>
<!-- This dataset has min start date from all 3 datasets -->
<script id="data-set-3" type="application/json">
[
{"date": "2016-10-02T09:55:00", "value": 12.4},
{"date": "2016-10-02T10:00:00", "value": 17.7},
{"date": "2016-10-02T10:05:00", "value": 14.6}
]
</script>
在上面的示例中,您可以看到data-set-2具有来自所有3个DataSet的最大结束日期,而data-set-3具有来自所有3个DataSet的最小开始日期。
最终结果:
<!DOCTYPE html>
<html>
<head>
<title>AmCharts multiple datasets min-max date range issue</title>
<meta charset="utf-8" />
<style type="text/css">
#chartdiv {
width: 100%;
height: 500px;
}
</style>
<script id="data-set-1" type="application/json">
[
{"date": "2016-10-02T10:00:00", "value": 23.8},
{"date": "2016-10-02T10:05:00", "value": 16.8},
{"date": "2016-10-02T10:10:00", "value": 20.5}
]
</script>
<!-- This dataset has max end date from all 3 datasets -->
<script id="data-set-2" type="application/json">
[
{"date": "2016-10-02T10:00:00", "value": 15.2},
{"date": "2016-10-02T10:05:00", "value": 21.4},
{"date": "2016-10-02T10:15:00", "value": 18.1}
]
</script>
<!-- This dataset has min start date from all 3 datasets -->
<script id="data-set-3" type="application/json">
[
{"date": "2016-10-02T09:55:00", "value": 12.4},
{"date": "2016-10-02T10:00:00", "value": 17.7},
{"date": "2016-10-02T10:05:00", "value": 14.6}
]
</script>
<link rel="stylesheet" href="https://www.amcharts.com/lib/3/plugins/export/export.css" type="text/css" media="all" />
</head>
<body>
<div id="chartdiv"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/serial.js"></script>
<script src="https://www.amcharts.com/lib/3/amstock.js"></script>
<script src="https://www.amcharts.com/lib/3/plugins/export/export.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
AmCharts.useUTC = true; // this will prevent adding timezone hours to ech date
var chart = AmCharts.makeChart("chartdiv", {
"pathToImages": "http://cdn.amcharts.com/lib/3/images/",
"type": "stock",
"theme": "light",
"categoryAxesSettings": {
"minPeriod": "mm" // precision to minutes
},
"dataSets": [], // empty, we will add each based on single sensor
"panels": [{
"recalculateToPercents": "never", // show value on scale not percent
"showCategoryAxis": true,
"title": "",
"percentHeight": 70,
"stockGraphs": [{ // generic config for all lines
"id": "g1",
"connect": true, // show gaps in data
"comparable": true, // must be true to disable/enable each dataset
"compareField": "value",
"valueField": "value",
"type": "smoothedLine",
"lineThickness": 2,
"bullet": "round"
}],
"stockLegend": {
"periodValueTextRegular": "[[value.close]]" // what will be shown at top legend
}
}],
"chartScrollbarSettings": {
"graph": "g1",
"usePeriod": "10mm",
"position": "top"
},
"chartCursorSettings": {
"valueBalloonsEnabled": true
},
"periodSelector": {
"fromText": "",
"toText": "",
"periodsText": "",
"position": "top",
"dateFormat": "YYYY-MM-DD JJ:NN",
"inputFieldWidth": 150,
"periods": [{
"period": "hh",
"count": 1,
"label": "1 H",
"selected": true
}, {
"period": "hh",
"count": 8,
"label": "8 H"
}, {
"period": "DD",
"count": 1,
"label": "1 D"
}, {
"period": "DD",
"count": 10,
"label": "10 D"
}, {
"period": "MM",
"selected": true,
"count": 1,
"label": "1 M"
}, {
"period": "YYYY",
"count": 1,
"label": "1 Y"
}, {
"period": "YTD",
"label": "YTD"
}, {
"period": "MAX",
"label": "MAX"
}]
},
"panelsSettings": {
"usePrefixes": true
},
"export": {
"enabled": true,
"exportTitles": true,
"libs": {
"path": "http://www.amcharts.com/lib/3/plugins/export/libs/"
},
"position": "bottom-right"
}
});
for (var i = 1; i <= 3; i++) {
var dataset = new AmCharts.DataSet();
dataset.compared = true;
dataset.title = "DataSet " + i;
dataset.categoryField = "date";
dataset.fieldMappings = JSON.parse('[{"fromField": "value", "toField": "value"}]');
var data = JSON.parse($("#data-set-" + i).html());
dataset.dataProvider = data;
chart.dataSets.push(dataset);
chart.validateData();
}
});
</script>
</body>
</html>
你可以看到整个图表被截断到data-set-1的日期范围,图表没有显示date-set-2 point:
{"date": "2016-10-02T10:15:00", "value": 18.1}
并且也没有显示日期设置3点:
{"date": "2016-10-02T09:55:00", "value": 12.4}
我试图在没有任何运气的情况下破解“从”和“到”输入:
chart.addListener("init",
function (e) {
//e.chart.startDate = moment("2016-10-01 00:00");
//e.chart.endDate = moment("2016-10-03 00:00");
});
如何强制图表查找所有DataSet中的最小和最大日期,而不仅仅是从添加到DataSet数组中的第一个日期中查找?
答案 0 :(得分:1)
股票图表将始终使用主要选定数据集中的日期范围,忽略来自不符合&#34;适合&#34;的比较数据集的数据点。在这个范围内。
此外,它将忽略没有直接时间戳匹配的数据点。
显而易见的解决方案是通过添加&#34;空&#34;来同步所有数据集中的数据。主数据集中的数据点与比较数据集中的数据点重叠。
我知道在生成数据的服务器端执行此操作可能会带来令人沮丧的不便和低效。
幸运的是,我们可以实现一个可以做到这一点的客户端包装器。
我在这里更新了你的例子:
<!DOCTYPE html>
<html>
<head>
<title>AmCharts multiple datasets min-max date range issue</title>
<meta charset="utf-8" />
<style type="text/css">
#chartdiv {
width: 100%;
height: 500px;
}
</style>
<script id="data-set-1" type="application/json">
[
{"date": "2016-10-02T10:00:00", "value": 23.8},
{"date": "2016-10-02T10:05:00", "value": 16.8},
{"date": "2016-10-02T10:10:00", "value": 20.5}
]
</script>
<!-- This dataset has max end date from all 3 datasets -->
<script id="data-set-2" type="application/json">
[
{"date": "2016-10-02T10:00:00", "value": 15.2},
{"date": "2016-10-02T10:05:00", "value": 21.4},
{"date": "2016-10-02T10:15:00", "value": 18.1}
]
</script>
<!-- This dataset has min start date from all 3 datasets -->
<script id="data-set-3" type="application/json">
[
{"date": "2016-10-02T09:55:00", "value": 12.4},
{"date": "2016-10-02T10:00:00", "value": 17.7},
{"date": "2016-10-02T10:05:00", "value": 14.6}
]
</script>
<link rel="stylesheet" href="https://www.amcharts.com/lib/3/plugins/export/export.css" type="text/css" media="all" />
</head>
<body>
<div id="chartdiv"></div>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<script src="https://www.amcharts.com/lib/3/amcharts.js"></script>
<script src="https://www.amcharts.com/lib/3/serial.js"></script>
<script src="https://www.amcharts.com/lib/3/amstock.js"></script>
<script src="https://www.amcharts.com/lib/3/plugins/export/export.min.js"></script>
<script type="text/javascript">
function syncDataTimestamps(chart) {
// check if plugin is enabled
if (chart.syncDataTimestamps !== true)
return;
// go thorugh all data sets and collect all the different timestamps
var dates = {};
for (var i = 0; i < chart.dataSets.length; i++) {
var ds = chart.dataSets[i];
for (var x = 0; x < ds.dataProvider.length; x++) {
var date = ds.dataProvider[x][ds.categoryField];
if ( !(date instanceof Date))
date = new Date(date);
if (dates[date.getTime()] === undefined)
dates[date.getTime()] = {};
dates[date.getTime()][i] = ds.dataProvider[x];
}
}
// iterate through data sets again and fill in the blanks
for (var i = 0; i < chart.dataSets.length; i++) {
var ds = chart.dataSets[i];
var dp = [];
for (var ts in dates) {
if (!dates.hasOwnProperty(ts))
continue;
var row = dates[ts];
if (row[i] === undefined) {
row[i] = {};
var d = new Date();
d.setTime(ts);
row[i][ds.categoryField] = d;
}
dp.push(row[i]);
}
dp.sort(function(a,b){
return new Date(a[ds.categoryField]) - new Date(b[ds.categoryField]);
});
ds.dataProvider = dp;
}
};
$(document).ready(function () {
AmCharts.useUTC = true; // this will prevent adding timezone hours to ech date
var chart = AmCharts.makeChart("chartdiv", {
"type": "stock",
"theme": "light",
"categoryAxesSettings": {
"minPeriod": "mm" // precision to minutes
},
"syncDataTimestamps": true,
"dataSets": [], // empty, we will add each based on single sensor
"panels": [{
"recalculateToPercents": "never", // show value on scale not percent
"showCategoryAxis": true,
"title": "",
"percentHeight": 70,
"stockGraphs": [{ // generic config for all lines
"id": "g1",
"connect": true, // show gaps in data
"comparable": true, // must be true to disable/enable each dataset
"compareField": "value",
"valueField": "value",
"type": "smoothedLine",
"lineThickness": 2,
"bullet": "round"
}],
"stockLegend": {
"periodValueTextRegular": "[[value.close]]" // what will be shown at top legend
}
}],
"chartScrollbarSettings": {
"graph": "g1",
"usePeriod": "10mm",
"position": "top"
},
"chartCursorSettings": {
"valueBalloonsEnabled": true
},
"periodSelector": {
"fromText": "",
"toText": "",
"periodsText": "",
"position": "top",
"dateFormat": "YYYY-MM-DD JJ:NN",
"inputFieldWidth": 150,
"periods": [{
"period": "hh",
"count": 1,
"label": "1 H",
"selected": true
}, {
"period": "hh",
"count": 8,
"label": "8 H"
}, {
"period": "DD",
"count": 1,
"label": "1 D"
}, {
"period": "DD",
"count": 10,
"label": "10 D"
}, {
"period": "MM",
"selected": true,
"count": 1,
"label": "1 M"
}, {
"period": "YYYY",
"count": 1,
"label": "1 Y"
}, {
"period": "YTD",
"label": "YTD"
}, {
"period": "MAX",
"label": "MAX"
}]
},
"panelsSettings": {
"usePrefixes": true
},
"export": {
"enabled": true,
"exportTitles": true,
"libs": {
"path": "http://www.amcharts.com/lib/3/plugins/export/libs/"
},
"position": "bottom-right"
}
});
for (var i = 1; i <= 3; i++) {
var dataset = new AmCharts.DataSet();
dataset.compared = true;
dataset.title = "DataSet " + i;
dataset.categoryField = "date";
dataset.fieldMappings = JSON.parse('[{"fromField": "value", "toField": "value"}]');
var data = JSON.parse($("#data-set-" + i).html());
dataset.dataProvider = data;
chart.dataSets.push(dataset);
}
syncDataTimestamps(chart);
chart.validateData();
});
</script>
</body>
</html>
&#13;
请注意,我还将validateData()
调用移出了循环,因此只调用一次,而不是不必要地调用三次。