Monday, April 30, 2012

Creating Android Charts with HTML/Javascript : RGraph


Creating Android Charts with HTML/Javascript : RGraph

Dont think this warrants a separate page, but here it is in any case.
NOTE to self:
RGraph uses the HTML5 Canvas component, which is NOT accommodated in the webkit packaged with Android 1.5. RGraph will works nicely and tested with Android 2.1 and 2.2.
Steps involved:
  1. Create an assets directory for HTML files – Android internally maps it to file:///android_asset/ (note singular asset)
  2. Copy rgraphview.html into it: res/assets/rgraphview.html
  3. Create a javascript directory: res/assets/RGraph
Some notes:
  • Ability to interaction with the plot/chart via Javascript  by checking data series
Note: As you guys/gals may have noticed, the data values are hard-coded..(naughty naughty naughty). This was done to keep things simple as possible. Ideally the data would come from a data source/content provider such as SQLite or Web service. I like the Active Record approach and will provide some details in my next article on doing Active Record for Android android-active-record


File: rgraphview.html

<html>
<head>
<title>RGraph: HTML5 canvas graph library - pie chart</title>

    <script src="RGraph/libraries/RGraph.common.core.js" ></script>
    <script src="RGraph/libraries/RGraph.common.annotate.js" ></script>
    <script src="RGraph/libraries/RGraph.common.context.js" ></script>
    <script src="RGraph/libraries/RGraph.common.tooltips.js" ></script>
    <script src="RGraph/libraries/RGraph.common.zoom.js" ></script>
    <script src="RGraph/libraries/RGraph.common.resizing.js" ></script>
    <script src="RGraph/libraries/RGraph.pie.js" ></script>

  <script>
        window.onload = function ()
        {
            /**
            * These are not angles - these are values. The appropriate angles are calculated
            */
            var pie1 = new RGraph.Pie('pie1', [41,37,16,3,3]); // Create the pie object
            pie1.Set('chart.labels', ['MSIE 7 (41%)', 'MSIE 6 (37%)', 'Firefox (16%)', 'Safari (3%)', 'Other (3%)']);
            pie1.Set('chart.gutter', 30);
            pie1.Set('chart.title', "Browsers (tooltips, context, zoom)");
            pie1.Set('chart.shadow', false);
            pie1.Set('chart.tooltips.effect', 'contract');
            pie1.Set('chart.tooltips', [
                                        'Internet Explorer 7 (41%)',
                                        'Internet Explorer 6 (37%)',
                                        'Mozilla Firefox (16%)',
                                        'Apple Safari (3%)',
                                        'Other (3%)'
                                       ]
                                      );
            pie1.Set('chart.highlight.style', '3d'); // Defaults to 3d anyway; can be 2d or 3d

            if (!RGraph.isIE8()) {
                pie1.Set('chart.zoom.hdir', 'center');
                pie1.Set('chart.zoom.vdir', 'up');
                pie1.Set('chart.labels.sticks', true);
                pie1.Set('chart.labels.sticks.color', '#aaa');
                pie1.Set('chart.contextmenu', [['Zoom in', RGraph.Zoom]]);
            }

            pie1.Set('chart.linewidth', 5);
            pie1.Set('chart.labels.sticks', true);
            pie1.Set('chart.strokestyle', 'white');
            pie1.Draw();

            var pie2 = new RGraph.Pie('pie2', [2,29,45,17,7]); // Create the pie object
            pie2.Set('chart.gutter', 45);
            pie2.Set('chart.title', "Some data (context, annotatable)");
            pie2.Set('chart.linewidth', 1);
            pie2.Set('chart.strokestyle', '#333');
            pie2.Set('chart.shadow', true);
            pie2.Set('chart.shadow.blur', 3);
            pie2.Set('chart.shadow.offsetx', 3);
            pie2.Set('chart.shadow.offsety', 3);
            pie2.Set('chart.shadow.color', 'rgba(0,0,0,0.5)');
            pie2.Set('chart.colors', ['red', 'pink', '#6f6', 'blue', 'yellow']);
            pie2.Set('chart.contextmenu', [['Clear', function () {RGraph.Clear(pie2.canvas); pie2.Draw();}]]);
            pie2.Set('chart.key', ['John (2%)', 'Richard (29%)', 'Fred (45%)', 'Brian (17%)', 'Peter (7%)']);
            pie2.Set('chart.key.background', 'white');
            pie2.Set('chart.key.shadow', true);
            pie2.Set('chart.annotatable', true);
            pie2.Set('chart.align', 'left');
            pie2.Draw();
        }
    </script>
</head>
<body>

    <div style="text-align: center">
        <canvas id="pie1" width="420" height="300">[No canvas support]</canvas>
        <canvas id="pie2" width="440" height="300">[No canvas support]</canvas>
    </div>

</body>
</html>




File: main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:orientation="horizontal"
 android:layout_width="fill_parent"
 android:layout_height="fill_parent"
 android:background="#FFFFFF">

 <WebView
  android:id="@+id/webview"
  android:layout_width="fill_parent"
  android:layout_height="fill_parent">
 </WebView>
</LinearLayout>


File: Main.java

import android.app.Activity;
import android.os.Bundle;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

public class Main extends Activity
 {

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState)
   {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    WebView webview = (WebView) this.findViewById(R.id.webview);
    WebSettings webSettings = webview.getSettings();
    webSettings.setJavaScriptEnabled(true);
    webSettings.setBuiltInZoomControls(true);
    webview.requestFocusFromTouch();
    webview.setWebViewClient(new WebViewClient());
    webview.setWebChromeClient(new WebChromeClient());

    // Load the URL
    webview.loadUrl("file:///android_asset/rgraphview.html");
   }

 }

No comments: