在浏览器中生成,查看和保存SVG客户端 [英] Generating, viewing, and saving SVG client-side in browser

查看:122
本文介绍了在浏览器中生成,查看和保存SVG客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个HTML5 + JS工具来生成SVG图像。我这样做时遇到了很多问题,虽然我对大多数问题都有解决方法,但至少在一个案例中我觉得必须有更好的方法。还有一些东西仍然只是正在工作。

I am writing a little HTML5+JS tool to generate an SVG image. I have encountered a number of issues in doing so, and while I have workarounds for most of them, in at least one case I feel like there must be a better way. And then there are a couple of things that still just aren't working.

目前,这是我自己使用的,所以交叉 - 浏览器兼容性不是问题;只要它适用于Firefox(首选)或Chromium,它就是好的。我希望一旦它正常工作就坚持在线,所以兼容性警告将不胜感激。

At present, this is for my own use, so cross-browser compatibility isn't a concern; as long as it works in Firefox (first preference) or Chromium, it's all good. I would like to stick it online once it's working right, though, so compatibility caveats would be appreciated.


  1. 所有处理都应该在客户端完成;事实上,在这个阶段,一切都是本地文件:// ,不涉及任何网络服务器。

  2. 添加文本和元素到使用脚本化表单元素的SVG图像(在HTML中内联)。

  3. 点击SVG(缩小到预览大小)以打开它,修改为新的窗口/标签。

  4. 使用一些易于访问的方法(即不是DOM检查器,复制到文本文件,保存)将SVG保存到磁盘。

  1. All processing should be done client-side; in fact, at this stage everything is a local file://, no web server involved.
  2. Add text and elements to an SVG image (inline in the HTML) using scripted form elements.
  3. Click on the SVG (which is shrunk down to a "preview" size) to open it, as modified, in a new window/tab.
  4. Use some easy-to-access method (i.e. not "DOM inspector, copy to text file, save") to save the SVG to disk.



测试用例



https://gist.github.com/perey/1d352a790f749aa05a8b 看到它在行动

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
  <head>
    <meta charset="utf-8"/>
    <title>SVG Generator</title>
    <style type="text/css">
      figure {
        width: 45%;
        float: right;
      }
      #output-pic {
        border: thin solid green;
        cursor: pointer;
      }
      form {
        width: 45%;
        float: left;
      }
    </style>
    <script>
      window.onload = function() {
        document.getElementById("input-box").oninput = update_text;
        document.getElementById("output-pic").onclick = show_svg;
        update_text();
      }
      function update_text() {
        var input_elem = document.getElementById("input-box");
        var output_elem = document.getElementById("changeable-text");
        output_elem.textContent = input_elem.value;
      }
      function show_svg() {
        var svg_win = window.open("", "svg_win");
        var embedded_svg = document.getElementById("output-pic");
        var transplanted_svg = svg_win.document.importNode(embedded_svg, true);
        var blank_root = svg_win.document.documentElement;
        svg_win.document.removeChild(blank_root);
        svg_win.document.appendChild(transplanted_svg);
      }
    </script>
  </head>
  <body>
    <figure role="img" aria-labelledby="preview-caption">
      <figcaption id="preview-caption">Preview <small>(click for full
        size)</small></figcaption>
      <svg id="output-pic"
           xmlns="http://www.w3.org/2000/svg"
           xmlns:xlink="http://www.w3.org/1999/xlink"
           version="1.1" width="640px" height="480px"
           viewBox="0 0 640 480" preserveAspectRatio="xMinYMin">
        <title>A test SVG file</title>
        <defs>
          <style type="text/css">
            text {
              font-family: serif;
              stroke: none;
              fill: red;
            }
            .underline {
              stroke: blue;
              stroke-width: 1;
              fill: none;
              marker-mid: url(#arrow);
            }
          </style>
          <marker id="arrow"
                  viewBox="-3 -3 6 6" orient="auto"
                  markerUnits="strokeWidth"
                  refX="0" refY="0"
                  markerWidth="6" markerHeight="6">
            <path d="M0,0 -3,-3 3,0 -3,3 Z"/>
          </marker>
        </defs>
        <text id="changeable-text" text-anchor="middle" font-size="40"
              x="320" y="240"></text>
        <path class="underline" d="M10,250 h310 310"/>
      </svg>
    </figure>
    <form>
      <label>Text: <input id="input-box"/></label>
    </form>
  </body>
</html>



问题



打开SVG



打开关于:空白,删除其文档元素,添加SVG元素,感觉非常hacky。然而,没有其他工作我只找到了一种在新窗口中构建文档的更好方法(见下文)。

Issues

Opening the SVG

Opening about:blank, deleting its document element, and adding the SVG element, feels really hacky. However, nothing else has worked I have only found a slightly better way of constructing a document in a new window (see below).

In特别是,我已经尝试加载一个准系统SVG文件并添加预览SVG的所有子节点,如下所示:

In particular, I've tried loading a barebones SVG file and adding all the child nodes of the preview SVG, like so:

function show_svg() {
    var svg_win = window.open("blank.svg", "svg_win");
    var embedded_svg = document.getElementById("output-pic");
    var transplanted_svg = svg_win.document.importNode(embedded_svg, true);
    var blank_root = svg_win.document.documentElement;

    while (transplanted_svg.hasChildNodes()) {
        blank_root.appendChild(transplanted_svg.firstChild);
    }
    svg_win.alert("Done!");
}

然而,在这个函数完成它之后,加载的文件然后擦除对它做出的所有改变并恢复到其原始状态。 (警告是为了强调这一事实:在Firefox中,当页面被擦除时,警报框本身就会消失而无需用户操作。在Chromium中,警告框挂起,但擦除是在它被解雇后发生的。)

However, after this function does its thing, the loaded file then "wipes" all changes made to it and reverts to its pristine state. (The alert is there to highlight this fact: in Firefox, the alert box itself disappears without user action when the page is "wiped". In Chromium, the alert box hangs about, but the wipe happens after it's dismissed.)

这不是将节点重新绑定到新窗口的 onload 处理程序。 是的。我第一次尝试时犯了一个错误。这就是我所做的:

It's not a matter of tying the node reparenting to the new window's onload handler. Yes it is. I made a mistake when I first tried that. Here's what I did:

function show_svg() {
    var svg_win = window.open("blank.svg", "svg_win");
    var embedded_svg = document.getElementById("output-pic");
    var transplanted_svg = svg_win.document.importNode(embedded_svg, true);
    var blank_root = svg_win.document.documentElement;

    svg_win.onload = function () {
        while (transplanted_svg.hasChildNodes()) {
            blank_root.appendChild(transplanted_svg.firstChild);
        }
        svg_win.alert("Done!");
    }
}

应该 done将 blank_root 的定义放在 onload 处理程序中。这很有效。

What I should've done is put the definition of blank_root inside the onload handler. That works.

尽管如此,仍然觉得应该有办法从头构建一个新文档。 修改空白SVG比修改 about:blank HTML更好,但这真的是最好的方法吗?

Still feels like there should be a way to construct a new document from scratch, though. "Modifying a blank SVG" is better than "modifying the about:blank HTML", but is that really the best way?

(这似乎只是Firefox的问题,而不是Chromium。)

(This only seems to be an issue with Firefox, not with Chromium.)

marker-mid 样式在预览图像中正常工作,但在打开的SVG中没有。我不知道为什么。 修改:修改SVG文件而不是 about:blank 没有此问题。我要提交一个错误,但我已经怀疑他们会说不要尝试将HTML文件动态转换为SVG文件。

The marker-mid styling works fine in the preview image, but not in the opened SVG. I have no idea why. Modifying an SVG file instead of about:blank doesn't have this issue. I'm off to file a bug, but I already suspect they're going to say "don't try and dynamically convert a HTML file into an SVG file".

我不知道如何做到这一点。一些诱人的提示似乎说它与Blob有关,但是我没有发现任何解决方案来保存生成的SVG文件客户端,我不明白他们做得多好以使它能够工作我。

I have no idea how to do this. A few tantalising hints seem to say that it's something to do with Blobs, but I've found nothing that addresses saving a generated SVG file client-side, and I don't understand what they're doing well enough to make it work for me.

任何帮助,建议,建议或更正?

Any help, suggestions, advice, or corrections?

推荐答案

我已经使用现代HTML5 API解决了我自己的问题。

I have solved my own problems, using modern HTML5 APIs.

新的 show_svg()函数看起来像这个:

The new show_svg() function looks like this:

function show_svg(evt) {
    var svg = document.getElementById("output-pic");
    var serializer = new XMLSerializer();
    var svg_blob = new Blob([serializer.serializeToString(svg)],
                            {'type': "image/svg+xml"});
    var url = URL.createObjectURL(svg_blob);

    var svg_win = window.open(url, "svg_win");
}

浏览器自己的保存功能将在这个新窗口上运行,并且不会涉及对感觉怪异或骇客的其他文件的任何修改。 (将SVG序列化只是为了再次在浏览器中查看它似乎有点奇怪,但这似乎是HTML5下的正确的东西。)

The browser's own Save functionality will work on this new window, and it doesn't involve any modifications to other files that "feel" weird or hacky. (It does seem a bit odd to serialise the SVG only to view it in the browser again, but this nonetheless seems to be The Right Thing under HTML5.)

唯一未解决的问题是消失的标记—事实上,问题变得更糟,因为现在< use> 元素也不起作用!但是,它们仍然存在并且在代码中起作用,因此一旦将SVG保存到文件中,文件中的所有内容都可以正常工作。而且我也向Mozilla提交了一个错误。

The only unresolved problem is the disappearing markers—in fact, the problem gets worse, as now <use> elements don't work either! However, they're still there and functional in the code, so once the SVG is saved to a file, everything in the file works fine. And I've filed a bug with Mozilla, too.

这篇关于在浏览器中生成,查看和保存SVG客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆