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

发布于 2024-10-01 04:40:08 字数 1058 浏览 9 评论 0原文

我使用 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 下完成此任务呢?

I have some nice graphics done using Raphaël (a JavaScript library), and I want to add a feature to save it as a PNG file.

This is simple on every browser except Internet Explorer, because on non-Internet Explorer browsers I get SVG as an output from Raphaël, and then I can convert it to canvas (using cansvg library) and canvas has a toDataURL() method. But on Internet Explorer, Raphaël outputs VML. I can't use the Chrome frame plugin. Why?

Users of my application choose Internet Explorer just because it is preinstalled on Windows, and they don't have permission to install anything else. So they can't install this plugin. So my second idea was to get an SVG string on Internet Explorer, pass it to cansvg to get a canvas and then use flashCanvas.

I tried to trick Raphaël to think it's running on a non-Internet Explorer browser and get SVG as output, but I failed, as Raphaël use some JavaScript functions that are absent in Internet Explorer to produce SVG.

So how do I accomplish this task under Internet Explorer?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

恋竹姑娘 2024-10-08 04:40:09

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

要求

  1. PHP
  2. Flash Player 9+(对于 Flashcanvas,如果我错了,请纠正我)
  3. RaphaelJS
  4. Raphael 导出
  5. < a href="https://code.google.com/p/canvg/" rel="nofollow">CanVG
  6. FlashCanvas 免费版或专业版
  7. Canvas2PNG + save.php(包含在 FlashCanvas 中)

概述

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

细分

  1. 启动一个空画布

    
    
  2. 用 Raphael 绘制一些 VML

    //基本示例
    var 纸 = 拉斐尔(10, 50, 320, 200);
    var 圆 = paper.circle(50, 40, 10);
    圆.attr("填充", "#f00");
    圆.attr("笔划", "#fff");
    
  3. 使用 Raphael Export 将纸张从 VML 转换为 SVG。

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

    var canvas = document.getElementById('export');
    if (FlashCanvas 类型!= "未定义") {
      FlashCanvas.initElement(canvas); //在我们的画布上启动Flashcanvas
    }
    
  5. 将 SVG 字符串从 Raphael Export 发送到 canvg

    canvg(画布, svg, {
      ignoreMouse: true, //我需要这些选项,这样 Internet Explorer 就不会清除画布
      忽略动画:true,
      忽略清除:正确,
      渲染回调:函数(){
        设置超时(函数(){
          canvas2png(画布);
        }, 1000);
      }
    });
    
  6. canvg 将 SVG 数据生成到画布上后,调用 Flashcanvas 的 canvas2png 函数

    //这是在上面的renderCallback canvg函数中调用的:
    渲染回调:函数(){
      设置超时(函数(){
        canvas2png(画布);
      }, 1000);
    }
    
  7. 纸张保存为PNG! $$$

注释/调查结果

  • 不要将 EXCANVAS 与 FLASHCANVAS 一起使用,我犯的这一行错误多次几乎导致我放弃 FlashCanvas。
  • Flashcanvas 应该尽早包含在 中,由于某种原因,我在稍后包含 flashcanvas.js 时遇到了问题。
  • Canvas2png.js 默认情况下会提示用户保存 .png 文件。或者,您可以通过编辑 Flashcanvas save.php 文件将 .png 写入服务器来自

    readfile('php://input');
    

    //将这些注释掉,这样就不会强制下载
    // header('内容类型:应用程序/八位字节流');
    // 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 会话的情况下调用此方法,我解决此问题的方法是将 Raphael Paper 保留在一页上,而 另一页。

总体思路是,将 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 麻烦):

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

PHP & JavaScript solution (no need for ImageMagick, Apache Batik Rasterizer, or Inkscape!):

Requirements

  1. PHP
  2. Flash Player 9+ (for Flashcanvas, correct me if I'm wrong)
  3. RaphaelJS
  4. Raphael Export
  5. CanVG
  6. FlashCanvas Free or Pro
  7. Canvas2PNG + save.php (included with FlashCanvas)

Overview

  1. Initiate an empty canvas
  2. Draw some VML with Raphael
  3. Use Raphael Export to convert paper from VML to SVG
  4. Initialise Flashcanvas on the empty canvas
  5. Send the SVG string from Raphael Export to canvg
  6. Once canvg has generated the SVG data onto the FlashCanvas initiated canvas, call Flashcanvas' canvas2png function
  7. Paper is saved as a PNG! $$$

Breakdown

  1. Initiate an empty canvas

    <canvas id="myCanvas"></canvas>
    
  2. Draw some VML with Raphael

    //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. Use Raphael Export to convert paper from VML to SVG.

    var svg = paper.toSVG();
    
  4. Initialise Flashcanvas on the empty canvas

    var canvas = document.getElementById('export');
    if (typeof FlashCanvas != "undefined") {
      FlashCanvas.initElement(canvas); //initiate Flashcanvas on our canvas
    }
    
  5. Send the SVG string from Raphael Export to 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. Once canvg has generated the SVG data onto the canvas, call Flashcanvas' canvas2png function

    //This is called within the renderCallback canvg function above:
    renderCallback: function() {
      setTimeout(function() {
        canvas2png(canvas);
      }, 1000);
    }
    
  7. Paper is saved as a PNG! $$$

Notes/Findings

  • DON'T INCLUDE/USE EXCANVAS with FLASHCANVAS, this one line of mistake I had that almost caused me to give up on FlashCanvas on numerous occasions.
  • Flashcanvas should be included as early as possible in the <head>, for some reason I had issues when including flashcanvas.js later.
  • Canvas2png.js by default will prompt the user to save the .png file. Alternatively you can write the .png to your server by editing the Flashcanvas save.php file from:

    readfile('php://input');
    

    To:

    //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);
    
  • Following the last note: if you opted to save the image to the server instead, by default you'll be forwarded to a blank save.php when you call canvas2png() (save.php is not run by AJAX!) and thus you'll lose your current Raphael drawing session.

Therefore, if you want to invoke this method without losing your current Raphael session, the way I solved this was to keep the Raphael Paper on one page, and the <canvas> page on another.

The general idea is that you keep your Raphael drawing activity on your main page, and when you're ready to export/save an image, you could open a new window that contains the empty canvas, and send the SVG data to that new temporary page. From there on you could follow the steps again exactly where we left off except in the new window, and at the end of the save.php file when the image has been generated and saved, you can use a javascript call: self.close() to close that new window.

We need this new window to pop up so that the canvas can be processed properly with the SVG data.

  • canvg with Internet Explorer 8 (Chrome/Firefox worked) was unable to read images that were generated from a .php URL, to fix this I had to use PHP to save the "php url image contents" as a temporary image on the server and use that temporary image as a reference for the SVG data by replacing its original xlink:href.

  • canvas2png.js has a fall back in case your browser does support toDataURL, making this solution cross browser compatible

  • As a final note, I thought I'd include the quick method to export images if you're using a browser that supports toDataURL, which I would infer that the browser also supports SVG, and so the process to save an image is much easier (without the need of Flashcanvas hassle):

    1. Initiate an empty canvas
    2. Draw some SVG with Raphael
    3. Export the SVG string using Raphael Export
    4. Use canvg to parse the SVG data into the empty canvas
    5. Use canvas.toDataURL()
迷途知返 2024-10-08 04:40:09

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

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

You might want to look into generating your images on the server-side. Browser support for generating graphics is still pretty limited.

Node Canvas just came out and I've used ImageMagick in the past with great success.

清引 2024-10-08 04:40:08

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

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

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

然而,当您想要 PNG 时,您可能最好从一开始就选择画布,因为如果您随后要转换为位图,则可能不需要图形的矢量面。检查 canvas 和 google IE canvas 脚本,看看是否可以使用它。

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

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

RaphaelJS does not use canvas.
It uses VML in IE, but SVG in all other browsers.

As the OP said, you can grab the raw SVG (as it's a whole SVG doc) and download that, he is looking for some similar functionality with VML.

The only way I could think to do it, is get IE to send the VML data (if that is even possible) back to a server which does the conversion to PNG and downloads it.

However, as you want a PNG, you are probably better going for canvas from the start as you likely don't need the vector side of the graphics if you are then converting to bitmap. Checkout canvas and the google IE canvas script to see if you can use that instead.

As for "Browser support for generating graphics is still pretty limited", it isn't. Check out RaphaelJS.com demos, it's perfectly feasible and a good solution. The only problem is IE <9 which hasn't adopted any modern technologies like HTML5, CSS3 or SVG.

Anything which supports Canvas or the google IEcanvas can also produce decent results.

伴随着你 2024-10-08 04:40:08

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

另一种解决方案是使用 Internet Explorer 的 ActiveX 解决方案,该解决方案可以从 VML 生成图像。其中一种解决方案是 HTML 快照 ActiveX 组件

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

Raphaël uses VML in Internet Explorer and SVG in all other browsers. Canvas has built-in ability to export as an image, where as such feature is not built in VML. You can use server-side code to achieve the same for non-supported browsers.

An alternative solution is to use ActiveX solutions for Internet Explorer that can generate an image from VML. One such solution is HTML Snapshot ActiveX Component.

Generally, it is not recommend to implement ActiveX solutions unless it is an absolute necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文