|
|
@@ -41,7 +41,9 @@ export default class StockHeatmap extends React.Component {
|
|
|
windowedData = [];
|
|
|
windowLength = 20;
|
|
|
windowPosition = 0;
|
|
|
- isMerged = false;
|
|
|
+ isMerged = false; // 是否合并了
|
|
|
+ isMerge = false; // 是否启用合并
|
|
|
+ symbol = 'None'
|
|
|
|
|
|
// 鼠标坐标
|
|
|
mouse = {
|
|
|
@@ -55,8 +57,8 @@ export default class StockHeatmap extends React.Component {
|
|
|
// 最大的买卖数量
|
|
|
maxBidAskVolume = 0;
|
|
|
|
|
|
- // 绘制间隔,120是帧率
|
|
|
- drawTimestampDistance = parseInt(1000 / 120);
|
|
|
+ // 绘制间隔,60是帧率
|
|
|
+ drawTimestampDistance = parseInt(1000 / 60);
|
|
|
// 上次绘制时间
|
|
|
prevDrawTimestamp = 0;
|
|
|
|
|
|
@@ -479,12 +481,21 @@ export default class StockHeatmap extends React.Component {
|
|
|
this.drawingContext.textAlign = 'left';
|
|
|
this.drawingContext.font = '12px Arial';
|
|
|
|
|
|
- let zoomLevelText = `当前视域: ${zoomTimeFormat(this.windowLength)}`
|
|
|
- this.drawingContext.fillText(zoomLevelText, 20, this.defaults.axisTickSize + this.defaults.xAxisTextPadding + 20);
|
|
|
- let w = this.drawingContext.measureText(zoomLevelText).width;
|
|
|
+ // ========================================= 底部文字绘制 =========================================
|
|
|
+ // 绘制品种
|
|
|
+ let symbol = this.symbol
|
|
|
+ let symbolText = `品种: ${symbol}`
|
|
|
+ this.drawingContext.fillText(symbolText, 5, this.defaults.axisTickSize + this.defaults.xAxisTextPadding + 20);
|
|
|
+ let w = this.drawingContext.measureText(symbolText).width;
|
|
|
+
|
|
|
+ // 绘制视域
|
|
|
+ let zoomLevelText = `当前视域: ${zoomTimeFormat(this.windowedData)} `
|
|
|
+ this.drawingContext.fillText(zoomLevelText, 20 + w + 20, this.defaults.axisTickSize + this.defaults.xAxisTextPadding + 20);
|
|
|
+ w += this.drawingContext.measureText(zoomLevelText).width;
|
|
|
const maxVolumeInWindowData = extractMaxTradedVolume(this.windowedData);
|
|
|
|
|
|
- const maxVolumeText = `最近${zoomTimeFormat(this.windowLength, 1)}内最大交易量: `;
|
|
|
+ // 绘制最大交易量
|
|
|
+ const maxVolumeText = `最近${zoomTimeFormat(this.windowedData)}内最大交易量: `;
|
|
|
this.drawingContext.fillText(maxVolumeText, 20 + w + 20, this.defaults.axisTickSize + this.defaults.xAxisTextPadding + 20);
|
|
|
this.drawingContext.fillStyle = this.defaults.textHighlightOnBackground;
|
|
|
w += this.drawingContext.measureText(maxVolumeText).width;
|
|
|
@@ -492,6 +503,7 @@ export default class StockHeatmap extends React.Component {
|
|
|
this.drawingContext.fillText(`${maxVolumeInWindowData}`, 20 + w + 20, this.defaults.axisTickSize + this.defaults.xAxisTextPadding + 20);
|
|
|
w += this.drawingContext.measureText(`${maxVolumeInWindowData}`).width;
|
|
|
|
|
|
+ // 最后交易数据的绘制
|
|
|
let latested = this.windowedData[this.windowedData.length - 1]
|
|
|
if (this.windowedData.length > 0) {
|
|
|
this.drawingContext.fillStyle = this.defaults.textOnBackground;
|
|
|
@@ -1038,12 +1050,15 @@ export default class StockHeatmap extends React.Component {
|
|
|
// move position only if within valid range
|
|
|
this.windowedData = this.data.slice(position, position + this.windowLength + 1);
|
|
|
|
|
|
- // if (this.windowedData.length > 1000) {
|
|
|
- // this.windowedData = this.mergeWindowedData();
|
|
|
- // this.isMerged = true;
|
|
|
- // } else {
|
|
|
- // this.isMerged = false;
|
|
|
- // }
|
|
|
+ // 是否启用合并
|
|
|
+ if (this.isMerge) {
|
|
|
+ if (this.windowedData.length > 1000) {
|
|
|
+ this.windowedData = this.mergeWindowedData();
|
|
|
+ this.isMerged = true;
|
|
|
+ } else {
|
|
|
+ this.isMerged = false;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// 延迟日志
|
|
|
if (this.windowedData.length > 1) {
|
|
|
@@ -1067,10 +1082,27 @@ export default class StockHeatmap extends React.Component {
|
|
|
* @param {number} zoom The seconds to zoom into
|
|
|
*/
|
|
|
setZoomLevel = (zoom) => {
|
|
|
- let l = Math.min(Math.max(zoom * 4, 3), this.data.length - 1);
|
|
|
- let l2 = this.windowLength - l;
|
|
|
- this.windowLength = l;
|
|
|
- this.moveDataWindow(this.windowPosition + l2);
|
|
|
+ if (this.data.length == 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ let theoreticalWindowDataLength = 0; // 理论数据条数
|
|
|
+ let zoomMillsTimestamp = zoom * 1000;
|
|
|
+
|
|
|
+ let firstIndex = Math.min(this.data.length - 1, this.windowPosition + this.windowLength)
|
|
|
+ let first = this.data[firstIndex]
|
|
|
+ for (let i = firstIndex; i >= 0; i--) {
|
|
|
+ let d = this.data[i]
|
|
|
+ if (first.time - d.time > zoomMillsTimestamp) {
|
|
|
+ break
|
|
|
+ }
|
|
|
+
|
|
|
+ theoreticalWindowDataLength += 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ this.windowLength = Math.max(3, theoreticalWindowDataLength - 1);
|
|
|
+ let pos = Math.max(0, firstIndex - this.windowLength - 1)
|
|
|
+ this.moveDataWindow(pos);
|
|
|
}
|
|
|
|
|
|
/**
|