【发布时间】:2012-05-22 08:11:05
【问题描述】:
我正在尝试在 Android 应用程序中创建交互式可视化。
将被可视化的数据将存储在本地的 sqlite 数据库中,并将被查询以生成可视化。
我还没有决定是构建原生应用还是网络应用。
根据我的研究,d3.js 似乎非常适合需求,但我不确定如何在移动环境中使用它。
【问题讨论】:
标签: android web-applications visualization d3.js
我正在尝试在 Android 应用程序中创建交互式可视化。
将被可视化的数据将存储在本地的 sqlite 数据库中,并将被查询以生成可视化。
我还没有决定是构建原生应用还是网络应用。
根据我的研究,d3.js 似乎非常适合需求,但我不确定如何在移动环境中使用它。
【问题讨论】:
标签: android web-applications visualization d3.js
您可以使用 WebView 组件轻松地将 Javascript 嵌入到 Android 应用程序中,也可以使用 PhoneGap 或类似平台。不幸的是,在 Android 3.0 之前,原生 android 浏览器不显示 svg,而 D3 是基于 SVG 的,因此在 android 2.3(或更低版本)浏览器中无法正常工作。但是它在 Firefox 浏览器中也可以工作。
另一种选择是在 WebView 或电话间隙中使用 InfoVis Toolkit。 InfoVis Toolkit 似乎在 Android 上运行得更好。
我不知道有什么可比的Android可视化平台,但是D3,它的前辈Protovis、Flare、Prefuse都是开源的。您或许可以尝试将其中一个移植到 Android。
这是一个相关的问题:visualization tool for mobile (tablet)
【讨论】:
我通过关注this tutorial 让 D3 可以在我的 Android 应用程序上工作。从那里,很容易扩展教程的代码以满足我的需要。
这里是稍微修改的教程版本(我添加了缩放控件和缩放):
<html>
<head>
<script type="text/javascript" src="file:///android_asset/js/d3.min.js"></script>
<script type="text/javascript" src="file:///android_asset/js/drawGraph.js"></script>
<meta name="viewport" content="width=device-width, user-scalable=yes" />
</head>
<body>
<svg id="piechart"></svg>
</body>
</html>
function initGraph(dataset, pHeight, pWidth) {
var height = parseInt(pHeight);
var width = parseInt(pWidth);
var svg = d3.select("#piechart");
var textLabelSuffix = "%";
showPieChart(dataset, svg, height, width,
textLabelSuffix);
}
function showPieChart(dataset, svg, height, width,
textLabelSuffix)
{
var outerRadius = width / 2;
var innerRadius = 0;
// set height/width to match the SVG element
svg.attr("height", height).attr("width", width);
// create a new pie layout
var pie = d3.layout.pie();
// initialize arcs/wedges to span
// the radius of the circle
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
// create groups
var arcs = svg.selectAll("g.arc")
// bind dataset to pie layout
.data(pie(dataset))
// create groups
.enter()
// append groups
.append("g")
// create arcs
.attr("class", "arc")
// position each arc in the pie layout
.attr("transform", "translate(" +
outerRadius + "," +
outerRadius + ")");
// initialize color scale - refer to
// https://github.com/mbostock/d3/wiki/Ordinal-Scales
var color = d3.scale.category10();
arcs.append("path")
.attr("fill", function(d,i) { return color(i); })
.attr("d", arc);
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) { return d.value +
textLabelSuffix; });
}
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/tvOutgoing"
android:layout_alignParentBottom="true"/>
</RelativeLayout>
public class VisualizationActivity extends AppCompatActivity {
private WebView webview;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_visualization);
// Prepare webview: add zoom controls and start zoomed out
webview = (WebView) findViewById(R.id.webview);
final WebSettings webSettings = webview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setBuiltInZoomControls(true);
webSettings.setSupportZoom(true);
webSettings.setUseWideViewPort(true);
webview.setWebChromeClient(new WebChromeClient());
webview.setInitialScale(1);
webview.setWebViewClient(new WebViewClient() {
@Override
public void onPageFinished(WebView view, String url) {
// after the HTML page loads, run JS to initialize graph
int dataset[] = new int[] {5,10,15,20,35};
String text = Arrays.toString(dataset);
webview.loadUrl("javascript:initGraph(" +
text + ", "
(webview.getHeight()) + ", "
+ (webview.getWidth()) + ")");
}
});
// Load base html from the assets directory
webview.loadUrl("file:///android_asset/html/graph.html");
}
}
【讨论】:
据我所知,Android 应用程序仅适用于 Java。因此,要使用 d3,您需要一个 java javascript 引擎/包装器(如 Rhino 或 apparently PhoneGap),或者只制作一个 HTML5 应用程序(而不是 Android 应用程序本身)。
关于 PhoneGap 的链接似乎是关于从 HTML5 生成应用程序,但您需要检查是否可以包含任意附加库。
它必须是一个应用程序吗? D3 更适合编写 HTML5 网站而不是应用程序。
【讨论】:
您好,我在使用 D3、C3 和 phonegap 在可安装应用程序上渲染图表时遇到了问题。 问题是,如果您尝试执行 c3.generate,它将在浏览器上正常运行,但在可安装应用程序上却不行,解决方案是编写您自己的指令并在其中使用 C3。
希望这对某人有所帮助。
【讨论】:
对于像我一样尝试通过参考教程学习如何在 Android 中集成 D3 的人来说,这里是当前 D3 版本 V5 的 D3 饼图的 js 代码。
function loadPieChart(dataset) {
var svg = d3.select("#piechart");
var height = 500;
var width = 500;
var textLabelSuffix = "%";
showPieChart(dataset, svg, height, width,
textLabelSuffix);
}
function showPieChart(dataset, svg, height, width,
textLabelSuffix)
{
var outerRadius = width / 2;
var innerRadius = 0;
// set height/width to match the SVG element
svg.attr("height", height).attr("width", width);
// create a new pie layout
var pie = d3.pie();
// initialize arcs/wedges to span
// the radius of the circle
var arc = d3.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
// create groups
var arcs = svg.selectAll("g.arc")
// bind dataset to pie layout
.data(pie(dataset))
// create groups
.enter()
// append groups
.append("g")
// create arcs
.attr("class", "arc")
// position each arc in the pie layout
.attr("transform", "translate(" +
outerRadius + "," +
outerRadius + ")");
// initialize color scale - refer to
// <a href="https://github.com/mbostock/d3/wiki/Ordinal-Scales" target="_blank">https://github.com/mbostock/d3/wiki/Ordinal-Scales</a>
var color = d3.scaleOrdinal(d3.schemeAccent);
arcs.append("path")
.attr("fill", function(d,i) { return color(i); })
.attr("d", arc);
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) { return d.value +
textLabelSuffix; });
}
【讨论】: