te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Generating HTML Canvas image data server-side? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Generating HTML Canvas image data server-side? - Stack Overflow

programmeradmin3浏览0评论

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).

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.

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?

I'd like to keep the graphs generated in javascript/canvas, rather than making them in a mon 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).

So the question is, how can I get these graphs into an email?

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?

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).

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.

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?

I'd like to keep the graphs generated in javascript/canvas, rather than making them in a mon 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).

So the question is, how can I get these graphs into an email?

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?

Share Improve this question asked Feb 23, 2012 at 7:58 GoldenNewbyGoldenNewby 4,4528 gold badges35 silver badges44 bronze badges 4
  • 4 Check out github./learnboost/node-canvas - it is a node implemented canvas that uses Cairo as the image processor. – steveukx Commented Feb 23, 2012 at 8:03
  • I don't quite understand. Do you want a server-side graphing library that is API-patible with the HTML5 canvas, so that you can use the same code in a browser and on the server? – Thilo Commented Feb 23, 2012 at 8:05
  • Pretty much yeah. I was unfamiliar with node-canvas and nodejs, is that the solution? – GoldenNewby Commented Feb 23, 2012 at 8:06
  • 2 I've been using node-canvas (and fabric.js on top of that) to generate images from canvas on a server and it does work pretty well. – kangax Commented Feb 24, 2012 at 3:33
Add a ment  | 

1 Answer 1

Reset to default 9

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)

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/
#.\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./ (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 mandline 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;
}
发布评论

评论列表(0)

  1. 暂无评论