在 Internet Explorer 上将 Raphaël 图像保存为 PNG

Posted

技术标签:

【中文标题】在 Internet Explorer 上将 Raphaël 图像保存为 PNG【英文标题】:Saving Raphaël image as PNG on Internet Explorer 【发布时间】:2010-11-07 14:26:40 【问题描述】:

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

这在除 Internet Explorer 之外的所有浏览器上都很简单,因为在非 Internet Explorer 浏览器上我得到 SVG 作为 Raphaël 的输出,然后我可以将其转换为画布(使用 cansvg 库)并且画布有一个 @987654326 @ 方法。但在 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 下完成这项任务呢?

【问题讨论】:

我不会将此作为答案发布,因为我自己没有尝试过,但您可能会成功“欺骗”拉斐尔使用 svg-web,它对 SVG 有很好的支持DOM API。您在其他浏览器中使用的技术将是相同的。我认为这是可以工作的,但你可能不得不稍微修改一下 raphaeljs 代码。请注意,我从未读过任何人尝试将 raphaeljs 与 svg-web、svg-web 与 canvg 或 canvg 与 flashcanvas 一起使用,因此,如果您让这一切正常工作,这将是一个史诗般的 hack,您绝对应该写它。祝你好运:) 正如我所说的 - 我让它在除 IE 之外的所有浏览器上都能运行。如果你想试试,我可以附上 aptana 项目。 现在是关于欺骗拉斐尔的事情。这些是 raphael 中使用的方法,IE 不支持:getNumberOfChars()、getExtentOfChar()、createElementNS() 以及其他一些问题 【参考方案1】:

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

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

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

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

至于“浏览器对生成图形的支持仍然非常有限”,事实并非如此。查看 RaphaelJS.com 演示,这是完全可行的,也是一个很好的解决方案。唯一的问题是 IE

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

【讨论】:

Excanvas 非常糟糕,Raphael 要好得多。话虽如此,我刚刚开始尝试将拉斐尔的画作保存为 IE 中的图像 :)。 我没用过,但是这个sourceforge.net/projects/vectorconverter现在已经存在了,可以修改来做你需要的事情【参考方案2】:

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

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

一般来说,除非绝对必要,否则不建议实施 ActiveX 解决方案。

【讨论】:

【参考方案3】:

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

要求

    PHP Flash Player 9+(对于 Flashcanvas,如果我错了,请纠正我) RaphaelJS Raphael Export CanVG FlashCanvas Free or Pro Canvas2PNG + save.php(包含在 FlashCanvas 中)

概述

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

故障

    启动一个空画布

    <canvas id="myCanvas"></canvas>
    

    用 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");
    

    使用 Raphael Export 将纸张从 VML 转换为 SVG。

    var svg = paper.toSVG();
    

    在空白画布上初始化 Flashcanvas

    var canvas = document.getElementById('export');
    if (typeof FlashCanvas != "undefined") 
      FlashCanvas.initElement(canvas); //initiate Flashcanvas on our canvas
    
    

    将 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);
      
    );
    

    一旦canvg在画布上生成了SVG数据,调用Flashcanvas的canvas2png函数

    //This is called within the renderCallback canvg function above:
    renderCallback: function() 
      setTimeout(function() 
        canvas2png(canvas);
      , 1000);
    
    

    纸张保存为 PNG! $$$

笔记/发现

不要在 FLASHCANVAS 中包含/使用 EXCANVAS,我犯的这一行错误几乎导致我多次放弃 FlashCanvas。 应尽早将 Flashcanvas 包含在 &lt;head&gt; 中,由于某种原因,我在稍后包含 flashcanvas.js 时遇到了问题。

Canvas2png.js 默认会提示用户保存 .png 文件。或者,您可以通过编辑 Flashcanvas save.php 文件 from 将 .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);
最后一点:如果您选择将图像保存到服务器,默认情况下,当您调用canvas2png() 时,您将被转发到一个空白的 save.php(save.php 不是由 AJAX 运行的!)因此您将失去当前的拉斐尔绘画课程。

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

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

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

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

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

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

    启动一个空画布 用 Raphael 绘制一些 SVG 使用 Raphael Export 导出 SVG 字符串 使用 canvg 将 SVG 数据解析到空画布中 使用 canvas.toDataURL()

【讨论】:

【参考方案4】:

您可能希望考虑在服务器端生成图像。浏览器对生成图形的支持仍然非常有限。

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

【讨论】:

"至于“浏览器对生成图形的支持仍然非常有限”,不是。查看 RaphaelJS.com 的演示,这是完全可行的,也是一个很好的解决方案。唯一的问题是 IE @Alex 他的问题正是如此。 . .他需要支持旧的浏览器。为什么只在后端生成图像然后通过 AJAX 加载它们不是一个好的解决方案?

以上是关于在 Internet Explorer 上将 Raphaël 图像保存为 PNG的主要内容,如果未能解决你的问题,请参考以下文章

为啥即使在模拟 Internet Explorer 8 文档模式时,Internet Explorer 11 也不支持条件注释?

对于某些情况,如 Internet Explorer 特定的 CSS 或 Internet Explorer 特定的 JavaScript 代码,如何仅针对 Internet Explorer 10?

如何从 Internet Explorer 11 降级到 Internet Explorer 10?

css 在Internet Explorer上隐藏滚动条

为啥在安装Windows Internet Explorer 7的时候,提示"此操作系统不支持Windows Internet Explorer 7.

JavaScript 在Firefox和Internet Explorer中关闭窗口