通过片段标识符或视图规范嵌入HTML的外部SVG文档的非标准视图:如何操作viewBox?

fsavigny

注意:这个问题已被实质性地重写,一方面使所有内容都更加简洁,但另一方面可能会剥夺其上下文的某些评论。我希望对话仍然可以理解。

我将SVG图像嵌入<object>sHTML页面中,并使用JavaScript使其可缩放和平移,其中所有事件处理程序均在rootElement每个对象的上调用contentDocument,即<svg>,并操纵其viewBox.baseVal属性。

下面是一个最小的工作示例(简化为平移功能)。我们有一个名为的SVG文件circle_and_rectangle.svg

<svg style="background: white" viewBox="0 0 300 300" xmlns="http://www.w3.org/2000/svg">
  <rect x="0.5" y="0.5" width="299" height="299" style="fill:grey"/>
  <circle cx="150" cy="150" r="75" style="fill:red"/>
</svg>

还有一个HTML文件,该文件在<object>元素中导入了此SVG文件

<!DOCTYPE html>
<title>External SVG embedding</title>
<script>
  window.onload = function () {
    svgRoot = document.getElementById('foo').contentDocument.rootElement
    svgRoot.addEventListener('mousedown', activatePanning,   false);
    svgRoot.addEventListener('mouseup',   deactivatePanning, false);
  }
 
  function activatePanning (event) {
    this.addEventListener('mousemove', panOnMouseMove, false)
  }

  function panOnMouseMove (event) {
    baseVal = this.viewBox.baseVal
    baseVal.x -= (event.movementX / this.clientWidth)  * baseVal.width
    baseVal.y -= (event.movementY / this.clientHeight) * baseVal.height
  }

  function deactivatePanning (event) {
    this.removeEventListener('mousemove', panOnMouseMove, false)
  }
</script>

<object id="foo" style="width:400px;height:300px;border: 1px solid green"
    type="image/svg+xml" data="circle_and_rectangle.svg">
</object>

如预期的那样,这显示了一个红色圆圈,紧贴灰色方块(在稍宽的绿色框内),可以用鼠标来回拖动。

注意:仅当通过服务器(在Web或本地计算机上)访问文件时,此方法才有效。(有关详细信息,请参阅评论。一旦找到一个无需Facebook等即可注册的工具,我会将其放在合适的代码共享网站上。)

现在,我发现如果仅嵌入SVG图像的部分视图将非常有用,而SVG可以通过以下两种方法之一实现(为了简洁起见,我省略了必需的属性):

<object ... data="circle_and_rectangle.svg#svgView(viewBox(75,75,150,150))"></object>

<!-- or, the SVG contains: -->
<view id="closeup" viewBox="75 75 150 150" />
<!-- and the HTML, instead of the above: -->
<object ... data="circle_and_rectangle.svg#closeup"></object>

如预期的那样,要么导致红色圆圈的特写(或放大)视图。但是,平移不再起作用图像是固定的。检查时:

  • 如上所述访问的viewBox值(的contentDocument.rootElement.viewBox.baseVal属性<object>)是所述根元素标准值<svg>(即0 0 300 300,其viewBox属性中的),而不是浏览器实际使用并直接在URI resp中指定的viewBox的值在引用的<view>元素中。
  • 这些值确实会像以前一样由处理程序操纵,但是不再具有任何可见效果

无论使用的是视图规范(#svgView(...))还是片段标识符(#closeup)与<view id="closeup">SVG中的相应元素,所描述的行为在Chrome和Firefox(在Linux中)相同

我在的contentElement大部分时间里都在,及其rootElementJavaScript引用以及MDN和Web上搜索了DOM ,但是在以下两个问题上没有任何实质性的实现:

  • 如何访问上述方案中实际使用的viewBox值(因为显然没有标准viewBox)?
  • 究竟是什么导致处理程序无法正常工作?由于他们还是操纵的视框中的值<svg>元素:这是确实简单,他们现在就错视框操作?
  • 更一般而言,在这种非标准视图中加载SVG时,是否有任何可靠的平移和缩放方式?
海道

当您使用非默认视图(<view>#svgView())时,将使用其参数代替根元素的参数。

因此,如果viewBox通过此视图设置参数viewBox则将丢弃根元素,并且对其进行编辑不会更改任何内容。

以前在SVG1.1中定义SVGSVGElement.currentView属性,但是在SVG2中删除了它,在流行的现代浏览器中,只有Safari才实现了它。

由于没有干净的API可以处理它,因此您需要检查一下location.hash它是否指向此类视图,然后对其进行编辑或指向的元素,以进行一些处理。

但是,如果我正确理解了您的情况,则可以完全控制svg,并且可以肯定会使用这种视图,因此,最简单的方法可能是使用一个<view>元素,然后编辑其viewBox属性,但Chrome浏览器存在问题并且不会在发生这种情况时更新视图...

这是一个实时代码段,其中的版本是从svg文档本身内部制作的,因为StackSnippets iframe不允许访问仅在Firefox中可用的内部文档

const svg_content = `
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" >
  <view id="my_view" viewBox="0 0 400 400" />
  <rect fill="red" x="0" y="0" width="20" height="20"/>
  <script>
    onmousemove = (evt) => {
      const view = document.getElementById("my_view");
      const viewBox = view.viewBox.baseVal;
      viewBox.x = evt.clientX * -1;
      viewBox.y = evt.clientY * -1;
    };
  <\/script>
</svg>`;
const blob = new Blob([svg_content], { type: "image/svg+xml" });
const url = URL.createObjectURL(blob);
const object = document.getElementById("obj");
object.data = url + "#my_view";
object {
  border: 1px solid;
}
<object id="obj"></object>

即使改变<object>data与更新#svgView()将在浏览器不工作,显然崩溃解析器...

因此,很抱歉成为这样一个告诉您的人,但是似乎没有任何跨浏览器的方式可以完成您想要的事情。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章