一、什么是ichartjs?
ichartjs 是一款基于HTML5的图形库。使用纯javascript语言, 利用HTML5的canvas标签绘制各式图形。 ichartjs致力于为您的应用提供简单、直观、可交互的体验级图表组件。是WEB/APP图表展示方面的解决方案 。如果你正在开发HTML5的应用,ichartjs正好适合您。 ichartjs目前支持饼图、环形图、折线图、面积图、柱形图、条形图。ichartjs是基于Apache License 2.0协议的开源项目。
二、如何使用ichartjs?
在你的html页面中,添加如下javascript引用即可:
<script type="text/javascript" src="ichart.1.2.min.js"></script>
三、ichartjs在Android中的应用
了解过WebApp开发的童鞋应该都知道,Android平台应用开发的另外一种方式,使用WebView加载HTML页面,在HTML页面中实现我们的功能和界面开发,那么Android代码和HTML代码交互就通过JavaScript来实现。ichartjs的使用也是这一套路线。
下面以一个ichartjs的3D柱状图的demo来讲解它在Android中的应用。
首先定义好需要的实体:
package com.example.achartdemo.beans; public class Contact { private String name; // 浏览器的名称 private double value; // 浏览器对应的所占市场份额值 private String color; // 在柱形图中所显示的颜色 /** * 构造函数 * @param name 浏览器的名称 * @param value 浏览器对应的所占市场份额值 * @param color 在柱形图中所显示的颜色 */ public Contact(String name, double value, String color) { this.name = name; this.value = value; this.color = color; } // 下面是三个实例变量的getters and setters public String getName() { return name; } public void setName(String name) { this.name = name; } public double getValue() { return value; } public void setValue(double value) { this.value = value; } public String getColor() { return color; } public void setColor(String color) { this.color = color; } }
然后模拟http请求加载数据的过程:
package com.example.achartdemo.http; import java.util.ArrayList; import java.util.List; import com.example.achartdemo.beans.Contact; public class ContactService { public List<Contact> getContacts() { List<Contact> contacts = new ArrayList<Contact>(); contacts.add(new Contact("IE", 32.85, "#a5c2d5")); contacts.add(new Contact("Chrome", 33.59, "#cbab4f")); contacts.add(new Contact("Firefox", 22.85, "#76a871")); contacts.add(new Contact("Safari", 7.39, "#9f7961")); contacts.add(new Contact("Opera", 1.63, "#a56f8f")); contacts.add(new Contact("Other", 1.69, "#6f83a5")); return contacts; } }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.achartdemo.MainActivity$PlaceholderFragment" > <WebView android:id="@+id/webview" android:layout_width="match_parent" android:layout_height="match_parent"/> </RelativeLayout>
package com.example.achartdemo; import android.annotation.SuppressLint; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.support.v4.app.Fragment; import android.support.v7.app.ActionBarActivity; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.webkit.WebSettings; import android.webkit.WebView; public class MainActivity extends ActionBarActivity { private static Context mContext; private static Handler mHandler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContext = this; if (savedInstanceState == null) { getSupportFragmentManager().beginTransaction() .add(R.id.container, new PlaceholderFragment()).commit(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } /** * A placeholder fragment containing a simple view. */ public static class PlaceholderFragment extends Fragment { private WebView mWebView; public PlaceholderFragment() { } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_main, container, false); initView(rootView); return rootView; } @SuppressLint({ "SetJavaScriptEnabled", "JavascriptInterface" }) private void initView(View rootView) { mWebView = (WebView) rootView.findViewById(R.id.webview); mWebView.setHorizontalScrollBarEnabled(true); mWebView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET); WebSettings settings = mWebView.getSettings(); settings.setDefaultTextEncodingName("UTF-8"); settings.setJavaScriptEnabled(true); settings.setSupportZoom(true); settings.setBuiltInZoomControls(true); mWebView.addJavascriptInterface(new JSInterface(mContext, mHandler, mWebView), JSInterface.TAG); String url = "file:///android_asset/index.html"; mWebView.loadUrl(url); } } }
关键的代码是我们需要在WebView中展现的HTML页面,代码如下:
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title>Hello World</title> <meta name="viewport" content="width=device-width, user-scalable=no" target-densitydpi="device-dpi"/> <meta name="Description" content="" /> <meta name="Keywords" content="" /> <script type="text/javascript" src="ichart.1.2.min.js"></script> <script type="text/javascript"> var data = new Array(); var contact = window.JSInterface.getContacts(); //得到JSInterface中转换出的json字符串 eval(‘data=‘+contact); //得到json数据 $(function(){ new iChart.Column3D({ render : ‘canvasDiv‘, //渲染的Dom目标,canvasDiv为Dom的ID data: data, //绑定数据 title : ‘Top 5 Browsers in August 2012‘, //设置标题 showpercent:true, //显示百分比 decimalsnum:2, width : 600, //设置宽度,默认单位为px height : 300, //设置高度,默认单位为px align:‘left‘, offsetx:50, animation : true,//开启过渡动画 duration_animation_duration:800,//800ms完成动画 legend : { enable : true }, coordinate:{ //配置自定义坐标轴 scale:[{ //配置自定义值轴 width:600, position:‘left‘, //配置左值轴 start_scale:0, //设置开始刻度为0 end_scale:40, //设置结束刻度为40 scale_space:8, //设置刻度间距为8 listeners:{ //配置事件 parseText:function(t,x,y){ //设置解析值轴文本 return {text:t+"%"} } } }] } }).draw(); //调用绘图方法开始绘图 }); </script> </head> <body> <div id=‘canvasDiv‘></div> </body> </html>
刚才在Activity中引用的JSInterface类,是我们用来跟HTML页面进行数据交互的JS接口类,代码如下:
package com.example.achartdemo; import java.util.List; import java.util.Random; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import android.annotation.SuppressLint; import android.content.Context; import android.os.Handler; import android.util.Log; import android.webkit.WebView; import android.widget.Toast; import com.example.achartdemo.beans.Contact; import com.example.achartdemo.http.ContactService; public class JSInterface { public static final String TAG = JSInterface.class.getSimpleName(); private Context mContext = null; private Handler mHandler = null; private WebView mView; private JSONArray jsonArray = new JSONArray(); private Random random = new Random(); public JSInterface(Context context, Handler handler, WebView webView) { mContext = context; mHandler = handler; mView = webView; } public void init() { // 通过handler来确保init方法的执行在主线程中 mHandler.post(new Runnable() { public void run() { // 调用网页setContactInfo方法 mView.loadUrl("javascript:setContactInfo(‘" + getJsonStr() + "‘)"); } }); } public int getW() { return px2dip(mContext.getResources().getDisplayMetrics().widthPixels); } public int getH() { return px2dip(mContext.getResources().getDisplayMetrics().heightPixels); } public int px2dip(float pxValue) { final float scale = mContext.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } public void setValue(String name, String value) { Toast.makeText(mContext, name+" "+value+"%", Toast.LENGTH_SHORT).show(); } @SuppressLint("DefaultLocale") public String getRandColorCode() { String r, g, b; Random random = new Random(); r = Integer.toHexString(random.nextInt(256)).toUpperCase(); g = Integer.toHexString(random.nextInt(256)).toUpperCase(); b = Integer.toHexString(random.nextInt(256)).toUpperCase(); r = r.length() == 1 ? "0" + r : r; g = g.length() == 1 ? "0" + g : g; b = b.length() == 1 ? "0" + b : b; return "#" + r + g + b; } public String getJsonStr() { try { for (int i = 0; i < 10; i++) { JSONObject object1 = new JSONObject(); object1.put("name", "name" + i); object1.put("value", random.nextInt(30)); object1.put("color", getRandColorCode()); jsonArray.put(object1); } Log.i("", jsonArray.toString()); return jsonArray.toString(); } catch (JSONException e) { e.printStackTrace(); } return null; } /** * 实现将list转换成json格式字符串 * @return json格式的字符串 */ public String getContacts() { ContactService contactService = new ContactService(); List<Contact> contacts = contactService.getContacts(); String json = null; try { JSONArray array = new JSONArray(); for (Contact contact : contacts) { JSONObject item = new JSONObject(); item.put("name", contact.getName()); item.put("value", contact.getValue()); item.put("color", contact.getColor()); array.put(item); } json = array.toString(); Log.i(TAG, json); } catch (JSONException e) { e.printStackTrace(); } return json; } }
上述的代码片段即可组合成一个工程,编译运行了。当然,我们需要把ichartjs的JS库和写好的HTML页面引入到我们工程目录下的assets文件夹下。另外,有一个需要注意的地方,我们在定义3D柱状图的时候,配置了柱状图的展示动画,需要在AndroidMenifest.xml文件中配置应用可以开启硬件加速:
<application android:hardwareAccelerated="true" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.achartdemo.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application>
下面附上运行的效果图: