ASE Home Page Products Download Purchase Support About ASE
ChartDirector Support
Forum HomeForum Home   SearchSearch

Message ListMessage List     Post MessagePost Message

  PHP Fullscreen Chart
Posted by Peter Schilling on Mar-17-2017 17:21
Hello Peter,

I am using ChartDirector 6.0 PHP-Edition.

in a new Project I face the Challenge of displaying a PHP Realtime-Line-Chart with Tracking abilities which should always be shown in fullscreen mode.

The closest demo is the realtimetrack.php.

Could you please give me a hint how to start?

Thank you,
Peter

  Re: PHP Fullscreen Chart
Posted by Peter Kwan on Mar-18-2017 05:46
Hi Peter,

Because in ChartDirector, the chart is rendered on the server side, so you would need to send the size you desired to the server (eg. as query parameters). The PHP charting code can then create the chart with the size you want.

For "fullscreen mode", I am not exactly sure if it means the full monitor size, or the full browser window size. In any case, your code would need to detect the size first, then send it to the server as parameters.

If the "fullscreen mode" refers to the monitor size, then the above is sufficient. If it refers to the browser window size, and you want to resize the chart size when the user resize the browser, then you would need to update the chart in the browser resize event too, which can be done with "partialUpdate". With "partialUpdate", you can pass the desired width and height as custom attributes (see WebChartViewer.getCustomAttr and JsChartViewer.setCustomAttr).

The above assumes you want to draw a more or less detail chart when the size chart, but not resizing the chart elements proportionally (eg. the font size may not changed). If you want to resize everything in the chart proportionally (just like resizing a photograph), you just need to use CSS to set the img size to 100% of the container, and ensure the container is 100% of the window size. For this type of resizing, you may start with an chart with more pixels, and let the browser resize it to fit smaller window.

Regards
Peter Kwan

  Re: PHP Fullscreen Chart
Posted by Peter Schilling on Mar-20-2017 15:21
Hello Peter,

thank you very much for the informations!

I managed it to react on the Browser resize event and get a the chart in the new browser dimension!
Our web-application runs in fullscreen-browser mode and we have to support monitors, tablets and mobile phones as well.

What I am absolutely insecure about is how to update the javascript data for the track line after resize.

Could you give me a short 'HOW TO', too?
This would be very nice!

Thank you in advance,
Peter

  Re: PHP Fullscreen Chart
Posted by Peter Schilling on Mar-20-2017 15:26
This is how I do the chart-redraw-request in the resize function:

function recalcLayout() {
        var url = "nnchart.php?w=" + window.innerWidth + "&h=" + window.innerHeight;
        document.getElementById('chartdiv').innerHTML="<img src="" + url + """>";
        console.log("URL: " + url);
}

  Re: PHP Fullscreen Chart
Posted by Peter Kwan on Mar-21-2017 04:29
Attachments:
Hi Peter,

As you mentioned that you need to have the "Realtime Chart with Track Line", I have attached an example modified from the original "Realtime Chart with Track Line".

Basically, you can update the chart using "partialUpdate", which is the same method that the code used to update the chart in realtime. The "partialUpdate" updates both the image and the track line.

In the original sample code, the chart is created initially and updated periodically using partialUpdate. In the modified code, the chart is not created initially. When the browser receives the HTML, the code will set up a "pre-update" handler to copy the window width and height to the custom attributes. Then it will perform a partialUpdate immediately. The effect is that the chart will display almost immediately after the HTML is received by the browser with a suitable size to fill the window.

Hope this can help.

Regards
Peter Kwan
realtimetrack.php
<?php
require_once("../lib/phpchartdir.php");

#
# Draw the chart
#
function drawChart(&$viewer) {
    #
    # 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 * 2.1) * 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.
	$width = $viewer->getCustomAttr("width") - 20;
	$height = max(200, $viewer->getCustomAttr("height") - 20);
	
    $c = new XYChart($width, $height, 0xf4f4f4, 0x000000, 0);
    $c->setRoundedFrame();

    # Set the plotarea at (55, 57) and of size 520 x 185 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, 57, $c->getWidth() - 80, $c->getHeight() - 90, 0xffffff, -1, -1, 0xcccccc, 0xcccccc);
    $c->setClipping();

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

    # Configure the y-axis with a 10pt Arial Bold axis title
    $c->yAxis->setTitle("Intensity (V/m)", "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, "Alpha");
    $layer->addDataSet($dataSeries2, 0x00cc00, "Beta");
    $layer->addDataSet($dataSeries3, 0x0000ff, "Gamma");

    # Output the chart
    $chartQuery = $c->makeSession($viewer->getId(), PNG);

    # Set the chart URL to the viewer
    $viewer->setImageUrl("getchart.php?".$chartQuery);

    # Output Javascript chart model to the browser to support tracking cursor
    $viewer->setChartModel($c->getJsChartModel());
}

#
# This script handles both the full page request, as well as the subsequent partial updates (AJAX
# chart updates). We need to determine the type of request first before we processing it.
#

# Create the WebChartViewer object
$viewer = new WebChartViewer("chart1");

if ($viewer->isPartialUpdateRequest()) {
    # Is a partial update request. Draw the chart and perform a partial response.
    drawChart($viewer);
    print($viewer->partialUpdateChart());
    exit();
}

?>
<!DOCTYPE html>
<html>
<head>
    <title>Realtime Chart with Track Line</title>
    <script type="text/javascript" src="cdjcv.js"></script>
</head>
<body style="margin:0px">
<script type="text/javascript">

//
// Execute the following initialization code after the web page is loaded
//
JsChartViewer.addEventListener(window, 'load', function() {
    var viewer = JsChartViewer.get('<?php echo $viewer->getId()?>');

    // Draw track cursor when mouse is moving over plotarea or if the chart is updated. In the latter case,
    // if the mouse is not on the plot area, we will update the legend to show the latest data values.
    viewer.attachHandler(["MouseMovePlotArea", "TouchStartPlotArea", "TouchMovePlotArea", "ChartMove",
        "PostUpdate", "Now"], function(e) {
        this.preventDefault(e);   // Prevent the browser from using touch events for other actions
		if (viewer.getChart())
			trackLineLegend(viewer, viewer.getPlotAreaMouseX());
    });

	viewer.attachHandler("PreUpdate", function() {
		viewer.setCustomAttr("width",  window.innerWidth - 170);
		viewer.setCustomAttr("height", window.innerHeight - 100);     
    });
	
	window.onresize = function () { viewer.partialUpdate(); }
        
    // When the chart is being updated, by default, an "Updating" box will pop up. In this example, we
    // will disable this box.
    viewer.updatingMsg = "";
	viewer.partialUpdate();
});

//
// Draw track line with legend
//
function trackLineLegend(viewer, mouseX)
{
    // Remove all previously drawn tracking object
    viewer.hideObj("all");

    // The chart and its plot area
    var c = viewer.getChart();
    var plotArea = c.getPlotArea();

    // Get the data x-value that is nearest to the mouse, and find its pixel coordinate.
    var xValue = c.getNearestXValue(mouseX);
    var xCoor = c.getXCoor(xValue);
    if (xCoor == null)
        return;

    // Draw a vertical track line at the x-position
    viewer.drawVLine("trackLine", xCoor, plotArea.getTopY(), plotArea.getBottomY(), "black 1px dotted");

    // Array to hold the legend entries
    var legendEntries = [];

    // Iterate through all layers to build the legend array
    for (var i = 0; i < c.getLayerCount(); ++i)
    {
        var layer = c.getLayerByZ(i);

        // The data array index of the x-value
        var xIndex = layer.getXIndexOf(xValue);

        // Iterate through all the data sets in the layer
        for (var j = 0; j < layer.getDataSetCount(); ++j)
        {
            var dataSet = layer.getDataSetByZ(j);

            // We are only interested in visible data sets with names, as they are required for legend entries.
            var dataName = dataSet.getDataName();
            var color = dataSet.getDataColor();
            if ((!dataName) || (color == null))
                continue;

            // Build the legend entry, consist of a colored square box, the name and the data value.
            var dataValue = dataSet.getValue(xIndex);
            legendEntries.push("<nobr>" + viewer.htmlRect(7, 7, color) + " " + dataName + ": " +
                ((dataValue == null) ? "N/A" : dataValue.toPrecision(4)) + viewer.htmlRect(20, 0) + "</nobr> ");

            // Draw a track dot for data points within the plot area
            var yCoor = c.getYCoor(dataSet.getPosition(xIndex), dataSet.getUseYAxis());
            if ((yCoor != null) && (yCoor >= plotArea.getTopY()) && (yCoor <= plotArea.getBottomY()))
            {
                viewer.showTextBox("dataPoint" + i + "_" + j, xCoor, yCoor, JsChartViewer.Center,
                    viewer.htmlRect(7, 7, color));
            }
        }
    }

    // Create the legend by joining the legend entries.
    var legend = "<nobr>[" + c.xAxis().getFormattedLabel(xValue, "hh:nn:ss") + "]" + viewer.htmlRect(20, 0) +
        "</nobr> " + legendEntries.reverse().join("");

    // Display the legend on the top of the plot area
    viewer.showTextBox("legend", plotArea.getLeftX(), plotArea.getTopY(), JsChartViewer.BottomLeft, legend,
        "width:" + plotArea.getWidth() + "px;font:bold 11px Arial;padding:3px;-webkit-text-size-adjust:100%;");
}

//
// Executes once every second to update the countdown display. Updates the chart when the countdown reaches 0.
//
function timerTick()
{
    // Get the update period and the time left
    var updatePeriod = parseInt(document.getElementById("UpdatePeriod").value);
    var timeLeft = Math.min(parseInt(document.getElementById("TimeRemaining").innerHTML), updatePeriod) - 1;

	var viewer = JsChartViewer.get('<?php echo $viewer->getId()?>');
	
    if (timeLeft == 0)
	    // Can update the chart now
		JsChartViewer.get('<?php echo $viewer->getId()?>').partialUpdate();
	else if (timeLeft < 0)
        // Reset the update period
        timeLeft += updatePeriod;

    // Update the countdown display
    document.getElementById("TimeRemaining").innerHTML = timeLeft;
}
window.setInterval("timerTick()", 1000);

</script>
<table cellspacing="0" cellpadding="0" border="0">
    <tr>
        <td align="right" colspan="2" style="background:#000088; color:#ffff00; padding:0px 4px 2px 0px;">
            <a style="color:#FFFF00; font:italic bold 10pt Arial; text-decoration:none" href="http://www.advsofteng.com/">
                Advanced Software Engineering
            </a>
        </td>
    </tr>
    <tr valign="top">
        <td style="width:150px; background:#c0c0ff; border-right:black 1px solid; border-bottom:black 1px solid;">
            <br />
            <br />
            <div style="font: 9pt Verdana; padding:10px;">
                <b>Update Period</b><br />
                <select id="UpdatePeriod" style="width:130px">
                    <option value="5">5</option>
                    <option value="10" selected="selected">10</option>
                    <option value="20">20</option>
                    <option value="30">30</option>
                    <option value="60">60</option>
                </select>
            </div>
            <div style="font:9pt Verdana; padding:10px;">
                <b>Time Remaining</b><br />
                <div style="width:128px; border:#888888 1px inset;">
                    <div style="margin:3px" id="TimeRemaining">0</div>
                </div>
            </div>
        </td>
        <td style="width:100%">
            <div style="font: bold 20pt Arial; margin:5px 0px 0px 5px;">
                Realtime Chart with Track Line
            </div>
            <hr style="border:solid 1px #000080" />
            <div style="padding:0px 5px 5px 10px;">
                <!-- ****** Here is the chart image ****** -->
                <?php echo $viewer->renderHTML()?>
            </div>
        </td>
    </tr>
</table>
</body>
</html>

  Re: PHP Fullscreen Chart
Posted by Peter Schilling on Mar-21-2017 16:00
Hello Peter,

thank you so much! :)

I will test it as soon as possible! Today I have to focus on the app-framework and the GUI.

I will inform you if I got familiar with your code ;)

Greetings,
Peter

  Re: PHP Fullscreen Chart
Posted by Peter Schilling on Mar-21-2017 20:35
Hello Peter,

I now face another Problem wich I can't solve.

In the php-code I use the function makeChart($filename); and it always return 1.
But the file is never created?

I got write access to the directory!

What do I miss to create the chart image in the filesystem?

This is the whole code:

        $data = array(85, 156, 179.5, 211, 123);

        # The labels for the bar chart
        $labels = array("Mon", "Tue", "Wed", "Thu", "Fri");

        # Create a XYChart object of size 250 x 250 pixels
        $c = new XYChart(250, 250);

        # Set the plotarea at (30, 20) and of size 200 x 200 pixels
        $c->setPlotArea(30, 20, 200, 200);

        # Add a bar chart layer using the given data
        $c->addBarLayer($data);

        # Set the labels on the x axis.
        $c->xAxis->setLabels($labels);

        $f = fopen("./test.txt", "w");
        fwrite($f, "dsfsdf");
        fclose($f);
        # Output the chart
        $filename = "./c_$cId.PNG";
        if( file_exists($filename)) {
            unlink($filename);
        }

        $ret = $c->makeChart($filename);
        if( $ret == 0 ) {
            echo "Failed creating chart $filename!";
        }
        else {
            echo "Chart $filename created!! ($ret) ";
        }

        echo "<img src="$filename">n";

  Re: PHP Fullscreen Chart
Posted by Peter Schilling on Mar-21-2017 20:48
Ok, forget about the last post.

I managed to save the chart image to file this way:

        # Output the chart
        $filename = "./c_$cId.png";
        if( file_exists($filename)) {
            unlink($filename);
        }

        $f = fopen($filename, "w");
        $fContent= $c->makeChart2(PNG);
        fwrite($f, $fContent);
        fclose($f);

But still strange that the makeChart function returns 1 and creates no image?!

  Re: PHP Fullscreen Chart
Posted by Peter Kwan on Mar-22-2017 00:45
Hi Peter,

I suspect the reason is that the filename that you specify means different things to ChartDirector and PHP fopen.

ChartDirector makeChart uses file system path, which is the path you use to address your file system. It is relative to the "current working directory" of the running process, which is not necessarily the same as the directory of the script. (In PHP, the current working directory can be obtained by using the getcwd function.)

According to PHP documentation, the PHP fopen assumes the path to be a URL path, not file system path. It may resolve it by assuming the path is relative to the current URL path (the URL path of the script), which may not be the same as the current working directory. In some cases (but not in your case), the URL path can be subjected to virtual directory mapping. So the URL path can be different from a file system path.

If is possible ChartDirector does create a chart image but is the current working directory, but is not the same as the current URL directory.

If you prefer to use a file system path relative to the current script, you may use:

$filename = dirname(__FILE__)."/c_$cId.png"

Regards
Peter Kwan

  Re: PHP Fullscreen Chart
Posted by peter.schilling@xapi.de on Mar-22-2017 02:13
Hello Peter,

but why is the function returning 1 for making me think the chart image file has been created?

I searched the whole htdocs directory and the file is nowhere created, doesn't matter in what form I give the filename!?

The documentation is not very clear at this point :(

But with my workaround I got my charts created in the filesystem..

Greetings,
peter

  Re: PHP Fullscreen Chart
Posted by Peter Kwan on Mar-22-2017 14:44
Hi Peter,

I suspect the file was created in the "current working directory", so it returned 1. The "current working directory" may not be inside the "htdocs". It can be the directory of your PHP executable, or Apache executable or some other directory, depending on many factors (your OS, Apache/PHP version and type, your system configuration, ...).

In fact, the advantage of using file system path is that you can save outside the "htdocs". In some application, it is desirable to save the file in temporary directories (eg. /tmp), or directories not accessible by any arbitrary web user (that is, not in the htdocs).

The file system path is different from the URL path. For example "/aaa.png" means a file at the root of the hard disk, not the root of htdocs. The relative path can be relative to different directories, and the file system path does not have virtual directory mappings.

As the "current working directory" is hard to predict, in our own sample code, we always use "absolute path". The "absolute path" of the running script is __FILE__, so the absolute path can be dynamically created using the code in my previous message. In PHP, there is also a function "realpath" that can return the "real path" (the absolute file system path) give a URL path. See:

http://php.net/manual/en/function.realpath.php

May be you can check if the file is created in other directories in your hard disk.

Regards
Peter Kwan

  Re: PHP Fullscreen Chart
Posted by Peter Schilling on Mar-22-2017 16:07
Hello Peter,

you are right as usual :)

I found the images created in the apache main folder!

So I can go back to the makeChart function.

Thank you very much again.

Greetings from Germany,
Peter