我可以使用d3.js在Android应用程序中创建交互式可视化吗?

时间:2012-05-14 19:57:00

标签: android web-applications visualization d3.js

我正在尝试在Android应用中创建交互式可视化。

将可视化的数据将本地存储在sqlite数据库中,并将被查询以生成可视化。

我还没有决定是构建原生应用还是网络应用。

根据我的研究,d3.js似乎很好地满足了需求,但我不确定如何在移动环境中使用它。

5 个答案:

答案 0 :(得分:14)

您可以使用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)

答案 1 :(得分:7)

我按照this tutorial让D3在我的Android应用上运行。从那里,可以很容易地扩展教程的代码以满足我的需求。

这是教程的略微修改版本(我添加了缩放控件和缩放):

  1. 创建一个JS资源文件夹(ProjectName / app / src / main / assets / js)
  2. 下载D3(https://d3js.org/)并将缩小的d3.min.js源文件复制到ProjectName / app / src / main / assets / js
  3. 为HTML资产创建目录:(ProjectName / app / src / main / assets / html)
  4. 创建文件ProjectName / app / src / main / assets / html / graph.html。将此代码复制到新文件中:
  5. <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>
    
    1. 创建将运行D3的JS文件:ProjectName / app / src / main / assets / js / drawGraph.js。将以下代码添加到其中:
    2. 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; });
      }
      
      1. 创建一个将托管D3代码的活动布局:
      2. <?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>
        
        1. 在您的活动中初始化网页浏览:
        2. 
          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");
          }
          

          }

答案 2 :(得分:2)

据我所知,Android应用程序仅限java。因此,要使用d3,您需要一个java javascript引擎/包装器(如Rhino或apparently PhoneGap)或者只需创建一个HTML5应用程序(而不是Android应用程序)。

关于PhoneGap的链接似乎是关于从HTML5生成应用程序,但您需要检查是否可以包含任意附加库。

是否必须是应用程序? D3更适合编写HTML5网站而不是应用程序。

答案 3 :(得分:0)

您好我在使用D3,C3和phonegap在可安装应用上渲染图表的问题。 问题是如果你尝试执行c3.generate它会在浏览器上正常工作,但不能在可安装的应用程序上工作,解决方案是编写自己的指令并在其中使用C3。

希望这有助于某人。

答案 4 :(得分:0)

对于像我这样的人,尝试通过参考教程来学习如何将D3集成到Android中,这里是当前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; });
    }