使用Javascript扩大和侵蚀SVG形状 [英] Dilate and erode SVG shapes using Javascript
问题描述
我最终发现了一种腐蚀和扩大多边形(偏移)的方法,以便使用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()
(< href =http://whaticode.com/2012/02/01/converting-svg-paths-to-polygons/ =nofollow noreferrer> http://whaticode.com/2012/02/01/01转换-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
经过几个小时搜索互联网,我发现只有位图图像腐蚀和扩大的例子,但没有关于矢量
我成功地使用Shapely扩展和侵蚀SVG多边形( 这是我在Python中扩展和腐蚀的代码(正如你看到的那样短): 另外找到这个文档,它尝试用数学术语来定义膨胀和腐蚀: 有一句话The bas二进制形态学中的思想是用简单的,预定义的形状探测图像,得出关于这种形状如何适合或错过图像形状的结论。这个简单的探测被称为结构元素,它本身就是一个二元图像(即空间或网格的一个子集)。 我认为这种方法可以用于变形矢量形状,但如何... ...编辑:在回复中的一个评论提出了使用过滤器,而不是创建新的几何可能的问题:如果有人想要将拖拽手柄添加到多边形点上,然后拖拽手柄看起来可能是错误的,这是可以接受的,因为这样的印象是原始路径数据是未触及的,这在滤波器中实际上是这种情况,但是 - 在进一步测试之后 - 它证明质量是一个更大的问题。根据这个和 SVG滤镜使用矢量图形对象的像素表示而不是路径数据本身,这导致不太好看的结果。 编辑2:可能的解决方法:此页面中的答案之一导致我使用可变宽度笔触和掩码来实现此问题的一个好看的解决方法。我做了一些测试,并实现了类似Adobe Illustrator的偏移路径效果。 你可以通过结合 虽然它不会给你新的几何体,只是可能看起来像新的几何体。 EDIT: I finally found a way to erode and dilate polygons (offsetting) so that new geometry is created using Clipper library:
https://sourceforge.net/projects/jsclipper/ Live demo of Javascript Clipper:
http://jsclipper.sourceforge.net/5.0.2.1/main_demo.html The Clipper can only handle polygons or multi-polygons (eg. polygons with holes), so for it to work with other graphical objects of SVG format, they have to be converted to straight lines. At least paths are rather easy to convert to lines using The other possibility is use this like technique (that does not create new geometry):
https://stackoverflow.com/a/12723835/1691517 Is there any way to erode and dilate shapes in SVG via Javascript? I have the following SVG example:
http://jsfiddle.net/timo2012/2S4Kt/1/ There are three shapes, blue is original, green is eroded (thinned) and red is dilated (bolded). They are made in Illustrator. I have tested erode and dilate filters, but the effect is not so good:
https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/examples/feMorphology.svg After few hours searching over internet, I have found only examples about bitmap image eroding and dilating, but nothing about vector shapes. I have succeeded in dilating and eroding SVG polygons using Shapely ( http://toblerity.github.com/shapely/manual.html ) in Python by sending path points via Ajax call to PHP script which makes system() call to Python script, but this method is slow and requires server to do the work that could be done client side. This is my code for dilating and eroding in Python (as you see it is quite short): Also find this document, which tries to define dilate and erode in mathematical terms:
http://en.wikipedia.org/wiki/Mathematical_morphology There is a sentence "The basic idea in binary morphology is to probe an image with a simple, pre-defined shape, drawing conclusions on how this shape fits or misses the shapes in the image. This simple "probe" is called structuring element, and is itself a binary image (i.e., a subset of the space or grid)." I assume that this method could be used in morphing vector shapes, but how... EDIT: One comment in a reply raised a possible issue of using filters instead of creating new geometry: if someone wants to add drag handles to polygon points, then drag handles may seem to be in wrong place. This can be acceptable, because then the impression is that the original path data is untouched, which is actually the case in filters, but - after further testing - it proved that the quality is a bigger problem. According to this and this SVG filter uses pixel representation of vector graphic object instead of path data itself, which leads to not so good looking results. EDIT2: POSSIBLE WORKAROUND: One of the answers in this page led me to use variable-width strokes and mask to achieve a good looking workaround to this issue. I made a few tests and get implemented an Adobe Illustrator -like Offset Path Effect. You can sort of get what you seem to be after by stroking with different stroke-widths in combination with It doesn't give you new geometry though, just something that might look like new geometry. 这篇关于使用Javascript扩大和侵蚀SVG形状的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
#!/ usr / bin / python26
from shapely.geometry从shapely.geometry中导入多边形
import MultiPolygon
import sys
$ b $ if len(sys.argv)> 2:
inset = eval(sys.argv [1])$ b $ b coords = eval(sys.argv [2])
else:
sys.exit()
bowtie =多边形(coords)
clean = bowtie.buffer(插入)
clean = clean.simplify(1,preserve_topology = False)
if clean.length> 0:
if clean.geom_type ==MultiPolygon:
for n in范围(0,len(clean)):
print list(clean [n] .exterior.coords)
#print\\\
elif clean.geom_type ==Polygon :
print list(clean.exterior.coords)
http://en.wikipedia.org/wiki / Mathematical_morphology
clip-path
或掩码
。这里有一个示例,对它的结构进行了一些解释,参见 here and 这里(向上或向下箭头查看其他一些内容这个例子中的幻灯片)。
path.getTotalLength()
and path.getPointAtLength()
(http://whaticode.com/2012/02/01/converting-svg-paths-to-polygons/).
#!/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)
clip-path
or mask
. Here's an example, some explanations of how it's constructed see here and here (arrow up or down to see some other slides on that example).