11

我使用Raphaël(一个 JavaScript 库)完成了一些漂亮的图形,我想添加一个功能将其保存为PNG文件。

这在除 Internet Explorer 之外的所有浏览器上都很简单,因为在非 Internet Explorer 浏览器上,我将SVG作为 Raphaël 的输出,然后我可以将其转换为画布(使用 cansvg 库),并且画布有一个toDataURL()方法。但在 Internet Explorer 上,Raphaël 输出VML。我无法使用Chrome框架插件。为什么?

我的应用程序的用户选择 Internet Explorer 只是因为它预装在 Windows 上,而且他们无权安装其他任何东西。所以他们不能安装这个插件。所以我的第二个想法是在 Internet Explorer 上获取一个 SVG 字符串,将其传递给 cansvg 以获取一个画布,然后使用flashCanvas.

我试图让 Raphaël 认为它在非 Internet Explorer 浏览器上运行并获取 SVG 作为输出,但我失败了,因为 Raphaël 使用 Internet Explorer 中不存在的一些 JavaScript 函数来生成 SVG。

那么如何在 Internet Explorer 下完成这个任务呢?

4

4 回答 4

2

PHP & JavaScript 解决方案(不需要ImageMagick、 Apache Batik Rasterizer 或Inkscape!):

要求

  1. PHP
  2. Flash Player 9+(对于 Flashcanvas,如果我错了,请纠正我)
  3. 拉斐尔JS
  4. 拉斐尔出口
  5. 可以VG
  6. FlashCanvas 免费或专业版
  7. Canvas2PNG + save.php(包含在 FlashCanvas 中)

概述

  1. 启动一个空画布
  2. 用 Raphael 画一些 VML
  3. 使用 Raphael Export 将纸张从 VML 转换为 SVG
  4. 在空画布上初始化 Flashcanvas
  5. 将 SVG 字符串从 Raphael Export 发送到 canvg
  6. 一旦 canvg 将 SVG 数据生成到 FlashCanvas 启动的画布上,调用 Flashcanvas 的 canvas2png 函数
  7. 纸张保存为 PNG!$$$

分解

  1. 启动一个空画布

    <canvas id="myCanvas"></canvas>
    
  2. 用 Raphael 画一些 VML

    //Basic Example
    var paper = Raphael(10, 50, 320, 200);
    var circle = paper.circle(50, 40, 10);
    circle.attr("fill", "#f00");
    circle.attr("stroke", "#fff");
    
  3. 使用 Raphael Export 将纸张从 VML 转换为 SVG。

    var svg = paper.toSVG();
    
  4. 在空画布上初始化 Flashcanvas

    var canvas = document.getElementById('export');
    if (typeof FlashCanvas != "undefined") {
      FlashCanvas.initElement(canvas); //initiate Flashcanvas on our canvas
    }
    
  5. 将 SVG 字符串从 Raphael Export 发送到 canvg

    canvg(canvas, svg, {
      ignoreMouse: true, //I needed these options so Internet Explorer wouldn't clear the canvas
      ignoreAnimation: true,
      ignoreClear: true,
      renderCallback: function() {
        setTimeout(function() {
          canvas2png(canvas);
        }, 1000);
      }
    });
    
  6. 一旦 canvg 将 SVG 数据生成到画布上,调用 Flashcanvas 的 canvas2png 函数

    //This is called within the renderCallback canvg function above:
    renderCallback: function() {
      setTimeout(function() {
        canvas2png(canvas);
      }, 1000);
    }
    
  7. 纸张保存为 PNG!$$$

注释/发现

  • DON'T INCLUDE/USE EXCANVAS with FLASHCANVAS,我犯的这一行错误几乎导致我在很多场合都放弃了 FlashCanvas。
  • Flashcanvas 应该尽早包含在 .js 中<head>,由于某种原因,我在稍后包含 flashcanvas.js 时遇到了问题。
  • Canvas2png.js 默认会提示用户保存 .png 文件。或者,您可以通过从以下位置编辑 Flashcanvas save.php 文件将 .png 写入服务器:

    readfile('php://input');
    

    //Comment these out so that the download is not forced
    //header('Content-Type: application/octet-stream');
    //header('Content-Disposition: attachment; filename="canvas.png"');
    
    $putdata = fopen("php://input", "r");
    $fp = fopen("path/to/image_name.png", "w");
    while ($data = fread($putdata, 1024)) {
      fwrite($fp, $data);
    }
    fclose($fp);
    fclose($putdata);
    
  • 最后一点:如果您选择将图像保存到服务器,默认情况下,当您调用时,您将被转发到空白的 save.php canvas2png()(save.php 不是由 AJAX 运行的!),因此您会输您当前的拉斐尔绘画课程。

因此,如果您想在不丢失当前 Raphael 会话的情况下调用此方法,我解决此问题的方法是将 Raphael 论文保留在一个页面上,并将该<canvas>页面保留在另一个页面上。

一般的想法是您将 Raphael 绘图活动保留在您的主页上,当您准备好导出/保存图像时,您可以打开一个包含空画布的新窗口,并将SVG 数据发送到新的临时页。从那里你可以再次按照我们离开的步骤,除了在新窗口中,在 save.php 文件的末尾,当图像生成并保存时,你可以使用 javascript 调用:self.close()关闭那个新的窗户。

我们需要弹出这个新窗口,以便可以使用 SVG 数据正确处理画布。

  • 使用 Internet Explorer 8(Chrome/Firefox 工作)的 canvg 无法读取从 .php URL 生成的图像,要解决此问题,我必须使用 PHP 将“php url 图像内容”保存为服务器上的临时图像,并且通过替换其原始xlink:href将该临时图像用作 SVG 数据的参考。

  • canvas2png.js 在您的浏览器不支持的情况下具有后备功能toDataURL,使此解决方案跨浏览器兼容

  • 最后一点,如果您使用支持 toDataURL 的浏览器,我想我会包含导出图像的快速方法,我会推断浏览器也支持 SVG,因此保存图像的过程要容易得多(无需 Flashcanvas 麻烦):

    1. 启动一个空画布
    2. 用 Raphael 画一些 SVG
    3. 使用 Raphael Export 导出 SVG 字符串
    4. 使用 canvg 将 SVG 数据解析到空画布中
    5. 使用 canvas.toDataURL()
于 2013-08-21T20:00:27.373 回答
2

RaphaelJS 不使用画布。它在 IE 中使用 VML,但在所有其他浏览器中使用 SVG。

正如 OP 所说,您可以获取原始 SVG(因为它是一个完整的 SVG 文档)并下载它,他正在寻找一些与 VML 类似的功能。

我能想到的唯一方法是让 IE 将 VML 数据(如果可能的话)发送回服务器,该服务器将其转换为 PNG 并下载它。

但是,由于您需要 PNG,因此您可能最好从一开始就使用画布,因为如果您随后转换为位图,则可能不需要图形的矢量端。检查画布和谷歌 IE 画布脚本,看看你是否可以使用它。

至于“浏览器对生成图形的支持仍然非常有限”,事实并非如此。查看 RaphaelJS.com 演示,这是完全可行的,也是一个很好的解决方案。唯一的问题是 IE <9 没有采用任何现代技术,如 HTML5、CSS3 或 SVG。

任何支持 Canvas 或 google IEcanvas 的东西也可以产生不错的结果。

于 2010-12-07T19:38:28.353 回答
2

Raphaël 在 Internet Explorer 中使用 VML,在所有其他浏览器中使用 SVG。Canvas 具有导出为图像的内置功能,而 VML 中未内置此类功能。您可以使用服务器端代码为不受支持的浏览器实现相同的目的。

另一种解决方案是使用Internet Explorer 的ActiveX解决方案,它可以从 VML 生成图像。一种这样的解决方案是HTML Snapshot ActiveX 组件

通常,除非绝对必要,否则不建议实施 ActiveX 解决方案。

于 2010-12-02T14:04:15.680 回答
0

您可能想研究在服务器端生成图像。浏览器对生成图形的支持仍然非常有限。

Node Canvas刚刚问世,我过去使用 ImageMagick 取得了巨大成功。

于 2010-11-12T19:28:12.690 回答