【问题标题】:Scale independent elements缩放独立元素
【发布时间】:2012-05-23 13:37:30
【问题描述】:

我正在开发一个 (2D) 计算几何库,我希望能够吐出图片来帮助调试。我想要的图元是点、线段和文本。但我事先不知道我有兴趣查看什么比例(可能只有一小部分多边形不能正常工作),所以我还需要能够缩放和平移图像。

当我在 Chrome 中查看生成的图像时,我连接了 SVGPan 以平移和缩放生成的图像,但是(可以理解)所有基元都随着缩放进行缩放,因为 SVGPan 仅通过使用缩放变换来工作。所以放大并不能帮助弄清楚非常小的特征区域发生了什么。

我找到了vector-effect 属性,它通过让我指定以像素为单位的宽度来很好地修复线段。但这并不能帮助我管理文本。理想情况下,无论变换比例有多大,它都是 12 pt。

而且我仍然对绘制点一无所知。我以为我可以使用圆圈,但半径也会缩放,所以如果你放大得太远,它看起来就像一堆圆圈而不是点。如果我使用矢量效果属性,圆的笔画宽度将不再缩放,但圆的半径仍然存在。所以我最终得到了带有细轮廓的大圆圈,而不是半径一两个像素的小圆圈。

有没有办法只缩放元素的位置,也许?我真的总是希望线条、点和文本无论比例如何都显示相同的大小,并且只有它们的位置比例。我的 SVG 文件都是机器生成的,严格来说是为了帮助我编码,所以我不介意奇怪的 hack,如果有人有任何想法的话。或者,如果有另一种技术而不是 SVG 对这个用例更有意义。

【问题讨论】:

标签: svg


【解决方案1】:

我已经在这些问题中更深入地回答了这个问题:

简而言之,您希望 (a) 使用 transform="translate(…,…) 来定位未缩放元素,并且 (b) 每次调整某些包装器上的转换时(如 SVGPan 所做的),将您想要不缩放的每个元素传递给此函数:

// Copyright 2012 © Gavin Kistner, !@phrogz.net
// License: http://phrogz.net/JS/_ReuseLicense.txt

// Counteracts all transforms applied above an element.
// Apply a translation to the element to have it remain at a local position
function unscale(el){
  var svg = el.ownerSVGElement;
  var xf = el.scaleIndependentXForm;
  if (!xf){
    // Keep a single transform matrix in the stack for fighting transformations
    xf = el.scaleIndependentXForm = svg.createSVGTransform();
    // Be sure to apply this transform after existing transforms (translate)
    el.transform.baseVal.appendItem(xf);
  }
  var m = svg.getTransformToElement(el.parentNode);
  m.e = m.f = 0; // Ignore (preserve) any translations done up to this point
  xf.setMatrix(m);
}

上面第一个问题的答案还描述了一个设计用于直接与 SVGPan 一起工作的辅助方法,因此您所要做的就是包含我的库(两个函数),为每个标记添加一个 noscale 类,然后编写类似:

unscaleEach('#viewport .noscale');

【讨论】:

  • 谢谢,这确实是我想要的。除了我注意到,如果有一个带有缩放变换的包装组,它会缩放非缩放元素,直到你用鼠标滚轮放大/缩小。查看您的代码这是有道理的,因为代码只能通过附加到鼠标滚轮事件来运行。有没有办法让 unscaleEach 脚本在首次加载 SVG 文档时运行?
  • @Jay 当然;如果你看一下代码,它所做的就是var r = getRoot(evt.target.ownerDocument); [].forEach.call(r.querySelectorAll(selector), unscale); 所以你可以随时在任何你想要的元素上调用unscale
  • 我通过在unscaleEach 函数的末尾添加[].forEach.call(getRoot(window.root).querySelectorAll(selector), unscale); 让它工作。它的工作方式与我现在想要的完全一样;再次感谢!
猜你喜欢
  • 1970-01-01
  • 2010-09-16
  • 1970-01-01
  • 1970-01-01
  • 2020-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多