Gol*_*wby 22 javascript html5 canvas
这个问题的标题可能会有些误导,但我不确定最佳标题是什么(因为我无法猜测解决方案).
基本上我正在开发的系统在很大程度上依赖于画布图.这些图表是通过javascript生成的,使用从API服务器通过ajax提取的数据生成.
棘手的部分是,我希望能够将这些图形通过电子邮件发送给该系统的用户,而实际上他们根本不必去网页.因此,虽然我知道可以在浏览器中获取使用javascript生成的图像的Base64值,但如果没有人可以运行该javascript呢?
我想保留在javascript/canvas中生成的图形,而不是将它们放在一个通用的服务器端图形库(GD,ImageMagick)中.Canvas图是动态的,允许通过javascript进行交互.虽然我不想在电子邮件通知中使用该功能,但我确实希望它们完全相同(至少在外观上).
所以问题是,如何将这些图表添加到电子邮件中?
在这一点上,我唯一的猜测是,我需要从字面上创建一个网站,对"图形渲染"执行AJAX请求,渲染这些图形,并将结果发送到服务器.然后我需要一个"服务器",它只是坐在那个网页上并生成图表.这是唯一的解决方案吗?
我使用phantomJs(比如node.js但不同的)服务器端来运行与客户端完全相同的代码,并获得相同的结果.你只需要一个单独的exe文件(就像一个webkit独立的web浏览器)
以下程序(在Perl中,但应该可以翻译成您最喜欢的语言)需要一些数据,插入到网页(可能是ajax)并将该网页发送到客户端,或将其存储为临时文件,并在同一页面上启动PhantomJs.然后让PhantomJs生成一个jpg,然后将其拾取(在这种情况下发送给客户端).
#!/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;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10550 次 |
| 最近记录: |