使用HTML5 Canvas从本地CSV“绘制”2D数组

4

我希望用浏览器绘制本地文本文件的内容,以进行数据可视化练习。

html和txt都是本地文件,仅供原型设计/个人使用。

基本上,我想使用JavaScript之类的语言来读取这样的文件:

0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0
0.0, 0.2, 0.3, 0.3, 0.3, 0.2, 0.0
0.0, 0.3, 0.5, 0.6, 0.5, 0.3, 0.0
0.0, 0.3, 0.6, 0.8, 0.6, 0.3, 0.0
0.0, 0.3, 0.5, 0.6, 0.5, 0.3, 0.0
0.0, 0.2, 0.3, 0.3, 0.3, 0.2, 0.0
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0

并且呈现为彩色圆形的正方形网格。 txt中的每个值将是相应圆圈的不透明度,就像这样(使用Python,Numpy,Cairo和PIL制作): enter image description here 我完全不懂javascript和HTML5 Canvas,所以非常感谢您提供的线索,告诉我该做什么,使用哪些功能等等。
无需提供完整代码(但如果能提供会很好!),只需提供函数和概念名称,以便我可以查找教程并从一堆“ Hello Worlds”或类似内容中组装我的收藏。
谢谢阅读!
3个回答

3
TL;DR: http://bv.iriscouch.com/so/_design/ex/index.htmlhttp://bv.iriscouch.com/so/_design/ex/separate-function.html 这是一个略微冗长的答案,但我感觉不久前我也曾处于你的鞋子中,并且会从以下一些指针中受益。我将使用Python类比来解释,因为你提到了那些Python库。同时,我也想提一下:我喜欢低级别的东西,我喜欢示波器,C等等,但是JavaScript美妙的、更低层次的核心在于它的对象和函数——浏览器环境是一个丛林,自从尽可能地把工作交给jQuery和Underscore.js之后,我变得更加快乐了。

首先,关于csv格式,如果这是一个绝对的要求,请使用d3.js库中的d3.csv。 (事实上,从现在开始学习的所有数据可视化javascript都应该准备尽可能多地从Mike Bostock的想象中复制。)但是在Javascript中询问csv有点像问“我是亚洲新手,在四川哪里可以吃到最好的寿司?”答案:“你就在四川!”。使用json。在您的情况下,我会这样做:

>>> f = open('sample.csv').readlines()
>>> rv = json.dumps([[float(i) for i in k.split(',')] for k in f])
>>> file_out.write(rv)

这是如何在一个文件中完成的:http://bv.iriscouch.com/so/_design/ex/index.html 这是如何将其分解为核心功能,然后在页面画布上呈现的方法:http://bv.iriscouch.com/so/_design/ex/separate-function.html (顺便说一下,请尝试iriscouch.com,它是互联网上最酷的东西之一,并且是熟悉Javascript的好方法。下面的示例都在那里。sudo pip install couchappcouchapp generate excp *.js *.html ex/_attachmentscd ex && couchapp push https://user:pass@youraccount.iriscouch.com/somename是我放置这些示例的方法,完全免费。Windows安装程序here。)
如果您想查看重新格式化的底层数据,可以点击这里
最后,您可以在http://aguacat.es中了解更多我的个人学习历程。
上述示例的内联内容:
<!doctype html>

<html>
  <head>
    <script src="jquery.js"></script>
  </head>
  <body>
    <canvas id="circles" height="700" width="700"></canvas>
    <script>
      // $ is just a function. It makes dealing with the
      // browser itself less annoying. Call it with a
      // function as argument. The function has no
      // name, like a python lambda, and it will
      // request the json and process it.
      $(function () {
        var the_color = "rgba(0,0,255,alpha_token)";
        // ask for the json and register the following
        // function (second argument to getJSON) to be called 
        // once it is delivered:
        $.getJSON('json_from_csv.json', function(data) {
          // no more jquery for now
          var canvas = document.getElementById("circles");
          // you declare these to avoid them being global variables:
          var h, w, column_width, column_height, x_pos, y_pos, radius;
          h = canvas.height;
          w = canvas.width;
          column_width = w / data[0].length;
          column_height = h / data.length;
          // we're working in 2 dimensions:
          var context = canvas.getContext('2d');
          radius = column_width / 2; 
          data.forEach(function (row, row_index) {
            row.forEach(function (entry, column_index) {
              x_pos = column_index * column_width + radius;
              y_pos = row_index * column_height + radius;
              context.moveTo(x_pos, y_pos);
              context.beginPath();
              context.arc(x_pos, y_pos, radius, 0, Math.PI*2)
              context.fillStyle = the_color.replace(/alpha_token/, entry);
              context.strokeStyle = the_color.replace(/alpha_token/, entry);
              context.fill();
              context.stroke();
              context.closePath();
            });
          });
          });
        });
      </script>
    </body>

</html>

哦,我的天啊,这是一个非常详细的答案。非常感谢您的关心!今天我很忙,但我会尽快仔细研究您的例子。再次感谢! - heltonbiker
抱歉再次打扰,但我无法使用JavaScript访问本地文件的内容(我猜这与安全有关),所以我想知道如何将文件拖放到“拖放”区域中,以便该文件(一个.json文件)可以在画布中呈现。你知道怎么做吗? - heltonbiker
仅供记录:使用SimpleHTTPServer一切正常(我也会测试apache),但是“没有人告诉我”我应该使用jquery.js。顺便说一下,我将其复制到了目录中。对于SimpleHTTPServer提示加1! - heltonbiker

2
回复Heltonbiker。使用JavaScript在本地存储访问数据是非常可能的,例如您可以创建一个JSON对象并将其存储在变量中,然后将文件保存在本地。您的文件看起来会像这样:
var jsonObject = {

    "priorities": [ [1,12], [4,2] ]
}

现在,如果您将本地文件包含在脚本的头部,如下所示:
<script type="text/javascript" language="javascript" src="priorities.json"></script>

现在我可以访问存储在同一目录下的index.html中的数据来操作我的画布。
Jeffrey,感谢您提供的有用文章。我正在寻找一种使用纯JavaScript从两个数据集绘制plot的方法,而这篇文章提供了一些不错的信息 :)

是的,我有一段时间开始这样做了。但实际上将文件命名为 priorities.json 是有点“错误”的。应该将其命名为 priorities.js,或者至少是 priorities.jsonp,因为文件内容是有效的Javascript,但不是有效的Json。 - heltonbiker
你是完全正确的,它没有通过验证器 :) - Knopfler

1

这是完全可能的!

通过XMLHttpRequest对象,您可以使用JavaScript读取本地文本文件,并通过正则表达式或类似方法解析其内容。

不幸的是,我对字符串解析并不很擅长,但我为加载文件和在画布上绘制圆圈编写了一个示例。

script.js:

var Visualizer =  {

    canvas      : document.getElementById("canvas"),
    context     : this.canvas.getContext("2d"),
    fileContents    : "",

    //Load a local file
    loadFile    : function(address) {
        var file = (window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP");
        if(file == null) {
            console.log("Error: XMLHttpRequest failed to initiate.");
        }
        file.onreadystatechange = function() {
            if (file.readyState == 4) { //Completed loading
                if (file.status == 200 || file.status == 0) {

                    //The responseText is the contents of the text file
                    fileContents = file.responseText;

                    Visualizer.onFileLoad();
                }
                else    //Otherwise, there was a problem while loading
                    console.log("Error " + file.status + " has occurred.");
            }
        }
        try {
            file.open("GET", address, true);
            file.send(null);

        } catch(e) {
            console.log("Error retrieving data file. Some browsers only accept cross-domain request with HTTP.");
        }

    },

    //Called when the xmlhttprequest object loads the file successfully
    onFileLoad  : function() {
        this.parseFile();
    },

    //Iterates through a file and draws circles
    parseFile   : function() {

        var x = 0;
        var y = 0;


        //~~~Create some method for parsing the text~~~

        var r = 100;
        var g = 100;
        var b = 255;

        var color = "rgba("+r+","+g+","+b+",1)";

        this.drawCircleAt(x+25, y+25, color);



    },


    //Draws circles with a 25 pixel diameter at the position specified.
    drawCircleAt    : function(x, y, color) {

        this.context.fillStyle = color;
        this.context.beginPath();
        this.context.arc(x, y, 25, 0, 6.283, false);
        this.context.fill();
        this.context.closePath();

    }


}

index.html:

<!DOCTYPE html>
<html>
    <head>
        <title></title>
    </head>
    <body>
        <canvas id="canvas" width="500" height="500">
        </canvas>
        <script type="text/Javascript" src="script.js"></script>
        <script>
            Visualizer.loadFile("file.txt");
            </script>
    </body>
</html>

如果你对代码有任何疑问,请随时提出。


由于某些原因,画布正在被绘制,但是为空的。我在一个目录中创建了文件。你的示例是否旨在按原样工作,还是只是一个草稿,我可以通过它实际获得我想要的结果? - heltonbiker
抱歉回复晚了。您需要在与index.html和script.js文件相同的目录中拥有一个名为“file.txt”的文本文件。虽然画布实际上不会解析任何内容,但它应该在屏幕上绘制一个圆形。 - Jeffrey Sweeney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接