使用Javascript扩展和侵蚀SVG形状

时间:2012-10-02 04:08:02

标签: javascript svg geometry

编辑:

我终于找到了一种侵蚀和扩张多边形(偏移)的方法,以便使用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

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

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

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

EDIT2:可能的解决方法:本页面的答案之一让我使用可变宽度笔划和蒙版来实现这个问题的一个好看的解决方法。我做了一些测试并实施not so good looking results

2 个答案:

答案 0 :(得分:1)

您是否真的测试过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过滤器上有一些剪辑似乎无法通过增加过滤器区域来解决,但除此之外,它非常接近于插图画家渲染。肯定比服务器端渲染。

http://jsfiddle.net/5Qv5v/

答案 1 :(得分:1)

您可以通过与clip-pathmask结合使用不同的笔触宽度来获得您的样子。这是example,有关如何构建的一些解释,请参阅herehere(向上或向下箭头以查看该示例中的其他幻灯片)。

它不会给你新的几何,只是看起来像新几何的东西。