我构建了一个类似于延迟加载示例(http://www.highcharts.com/stock/demo/lazy-loading)的图表,但是具有范围选择器的输入字段。 当我放大一切都很好。现在我想使用输入字段更改所选范围。 但是我无法将输入更改为超出缩放区域的值,尽管我的导航器中有更多数据可见。
在setExtremes函数中,我正在做一些计算:
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' }
);
}
}
};
(代码取自第21126行的highstock.src.js)
所以我无法将缩放扩展到当前活动选择之外,但导航器会显示更多数据。 有没有人知道如何设置超出当前缩放时间范围的日期?
我通过检查&#34; afterSetExtremes&#34;中的导航器范围来解决它。事件
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});
}
};
或者查看下面的解决方案并覆盖该方法。
答案 0 :(得分:1)
没有默认的API。通过覆盖drawInput函数(第二个代码片段)来扩展Highcharts。
您应该注释或删除一部分代码 - if
子句:
//验证极端情况。如果数据最小或最大,请使用
//实际数据极端(#2438)。
示例:http://jsfiddle.net/epL7awo4/1/
$(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
}
}]
});
});
});