生成HTML Canvas图像数据服务器端? [英] Generating HTML Canvas image data server-side?

查看:218
本文介绍了生成HTML Canvas图像数据服务器端?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题的标题可能有点误导,但我不知道最好的标题是什么(因为我还不能猜到解决方案)。

The title of this question may be slightly misleading, but I'm not sure what the best title would be (since I can't guess at a solution yet).

基本上,我开发的系统很大程度上依赖于画布图。这些图是通过javascript生成的,并且是使用通过ajax从API服务器拉取的数据生成的。

Basically the system I am developing relies heavily on canvas graphs. These graphs are generated through javascript, and are made using data pulled via ajax from an API server.

棘手的部分是,我想能够通过电子邮件发送图表给这个系统的用户,没有他们实际上必须去到网页。所以,虽然我知道,可以得到在浏览器中使用JavaScript生成的图像的Base64值,但是如果没有人能够运行那个javascript呢?

The tricky part is, I'd like to be able to email these graphs to users of this system, without them actually having to go to the web page at all. So while I'm aware that it is possible to get the Base64 value of an image generated with javascript in a browser, what about if no one is there to run that javascript?

我想保留在javascript / canvas生成的图形,而不是使它们在一个通用的服务器端图形库(GD,ImageMagick)。 Canvas图是动态的,允许通过javascript进行交互。虽然我不想在电子邮件通知中的功能,但我确实希望它们是相同的(至少在外观上)。

I'd like to keep the graphs generated in javascript/canvas, rather than making them in a common server-side graphics library (GD, ImageMagick). The Canvas graphs are dynamic, and allow for interaction via javascript. Though I don't want that functionality in the email notification, I do want them to be identical otherwise (at least in appearance).

所以问题是,如何

在这一点上,我唯一的猜测是,我需要真正做一个网站,做一个AJAX请求的图形渲染,呈现这些图形,并将结果发送到服务器。然后,我需要一个服务器,只是坐在那个网页上,并搅拌出图表。这是唯一的解决方案吗?

At this point, my only guess is that I'd need to literally make a website that does AJAX requests for "graphs to render", renders these graphs, and sends the results to the server. Then I'd need a "server" that just sits there on that web page and churns out graphs. Is that the only solution here?

推荐答案

我使用phantomJs(像node.js但不同)serverside运行完全相同的代码作为客户端,并得到相同的结果。所有你需要的是一个单独的exe文件(像webkit独立的web浏览器)

I used phantomJs (like node.js but different) serverside to run exactly the same code as client side, and get the same result. all you need is one single exe-file (like a webkit stand alone web brower)

以下程序(在Perl,但应该是可行的, )获取一些数据,插入到网页(可能是ajax的),并将该网页发送到客户端,或将其存储为临时文件,并在同一页面上启动PhantomJs。然后请PhantomJs生成一个jpg,然后拾起(在这种情况下sendt到客户端)。

The following program (in Perl, but should be feasible to translate to you favourite language) takes some data, inserts into a web-page (could be ajax'ed) and either sends that web page to the client, or stores it as a temporary file, and starts PhantomJs on the same page. Then ask PhantomJs to generate a jpg, that is then picked up (and in this case sendt to the client).

#!/usr/bin/perl

use strict;
use File::Temp;
$|=1;
#this script returns a graph, either as html +js web page to render client side,
#or renders the same page server side, and returns the jpg image.

#files needed:
#.\phantom_srv_client.pl  #this script
#.\phantomjs.exe          #the webkit runtime stand alone file, from http://phantomjs.org/
#.\Scripts\excanvas.min.js #canvas simulator for IE8-
#.\Scripts\jquery.min.js   #jQuery as we know it
#.\Scripts\jquery.jqplot.min.js #graph library on top of jQuery from http://www.jqplot.com/ (Flot or any can be used)


#do we want client side rendering (html + js), or server side rendering (jpg)
#jpg seems to render nicer than png on some pages?
use CGI;
my $show_as_jpg = CGI::param("jpg");

#path to javascript libraries (jQuery etc). 
#Must be absolute file location for server rendering, relative for web
use FindBin;
my $script_path = $show_as_jpg 
    ? $FindBin::Bin."/Scripts" 
    : './Scripts';


#data to send to graph (two sets)
my $data = [[2,5,4], [6,4,5]];

#use json to get this as a javascript text
my $json_data;
eval {require JSON; $json_data=JSON::to_json($data)};
#in case JSON is not installed, get the json/javascript data manually (just for demo)
$json_data ||= "[[2,5,4], [6,4,9]]"; #here 9 at the end to see a difference

#The following is the web page that renders the graph, client or server side 
#(links to scripts must be abolute to work serverside, as temp-files may go anywhere, $script_path keeps track of that)
#$json_data is the Perl data structure converted to JSON (aka javascript, but not)
my $graph_html =qq|
<!DOCTYPE html>
<html>
<head>
    <!--[if lt IE 9]><script language="javascript" type="text/javascript" src="$script_path/excanvas.min.js"></script><![endif]-->
    <script class="include" type="text/javascript" src="$script_path/jquery.min.js"></script>
    <script class="include" type="text/javascript" src="$script_path/jquery.jqplot.min.js"></script>

    <script class="code" type="text/javascript" language="javascript">
        jQuery(document).ready(function(){
            /*data from perl (\$json_data) inserted here */
            var data = $json_data;
            jQuery.jqplot("chart1", data );
        });
    </script>
    </head>
<body>
    <div id="chart1" style="width:600px; height:400px;"></div>
    <a href='?jpg=1'>View as jpg</a>
</body>
</html>
|;


#this is the javascript that tells PhantomJs what to do (ie open a doc and render it to bitmap)
my $phantom_doc_js =qq|
    var system = require('system');
    //read from commandline which files to open, and write to
    var open_doc = system.args[1];
    var return_doc = system.args[2];
    var page = require('webpage').create();
    page.open(open_doc, function () {
        page.render(return_doc);
        phantom.exit();
    });
|;

#see if we shall render this page serverside
if ($show_as_jpg) {
    #get temporary filenames with related file handlers
    #where to put phantomjs script (generic so could be a static file)
    my ($phantom_doc_filehandler, $phantom_doc_filename) = File::Temp::tempfile(  SUFFIX => '.js', TMPDIR => 1);
    #where to put web page with data to render and ref to javascripts etc
    my ($phantom_graph_filehandler, $phantom_graph_filename) = File::Temp::tempfile(SUFFIX => '.html', TMPDIR => 1);
    #also get a filename with no handler, so phantomjs can return the jpg file. Extention must be .jpg!
    my (undef, $image_filename) = File::Temp::tempfile( SUFFIX => '.jpg',TMPDIR => 1, OPEN => 0);

    #store file content and close files
    print $phantom_doc_filehandler $phantom_doc_js; close $phantom_doc_filehandler;
    print $phantom_graph_filehandler $graph_html;   close $phantom_graph_filehandler;

    #now call PhantomJs with filenames to read from and write to.
    #Next version should support piping, which would simplify a lot

    #use absolute path to phantomjs.exe in case web-server does not use current path
    system($FindBin::Bin.'\\phantomjs', $phantom_doc_filename, $phantom_graph_filename, $image_filename) == 0 
        or die "system failed: $?";

    #read the entire image file
    my $img = slurp_file($image_filename);
    print "Content-Type: image/jpeg\nPragma: no-cache\n\n".$img;

    #The temp files are no more needed
    unlink $phantom_doc_filename, $phantom_graph_filename, $image_filename;

} else { # just render client side
    print "Content-Type: text/html\nPragma: no-cache\n\n".$graph_html;
}

#slurp is not always std perl   
sub slurp_file{
  my $filename = shift;
  my $string;
  local $/ = undef;
  open FILE, $filename or die "Couldn't open file: $!";
  binmode FILE;
  $string = <FILE>;
  close FILE;
  return $string;
}

这篇关于生成HTML Canvas图像数据服务器端?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆