Highcharts 范围选择器:更改超出缩放时间范围的日期
我构建了一个类似于lazy-loading示例()的图表,但是带有范围选择器的输入字段。 当我放大时,一切都很好。现在,我想通过使用输入字段更改所选范围。 但我无法将输入更改为超出缩放区域的值,尽管我的导航器中有更多可见数据 在setExtremes函数中,我正在进行一些计算:Highcharts 范围选择器:更改超出缩放时间范围的日期,highcharts,Highcharts,我构建了一个类似于lazy-loading示例()的图表,但是带有范围选择器的输入字段。 当我放大时,一切都很好。现在,我想通过使用输入字段更改所选范围。 但我无法将输入更改为超出缩放区域的值,尽管我的导航器中有更多可见数据 在setExtremes函数中,我正在进行一些计算: DX.IPFixGraphModule.prototype.setExtremes = function(e) { var fromTime, maxZoom = 30 * 60 * 1000, now
DX.IPFixGraphModule.prototype.setExtremes = function(e) {
var fromTime,
maxZoom = 30 * 60 * 1000,
now = new Date().getTime();
if (e.min) {
fromTime = e.min;
} else {
fromTime = e.dataMin;
}
fromTime = Math.round(fromTime);
var diff = now - fromTime;
// -1 month = max 1 week zoom
if (diff >= 2592000000) {
maxZoom = 7 * 24 * 60 * 60 * 1000;
}
// -1 week = max 12 hour zoom
else if (diff >= 604800000) {
maxZoom = 12 * 60 * 60 * 1000;
}
// this refers to axis
// @see http://api.highcharts.com/highstock#Axis.update
this.update({
minRange: maxZoom
}, false);
})
但我在e.min和e.max中接收到的值不是原始输入值,而是已更正为显示的时间范围
// handle changes in the input boxes
input.onchange = function () {
var inputValue = input.value,
value = (options.inputDateParser || Date.parse)(inputValue),
xAxis = chart.xAxis[0],
dataMin = xAxis.dataMin,
dataMax = xAxis.dataMax;
// If the value isn't parsed directly to a value by the browser's Date.parse method,
// like YYYY-MM-DD in IE, try parsing it a different way
if (isNaN(value)) {
value = inputValue.split('-');
value = Date.UTC(pInt(value[0]), pInt(value[1]) - 1, pInt(value[2]));
}
if (!isNaN(value)) {
// Correct for timezone offset (#433)
if (!defaultOptions.global.useUTC) {
value = value + new Date().getTimezoneOffset() * 60 * 1000;
}
// Validate the extremes. If it goes beyound the data min or max, use the
// actual data extreme (#2438).
if (isMin) {
if (value > rangeSelector.maxInput.HCTime) {
value = UNDEFINED;
} else if (value < dataMin) {
value = dataMin;
}
} else {
if (value < rangeSelector.minInput.HCTime) {
value = UNDEFINED;
} else if (value > dataMax) {
value = dataMax;
}
}
// Set the extremes
if (value !== UNDEFINED) {
chart.xAxis[0].setExtremes(
isMin ? value : xAxis.min,
isMin ? xAxis.max : value,
UNDEFINED,
UNDEFINED,
{ trigger: 'rangeSelectorInput' }
);
}
}
};
//处理输入框中的更改
input.onchange=函数(){
var inputValue=input.value,
value=(options.inputDateParser | | Date.parse)(inputValue),
xAxis=chart.xAxis[0],
dataMin=xAxis.dataMin,
dataMax=xAxis.dataMax;
//如果浏览器的Date.parse方法未将该值直接解析为值,
//就像IE中的YYYY-MM-DD一样,尝试用不同的方式解析它
如果(isNaN(值)){
value=inputValue.split('-');
value=Date.UTC(品脱(值[0]),品脱(值[1])-1,品脱(值[2]);
}
如果(!isNaN(值)){
//时区偏移正确(#433)
如果(!defaultOptions.global.useUTC){
value=value+newdate().getTimezoneOffset()*60*1000;
}
//验证极端值。如果超出数据最小值或最大值,请使用
//实际数据极端(#2438)。
if(isMin){
if(值>rangeSelector.maxInput.HCTime){
值=未定义;
}否则如果(值<数据最小值){
值=数据分钟;
}
}否则{
if(值数据最大值){
值=数据最大值;
}
}
//走极端
如果(值!==未定义){
chart.xAxis[0]。setExtremes(
isMin?值:xAxis.min,
isMin?xAxis.max:值,
未定义,
未定义,
{触发器:'rangeSelectorInput'}
);
}
}
};
(代码取自第21126行附近的highstock.src.js)
因此,我无法将缩放范围扩展到当前活动选择之外,但导航器会显示更多数据。
有人知道如何将日期设置在当前缩放的时间范围之外吗
可能的解决办法
我通过在“afterSetExtremes”事件中检查导航器范围来解决这个问题
DX.IPFixGraphModule.prototype.afterSetExtremes=函数(e){
如果(例如触发器=='rangeSelectorInput'){
var fromValue=this.stockchart.rangeSelector.minInput.value,
toValue=this.stockchart.rangeSelector.maxInput.value,
fromTime=parseDateTime(fromValue),
toTime=parseDateTime(toValue),
navigatorAxis=this.stockchart.get('navigator-x-axis'),
maxValue=navigatorAxis.dataMax,
minValue=navigatorAxis.dataMin;
如果(从时间<最小值){
fromTime=最小值;
}
如果(toTime>maxValue){
toTime=最大值;
}
this.stockchart.xAxis[0].setextrems(fromTime,toTime);
}否则{
有时,
toTime;
如果(e.min){
fromTime=e.min;
}否则{
fromTime=e.dataMin;
}
fromTime=Math.round(fromTime);
如果(e.max){
toTime=e.max;
}否则{
toTime=e.dataMax;
}
toTime=数学四舍五入(toTime);
this.settings.afterSetExtremes({startTimestamp:fromTime,endTimestamp:toTime});
}
};
或者参阅下面的解决方案并重写该方法。没有默认的API。通过重写drawInput函数(第二个代码段)扩展Highcharts 您应该注释掉或删除代码的一部分-以下内容后的
if
子句:
//验证极端。如果超出数据最小值或最大值,请使用
//实际数据极端(#2438)
例如:
$(函数(){
(职能(H){
H.wrap(H.RangeSelector.prototype,'drawInput',函数(继续){
变量名称=参数[1],
merge=H.merge,
createElement=H.createElement,
前缀='highcharts-',
绝对值=‘绝对值’,
PX='PX',
extend=H.extend,
品脱=高品脱,
未定义;
//drawInput:函数(名称){
var rangeSelector=这个,
chart=rangeSelector.chart,
chartStyle=chart.renderer.style,
renderer=chart.renderer,
选项=chart.options.rangeSelector,
defaultOptions=H.getOptions(),
lang=defaultOptions.lang,
div=rangeSelector.div,
isMin=name=='min',
输入,
标签,
日期框,
inputGroup=this.inputGroup;
//创建文本标签
此[name+'Label']=Label=renderer.Label(lang[isMin?'rangeSelectorFrom':'rangeSelectorTo'],此.inputGroup.offset)
艾特先生({
填充:2
})
.css(合并(图表样式、选项、标签样式))
.add(输入组);
inputGroup.offset+=标签宽度+5;
//创建一个SVG标签,显示更新的日期范围和记录,并单击
//引入HTML输入。
此[name+'DateBox']=DateBox=renderer.label(“”,inputGroup.offset)
艾特先生({
填充:2,
宽度:options.inputBoxWidth | | 90,
高度:options.in
DX.IPFixGraphModule.prototype.afterSetExtremes = function(e) {
if (e.trigger === 'rangeSelectorInput') {
var fromValue = this.stockchart.rangeSelector.minInput.value,
toValue = this.stockchart.rangeSelector.maxInput.value,
fromTime = parseDateTime(fromValue),
toTime = parseDateTime(toValue),
navigatorAxis = this.stockchart.get('navigator-x-axis'),
maxValue = navigatorAxis.dataMax,
minValue = navigatorAxis.dataMin;
if (fromTime < minValue) {
fromTime = minValue;
}
if (toTime > maxValue) {
toTime = maxValue;
}
this.stockchart.xAxis[0].setExtremes(fromTime, toTime);
} else {
var fromTime,
toTime;
if (e.min) {
fromTime = e.min;
} else {
fromTime = e.dataMin;
}
fromTime = Math.round(fromTime);
if (e.max) {
toTime = e.max;
} else {
toTime = e.dataMax;
}
toTime = Math.round(toTime);
this.settings.afterSetExtremes({startTimestamp: fromTime, endTimestamp: toTime});
}
};
$(function () {
(function (H) {
H.wrap(H.RangeSelector.prototype, 'drawInput', function (proceed) {
var name = arguments[1],
merge = H.merge,
createElement = H.createElement,
PREFIX = 'highcharts-',
ABSOLUTE = 'absolute',
PX = 'px',
extend = H.extend,
pInt = H.pInt,
UNDEFINED;
//drawInput: function (name) {
var rangeSelector = this,
chart = rangeSelector.chart,
chartStyle = chart.renderer.style,
renderer = chart.renderer,
options = chart.options.rangeSelector,
defaultOptions = H.getOptions(),
lang = defaultOptions.lang,
div = rangeSelector.div,
isMin = name === 'min',
input,
label,
dateBox,
inputGroup = this.inputGroup;
// Create the text label
this[name + 'Label'] = label = renderer.label(lang[isMin ? 'rangeSelectorFrom' : 'rangeSelectorTo'], this.inputGroup.offset)
.attr({
padding: 2
})
.css(merge(chartStyle, options.labelStyle))
.add(inputGroup);
inputGroup.offset += label.width + 5;
// Create an SVG label that shows updated date ranges and and records click events that
// bring in the HTML input.
this[name + 'DateBox'] = dateBox = renderer.label('', inputGroup.offset)
.attr({
padding: 2,
width: options.inputBoxWidth || 90,
height: options.inputBoxHeight || 17,
stroke: options.inputBoxBorderColor || 'silver',
'stroke-width': 1
})
.css(merge({
textAlign: 'center',
color: '#444'
}, chartStyle, options.inputStyle))
.on('click', function () {
rangeSelector.showInput(name); // If it is already focused, the onfocus event doesn't fire (#3713)
rangeSelector[name + 'Input'].focus();
})
.add(inputGroup);
inputGroup.offset += dateBox.width + (isMin ? 10 : 0);
// Create the HTML input element. This is rendered as 1x1 pixel then set to the right size
// when focused.
this[name + 'Input'] = input = createElement('input', {
name: name,
className: PREFIX + 'range-selector',
type: 'text'
}, extend({
position: ABSOLUTE,
border: 0,
width: '1px', // Chrome needs a pixel to see it
height: '1px',
padding: 0,
textAlign: 'center',
fontSize: chartStyle.fontSize,
fontFamily: chartStyle.fontFamily,
top: chart.plotTop + PX // prevent jump on focus in Firefox
}, options.inputStyle), div);
// Blow up the input box
input.onfocus = function () {
rangeSelector.showInput(name);
};
// Hide away the input box
input.onblur = function () {
rangeSelector.hideInput(name);
};
// handle changes in the input boxes
input.onchange = function () {
var inputValue = input.value,
value = (options.inputDateParser || Date.parse)(inputValue),
xAxis = chart.xAxis[0],
dataMin = xAxis.dataMin,
dataMax = xAxis.dataMax;
// If the value isn't parsed directly to a value by the browser's Date.parse method,
// like YYYY-MM-DD in IE, try parsing it a different way
if (isNaN(value)) {
value = inputValue.split('-');
value = Date.UTC(pInt(value[0]), pInt(value[1]) - 1, pInt(value[2]));
}
if (!isNaN(value)) {
// Correct for timezone offset (#433)
if (!defaultOptions.global.useUTC) {
value = value + new Date().getTimezoneOffset() * 60 * 1000;
}
// Validate the extremes. If it goes beyound the data min or max, use the
// actual data extreme (#2438).
/* if (isMin) {
if (value > rangeSelector.maxInput.HCTime) {
value = UNDEFINED;
} else if (value < dataMin) {
value = dataMin;
}
} else {
if (value < rangeSelector.minInput.HCTime) {
value = UNDEFINED;
} else if (value > dataMax) {
value = dataMax;
}
}*/
// Set the extremes
if (value !== UNDEFINED) {
chart.xAxis[0].setExtremes(
isMin ? value : xAxis.min,
isMin ? xAxis.max : value,
UNDEFINED,
UNDEFINED, {
trigger: 'rangeSelectorInput'
});
}
}
};
//},
});
}(Highcharts));
/**
* Load new data depending on the selected min and max
*/
function afterSetExtremes(e) {
var chart = $('#container').highcharts();
chart.showLoading('Loading data from server...');
$.getJSON('http://www.highcharts.com/samples/data/from-sql.php?start=' + Math.round(e.min) +
'&end=' + Math.round(e.max) + '&callback=?', function (data) {
chart.series[0].setData(data);
chart.hideLoading();
});
}
// See source code from the JSONP handler at https://github.com/highslide-software/highcharts.com/blob/master/samples/data/from-sql.php
$.getJSON('http://www.highcharts.com/samples/data/from-sql.php?callback=?', function (data) {
// Add a null value for the end date
data = [].concat(data, [
[Date.UTC(2011, 9, 14, 19, 59), null, null, null, null]
]);
// create the chart
$('#container').highcharts('StockChart', {
chart: {
type: 'candlestick',
zoomType: 'x'
},
navigator: {
adaptToUpdatedData: false,
series: {
data: data
}
},
scrollbar: {
liveRedraw: false
},
title: {
text: 'AAPL history by the minute from 1998 to 2011'
},
subtitle: {
text: 'Displaying 1.7 million data points in Highcharts Stock by async server loading'
},
rangeSelector: {
buttons: [{
type: 'hour',
count: 1,
text: '1h'
}, {
type: 'day',
count: 1,
text: '1d'
}, {
type: 'month',
count: 1,
text: '1m'
}, {
type: 'year',
count: 1,
text: '1y'
}, {
type: 'all',
text: 'All'
}],
inputEnabled: true,
selected: 4 // all
},
xAxis: {
events: {
afterSetExtremes: afterSetExtremes
},
minRange: 3600 * 1000 // one hour
},
yAxis: {
floor: 0
},
series: [{
data: data,
dataGrouping: {
enabled: false
}
}]
});
});
});