【问题标题】:Update chart after every array plot, Highcharts在每个数组绘图后更新图表,Highcharts
【发布时间】:2019-11-07 06:41:48
【问题描述】:

我正在尝试从服务器端加载数据并在 Highcharts 中一一显示。

但在将它们显示在 Highchart 上之前,我正在对数据进行一些处理,然后将其渲染到 Highchart 中。

我正在使用 AJAX,这样我每次都可以获取数据,而无需刷新页面并重新加载图表。

图表对第一组数据运行良好,然后显示未定义,图表未显示任何下一组数据。

这里有我用来获取数据的 random.php 文件:

header("Content-type: text/json");

$data = [];
for($i=0; $i<500; $i++)
{
    $data[] = rand(0,10);  
}

$into_mysql = json_encode($data);

echo $into_mysql;

现在我正在其他页面的图表中获取数据:

var chart;
// Prototype to Request Data using `AJAX`
function requestData() {
    $.ajax({
        url: 'random.php',
        async: false,
        success: function (data) {
            y = data;
            console.log(y);
            return (y);
        }
    });
}


// Fetch the data from the `requestData` and process it.
function fetch() {
    requestData();
    var divisor = 2;
    var count = 0;
    for (var i = 0, length = y.length; i < length; i++) {
        y[i] /= divisor;
    }
    console.log(y);
    return (y);
    setInterval(function () { requestData }, 1000);
}

var json_array = fetch();

var i = 0;
function next() {

    return json_array[i++];
    // i++;

}

Highcharts.chart('container', {
    chart: {
        type: 'line',
        animation: Highcharts.svg, // don't animate in old IE
        marginRight: 10,
        events: {
            load: function () {

                // set up the updating of the chart each second
                var series = this.series[0],
                    chart = this;
                var count = 0;
                setInterval(function () {
                    var x = (new Date()).getTime(), // current time
                        y = next();
                    console.log(y);
                    series.addPoint([x, y], false, true);
                    chart.redraw(false);
                }, 1000 / 130);
            }
        }
    },

    time: {
        useUTC: false
    },

    title: {
        text: 'ECG Graph Plot From MySQl Data'
    },
    xAxis: {
        type: 'datetime',
        labels: {
            enabled: false
        },
        tickPixelInterval: 150
    },
    yAxis: {
        //max: 1.5,
        //min: -1.5,
        title: {
            text: 'Value'
        },
        plotLines: [{
            value: 0,
            width: 1,
            color: '#808080'
        }]
    },
    tooltip: {
        headerFormat: '<b>{series.name}</b><br/>',
        pointFormat: '{point.x:%Y-%m-%d %H:%M:%S}<br/>{point.y:.2f}'
    },
    legend: {
        enabled: false
    },
    exporting: {
        enabled: false
    },
    series: [{
        animation: false,
        name: 'ECG Graph Plot From MySQl Data',
        dataGrouping: {
            enabled: false
        },
        data: (function () {
            // generate an array of random data
            var data = [],
                time = (new Date()).getTime(),
                i;

            for (i = -1000; i <= 0; i += 1) {
                data.push([
                    time + i * 10,
                    null
                ]);
            }
            return data;
        }())
    }]
});   

所以我需要的是一个一个地渲染数据而不破坏它。当来自 random.php 的 One 数据集结束时。下一个数据应该继续那个开始。

更新:

假设每隔几秒就会生成一个包含 500 个数据的数组。我想要的是在一张高图中一一显示数组点。但只显示第一组数组数据,其余数组数据不显示。

【问题讨论】:

  • 你能在像 jsfiddle 这样的在线代码编辑器中重现你的问题吗?使用具有相同结构的假静态数据代替真实数据。请尽量准确地说明您将要实现的目标。
  • 我无法在在线代码编辑器中生成相同的内容。因为我每次都需要来自 AJAX 调用的数据。 @WojciechChmiel。
  • 我试图让问题更清楚。请参阅问题底部的更新部分
  • 这是您的代码的复制品:jsfiddle.net/BlackLabel/defm0qLc/1。您不需要 AJAX 使用静态数据和 setTimeout 来重现它。
  • 你这样做真是太好了 :) .. 现在根据你的小提琴,数组数据只在 Highcharts 上产生一次。现在我需要的是下一个数组数据应该在前一个数据的延续中打印。它只显示一个数组数据。我尝试了很多东西。但无法做到这一点。 @WojciechChmiel

标签: javascript php ajax highcharts


【解决方案1】:

我想我找到了解决您的代码的可能方法。首先,您当前的方法存在一些误解:

  • return 声明之后没有任何事情可以完成。是的,正如您在评论中指出的那样,在函数中执行 return 之后,什么都没有完成

  • 在您的高位图表中,您的数据取决于 json_array(基本上您读取数组的 X 元素),但实际上您从未更新 json_array 提供更多信息。

好的……我该怎么办?

让我们看看。首先,您应该确保在第一次获取后的某个时间间隔内获取数据。如何做到这一点:

function fetch() {
    requestData();
    var divisor = 2;
    var count = 0;
    for (var i = 0, length = y.length; i < length; i++) {
        y[i] /= divisor;
    }
    console.log(y);
    // Create the interval before returning, and actually calling the function
    setInterval(function () { requestData() }, 1000);
    return (y);
}

其次,您需要每个 requestData 更新您正在读取的数组: 免责声明,我正在使用您的 cmets 的 jsfiddle 创建一个简单的示例


  var json_array = fetch();

  function requestData() {
    var data = [];

    for (var i = 0; i < 500; i++) {
      data.push(Math.random() * 10);
    }

    y = data;

    // Check that json_array have been initialized and after add the data that we fetched in it (so from [1, 2, 3] to... [1, 2, 3, 4, 5, 6]
    if (Array.isArray(json_array)) {
      json_array = json_array.concat(data);
    }
  }

使用你的 ajax 代码应该是这样的

function requestData() {
    $.ajax({
        url: 'random.php',
        async: false,
        success: function (data) {
         /// you can skip this check... I just do it for safety
         if (Array.isArray(json_array)) {
           json_array = json_array.concat(data);
         }
        }
    });
}

基本上就是这样,只要您的请求比您在图表中读取 X 的速度更快,它应该可以正常工作。

I have here the working demo

额外 这不是必需的,因为在解决方案中我尝试尽可能少地修改您的代码,主要指出您的方法有什么问题,但我会考虑对您的代码进行下一步改进:

  • 在服务中提取抽象数据。基本上你可以创建一个类/原型,一旦你实例化它就会获取数据并继续获取数据并添加它
  • 该类还将检查您当前可以访问的数据索引数量,并为您提供下一个元素。
  • 修改您的 highcharts 以使用它。

这是实现的抽象

class DataFetcher {
constructor() {
   this.currentDataPoint = 0
   this.data = fetch(...)
   this.keepFetching()
}
keepFetching() {
   fetchMoreData().onSuccess((data) => { this.data = data }
}

getNext() {
   if (this.isThereData) {
// Return data point and increase pointer
     dataPoint = this.data[this.currentDataPoint]
     this.currentDataPoint =+ 1
     return dataPoint
   }
// Return nothing because there is no more data points
   return null
}

isThereData() { 
  return this.data.length >= this.currentDataPoint + 1
}

}

最后,您可以使用 map 函数抽象出这些数据的划分:

function fetch() {
    requestData();
    y = y.map(value => value/2);
    console.log(y);
    // Create the interval before returning, and actually calling the function
    setInterval(function () { requestData() }, 1000);
    return (y);
}

// Also the other function
function requestData() {
    var data = [];

    for (var i = 0; i < 500; i++) {
      data.push(Math.random() * 10);
    }

    y = data.map(dataPoint => dataPoint/2);

    // Check that json_array have been initialized and after add the data that we fetched in it (so from [1, 2, 3] to... [1, 2, 3, 4, 5, 6]
    if (Array.isArray(json_array)) {
      json_array = json_array.concat(data);
    }
  }

希望这可以帮助您完善您的解决方案!

【讨论】:

  • 哇。完美的解释和完成。我将实施您的方法,并会尽快回复您。
  • 只有一件事。除数不适用于第二组数据。
  • fetch()函数下的逻辑只调用一次。从下一次开始,它只显示随机数据而不除以 2。如 fetch()。
  • Opps,我会更新它,但它应该像在 for 循环中添加 /2 一样简单。希望对您有所帮助,如果可以,您可以将其标记为已解决
  • 是的,我可以在循环中手动将问题除以 2。但我希望自动调用 fetch 功能。但是,您提供的答案仍然非常完美。这就是为什么我将其标记为已解决。我感谢你的努力。 :)
猜你喜欢
  • 2020-03-16
  • 2016-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 2014-01-07
相关资源
最近更新 更多