【问题标题】:Dilate and erode SVG shapes using Javascript使用 Javascript 扩张和侵蚀 SVG 形状
【发布时间】:2012-09-22 23:00:38
【问题描述】:

编辑:

我终于找到了一种侵蚀和扩张多边形(偏移)的方法,以便使用 Clipper 库创建新的几何图形: https://sourceforge.net/projects/jsclipper/

Javascript Clipper 现场演示: http://jsclipper.sourceforge.net/5.0.2.1/main_demo.html

Clipper 只能处理多边形或多多边形(例如带孔的多边形),因此要与其他 SVG 格式的图形对象一起使用,必须将它们转换为直线。至少使用path.getTotalLength()path.getPointAtLength() (http://whaticode.com/2012/02/01/converting-svg-paths-to-polygons/) 将路径转换为行相当容易。

另一种可能性是使用类似技术(不会创建新几何): https://stackoverflow.com/a/12723835/1691517


有什么方法可以通过 Javascript 腐蚀和扩张 SVG 中的形状?

我有以下 SVG 示例: http://jsfiddle.net/timo2012/2S4Kt/1/

共有三种形状,蓝色是原始的,绿色是侵蚀的(变细的),红色是扩张的(加粗的)。它们是在 Illustrator 中制作的。

我测试过侵蚀和扩张过滤器,但效果不太好: https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/examples/feMorphology.svg

在互联网上搜索了几个小时后,我只找到了有关位图图像侵蚀和膨胀的示例,但没有找到有关矢量形状的示例。

我已经成功地在 Python 中使用 Shapely (http://toblerity.github.com/shapely/manual.html) 扩展和侵蚀 SVG 多边形,方法是通过 Ajax 调用向 PHP 脚本发送路径点,从而使 system() 调用 Python 脚本,但是这种方法很慢并且需要服务器做客户端可以做的工作。

这是我在 Python 中用于膨胀和腐蚀的代码(如您所见,它很短):

#!/usr/bin/python26

from shapely.geometry import Polygon
from shapely.geometry import MultiPolygon

import sys

if len(sys.argv)>2:
  inset=eval(sys.argv[1])
  coords=eval(sys.argv[2])
else:
  sys.exit()

bowtie = Polygon(coords)
clean = bowtie.buffer(inset)
clean = clean.simplify(1, preserve_topology=False)
if clean.length>0:
  if clean.geom_type=="MultiPolygon":
    for n in range(0, len(clean)):
      print list(clean[n].exterior.coords)
      #print "\n"
  elif clean.geom_type=="Polygon":
    print list(clean.exterior.coords)

还可以找到这个文档,它试图用数学术语定义扩张和腐蚀: http://en.wikipedia.org/wiki/Mathematical_morphology

有一句话“二值形态学的基本思想是用一个简单的、预定义的形状探测图像,得出这个形状如何适合或错过图像中的形状的结论。这个简单的“探测”被称为结构元素,它本身就是一个二值图像(即空间或网格的子集)。”

我假设这种方法可以用于变形矢量形状,但是如何...

编辑:回复中的一条评论提出了使用过滤器而不是创建新几何体的可能问题:如果有人想将拖动手柄添加到多边形点,那么拖动手柄可能似乎在错误的位置。这是可以接受的,因为给人的印象是原始路径数据没有受到影响,这实际上是过滤器中的情况,但是 - 经过进一步测试 - 证明质量是一个更大的问题。根据thisthis,SVG过滤器使用矢量图形对象的像素表示而不是路径数据本身,这导致not so good looking results

EDIT2:可能的解决方法:此页面中的一个答案使我使用可变宽度笔划和蒙版来实现此问题的美观解决方法。我做了一些测试并实现了an Adobe Illustrator -like Offset Path Effect

【问题讨论】:

    标签: javascript svg geometry


    【解决方案1】:

    您可以通过结合clip-pathmask 使用不同的笔划宽度来获得您想要的东西。这是一个example,有关它的构造方式的一些说明请参见herehere(向上或向下箭头以查看该示例的其他幻灯片)。

    但它并没有给你新的几何,只是一些看起来像新几何的东西。

    【讨论】:

    • 谢谢!我检查了这些,但如果多边形控制点必须是可拖动的,那么这种技术没有帮助,对吗?
    • 就像我写的那样,你不会从中得到任何新的几何图形,所以如果这是你需要的,那么这可能无济于事。您仍然可以在原始路径上有拖动手柄,这可能会影响其他细化/粗体路径。
    • 好的。似乎我正在寻找新的几何形状。但有点令人惊讶的是,这样的基本几何函数在谷歌搜索中找不到现成的十位。布尔函数也是如此。所有的数学家都在哪里?他们都应该编写这些函数! SVG 和 Javascript 很重要!
    • 我正在尝试将您的建议在现实中实现Illustrator中偏移路径的效果。笔画可以用来切割东西,还是只能用来填充形状?或者“不同的笔划宽度与剪辑路径或蒙版相结合”是什么意思?
    • 偏移路径正(扩张)不是什么大问题,因为我们可以将边框颜色定义为与填充颜色相同。抵消负(侵蚀)是一个更大的问题。可以简单的通过让边框颜色透明来实现吗?
    【解决方案2】:

    您是否实际测试过 SVG 的原生过滤器?这看起来很接近:

    <svg width="612" height="792" viewBox="0 0 612 792" xmlns="http://www.w3.org/2000/svg">
    
      <defs>
        <filter id="erode">
          <feMorphology operator="erode" in="SourceGraphic" radius="12" />
        </filter>
        <filter id="dilate">
          <feMorphology operator="dilate" in="SourceGraphic" radius="8" />
        </filter>
          <path id="original_path" d="M193.193,85c23.44,0.647,45.161,0.774,62,12c1.596,1.064,12,11.505,12,13
        c0,2.941,8.191,5.669,3,12c-3.088,3.767-6.01-0.758-11-1c-19.56-0.948-33.241,12.296-33,34c0.163,14.698,8.114,24.492,4,41
        c-1.408,5.649-6.571,15.857-10,21c-2.484,3.726-7.898,10.784-12,13c-4.115-11.677,2.686-27.29-6-35c-6.693-5.942-20.021-4.051-26,1
        c-13.573,11.466-11.885,41.492-7,58c-5.8,1.772-18.938,7.685-23,12c-6.752-10.805-15.333-17.333-24-26c-3.307-3.307-9.371-12-15-12
        c-16.772,0-13.963-15.741-13-28c1.283-16.324,1.727-28.24,4-42c1.276-7.72,8-16.411,8-23c0-7.416,15.945-29,23-29
        c4.507,0,17.678-8.701,24-11C164.853,90.76,178.27,88.546,193.193,85"/>
      </defs>
      <use xlink:href="#original_path" fill="#f00" filter="url(#dilate)"></use>    
      <use xlink:href="#original_path" fill="blue"></use>
      <use xlink:href="#original_path" fill="#1CFF00" filter="url(#erode)"></use>    
    </svg>
    

    dilate 过滤器上有一些剪裁,似乎无法通过增加过滤器区域来解决,但除此之外,它非常接近您的 illustrator 渲染。当然胜过渲染服务器端。

    http://jsfiddle.net/5Qv5v/

    【讨论】:

    • 感谢您的努力!过滤器不是很糟糕,但仍然不适合所有情况。如果我们将拖动手柄添加到多边形点,基于过滤器的解决方案如何适应它?
    • 如果这是您的用例,那么您应该在问题中说明。
    • 添加了这个。我差点忘了 svg 也可以用作没有交互性的普通图像 :) 感谢提醒!
    • jsfiddle.net/5Qv5v 中的上述过滤器解决方案似乎不适用于 iPhone4 Safari。只有绿色路径可见。按照约定,jsfiddle.net/timo2012/2S4Kt/1 中基于几何的解决方案适用于该平台。
    • 众所周知,iOS caniuse.com/svg-filters,请不要在问题上堆砌要求。
    猜你喜欢
    • 2019-06-21
    • 2012-09-24
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-15
    • 2014-02-23
    • 2011-06-17
    相关资源
    最近更新 更多