ChartDirector Ver 5.0 (PHP Edition)

Realtime Chart Demonstration




This sample program demonstrates a realtime chart with configurable chart update rate. The chart is being updated without the entire page refreshing.

The code consists of two parts - the containing web page and the charting page.

The containing web page is in HTML, with an <IMG> tag for displaying the chart. A browser side Javascript periodically refreshes the <IMG> tag. This causes new requests to the charting page, which will return updated charts. So the chart appears to update in periodically.

The container web page can easily be implemented using standard browser side Javascript without any third party library at all. However, in this example, we demonstrate using the JsChartViewer library for refreshing the <IMG>, as it offers several advantages like double buffering (to avoid flickering), handling of overlapping updates, better error handling and cache avoidance. See JsChartViewer.streamUpdate for more details.

NOTE: This sample script uses "cdjcv.js". When developing your own script using this sample code as a template, please ensure you copy "cdjcv.js" to the proper directory and reference it using the proper path.

Source Code Listing

[File: phpdemo/realtimedemo.php]
<html>
<head>
    <title>ChartDirector Realtime Chart Demonstration</title>
    <script type="text/javascript" src="cdjcv.js"></script>
</head>
<body style="margin:0px">
<table cellspacing="0" cellpadding="0" border="0">
    <tr>
        <td align="right" colspan="2" style="background:#000088">
            <div style="padding-bottom:2px; padding-right:3px; font-weight:bold; font-size:10pt; font-style:italic; font-family:Arial;">
                <a style="color:#FFFF00; text-decoration:none" href="http://www.advsofteng.com/">Advanced Software Engineering</a>
            </div>
        </td>
    </tr>
    <tr valign="top">
        <td style="width:150px; background:#c0c0ff; border-left:black 1px solid; border-right:black 1px solid; border-bottom:black 1px solid;">
            <br /><br />
            <div style="padding:10px; font-size:9pt; font-family:Verdana">
                <b>Update Period</b><br />
                <select id="UpdatePeriod" style="width:130px">
                    <option value="5">5 seconds</option>
                    <option value="10" selected="selected">10 seconds</option>
                    <option value="20">20 seconds</option>
                    <option value="30">30 seconds</option>
                    <option value="60">60 seconds</option>
                </select>
            </div>
            <div style="padding:10px; font-size:9pt; font-family:Verdana">
                <b>Time Remaining</b><br />
                <div style="width:130px; border:#888888 1px inset;">
                    <div style="margin:3px" id="TimeRemaining"> </div>
                </div>
            </div>
        </td>
        <td>
            <div style="font-weight:bold; font-size:20pt; margin:5px 0px 0px 5px; font-family:Arial">
                ChartDirector Realtime Chart Demonstration
            </div>
            <hr style="border:solid 1px #000080" />
            <div style="padding:0px 5px 0px 10px">
                <!-- ****** Here is the image tag for the chart image ****** -->
                <img id="ChartImage1" src="realtimechart.php?chartId=demoChart1">
            </div>
        </td>
    </tr>
</table>
<script type="text/javascript">
// The followings is executed once every second
function updateDisplay()
{
    // Utility to get an object by id that works with most browsers
    var getObj = function(id) {    return document.getElementById ? document.getElementById(id) : document.all[id]; }

    // Get the configured update period
    var updatePeriodObj = getObj("UpdatePeriod");
    var updatePeriod = parseInt(updatePeriodObj.value);

    // Subtract 1 second for the remaining time - reload the counter if remaining time is 0
    if (!updatePeriodObj.timeLeft || (updatePeriodObj.timeLeft <= 0))
        updatePeriodObj.timeLeft = updatePeriod - 1;
    else
        updatePeriodObj.timeLeft = Math.min(updatePeriod, updatePeriodObj.timeLeft) - 1;

    // Update the chart if configured time has elasped
    if ((updatePeriodObj.timeLeft <= 0) && window.JsChartViewer)
        JsChartViewer.get('ChartImage1').streamUpdate();

    // Update the display to show remaining time
    getObj("TimeRemaining").innerHTML = updatePeriodObj.timeLeft + ((updatePeriodObj.timeLeft > 1) ? " seconds" : " second");
}
window.setInterval("updateDisplay()", 1000);
</script>
</body>
</html>

[File: phpdemo/realtimechart.php]
<?php
require_once("../lib/phpchartdir.php");

#
# Data to draw the chart. In this demo, the data buffer will be filled by a random
# data generator. In real life, the data is probably stored in a buffer (eg. a
# database table, a text file, or some global memory) and updated by other means.
#

# We use a data buffer to emulate the last 240 samples.
$sampleSize = 240;
$dataSeries1 = array_pad(array(), $sampleSize, 0);
$dataSeries2 = array_pad(array(), $sampleSize, 0);
$dataSeries3 = array_pad(array(), $sampleSize, 0);
$timeStamps = array_pad(array(), $sampleSize, 0);

# Our pseudo random number generator
$firstDate = chartTime2(time()) - count($timeStamps);
for($i = 0; $i < count($timeStamps); ++$i) {
    $p = $firstDate + $i;
    $timeStamps[$i] = $p;
    $dataSeries1[$i] = cos($p * 7 * 18463) * 10 + 1 / (cos($p) * cos($p) + 0.01) + 20
        ;
    $dataSeries2[$i] = 100 * sin($p / 27.7) * sin($p / 10.1) + 150;
    $dataSeries3[$i] = 100 * cos($p / 6.7) * cos($p / 11.9) + 150;
}

# Create an XYChart object 600 x 270 pixels in size, with light grey (f4f4f4)
# background, black (000000) border, 1 pixel raised effect, and with a rounded frame.
$c = new XYChart(600, 270, 0xf4f4f4, 0x000000, 0);
$c->setRoundedFrame();

# Set the plotarea at (55, 62) and of size 520 x 175 pixels. Use white (ffffff)
# background. Enable both horizontal and vertical grids by setting their colors to
# grey (cccccc). Set clipping mode to clip the data lines to the plot area.
$c->setPlotArea(55, 62, 520, 175, 0xffffff, -1, -1, 0xcccccc, 0xcccccc);
$c->setClipping();

# Add a title to the chart using 15 pts Times New Roman Bold Italic font, with a
# light grey (dddddd) background, black (000000) border, and a glass like raised
# effect.
$textBoxObj = $c->addTitle("Zooming and Scrolling Demonstration", "timesbi.ttf", 15);
$textBoxObj->setBackground(0xdddddd, 0x000000, glassEffect());

# Add a legend box at the top of the plot area with 9pts Arial Bold font. We set the
# legend box to the same width as the plot area and use grid layout (as opposed to
# flow or top/down layout). This distributes the 3 legend icons evenly on top of the
# plot area.
$b = $c->addLegend2(55, 33, 3, "arialbd.ttf", 9);
$b->setBackground(Transparent, Transparent);
$b->setWidth(520);

# Configure the y-axis with a 10pts Arial Bold axis title
$c->yAxis->setTitle("Price (USD)", "arialbd.ttf", 10);

# Configure the x-axis to auto-scale with at least 75 pixels between major tick and
# 15 pixels between minor ticks. This shows more minor grid lines on the chart.
$c->xAxis->setTickDensity(75, 15);

# Set the axes width to 2 pixels
$c->xAxis->setWidth(2);
$c->yAxis->setWidth(2);

# Set the x-axis label format
$c->xAxis->setLabelFormat("{value|hh:nn:ss}");

# Create a line layer to plot the lines
$layer = $c->addLineLayer2();

# The x-coordinates are the timeStamps.
$layer->setXData($timeStamps);

# The 3 data series are used to draw 3 lines. Here we put the latest data values as
# part of the data set name, so you can see them updated in the legend box.
$layer->addDataSet($dataSeries1, 0xff0000, $c->formatValue($dataSeries1[count(
    $dataSeries1) - 1], "Software: <*bgColor=FFCCCC*> {value|2} "));
$layer->addDataSet($dataSeries2, 0x00cc00, $c->formatValue($dataSeries2[count(
    $dataSeries2) - 1], "Hardware: <*bgColor=CCFFCC*> {value|2} "));
$layer->addDataSet($dataSeries3, 0x0000ff, $c->formatValue($dataSeries3[count(
    $dataSeries3) - 1], "Services: <*bgColor=CCCCFF*> {value|2} "));

# Output the chart
header("Content-type: image/png");
print($c->makeChart2(PNG));
?>