Преобразование полигона SVG в путь
У меня есть довольно большой файл SVG административных подразделений, с которым мне нужно работать в Raphael.JS(у него 600 полигонов и вес 1,2 Мб).
Теперь мне нужно преобразовать эти полигоны в пути, чтобы они работали в Рафаэле. Великий инструмент poly2path делает это, но не поддерживает какую-либо командную команду, так что каждая позиция многоугольника относительно остальных теряется.
Знаете ли вы о каком-либо инструменте для преобразования полигонов SVG в пути? (У меня также есть файл AI, который использовался для экспорта SVG).
Большое спасибо
Ответы
Ответ 1
- Откройте ваш SVG в веб-браузере.
-
Запустите этот код:
var polys = document.querySelectorAll('polygon,polyline');
[].forEach.call(polys,convertPolyToPath);
function convertPolyToPath(poly){
var svgNS = poly.ownerSVGElement.namespaceURI;
var path = document.createElementNS(svgNS,'path');
var pathdata = 'M '+poly.getAttribute('points');
if (poly.tagName=='polygon') pathdata+='z';
path.setAttribute('d',pathdata);
poly.parentNode.replaceChild(path,poly);
}
-
Используя средства разработчика (или Firebug) браузера, используйте "Скопировать как HTML" (или скопировать SVG) в элемент, чтобы получить измененный источник в буфер обмена.
-
Вставьте новый файл и наслаждайтесь.
У меня есть демонстрационный пример вышеупомянутого метода (слегка измененный) на моем сайте:
http://phrogz.net/svg/convert_polys_to_paths.svg
На этой странице используются два метода; один (как и выше) использует строковые методы для получения и установки точек; другой использует SVG DOM для доступа к точкам и установки команд пути.
Как отмечено @Interactive в комментариях, вы можете сделать это с помощью текстовых преобразований:
- Преобразуйте все
<polyline
и <polygon
в <path
- Измените все
points="
на d="M
-
Для любых элементов, которые были <polygon>
, вам нужно добавить z
в качестве последнего символа атрибута d
для подключения последней точки к первой. Например:
<polygon points="1,2 3,-4 5,6"/>
становится
<path d="M1,2 3,-4 5,6z"/>
Этот "взлом" работает, потому что спецификации объявляют, что команда moveto
(M
или M
), за которой следуют несколько координат, является законной, причем все координаты после первого интерпретируются как команды lineto
.
Ответ 2
Копирование всего из инструментов разработчика кажется довольно неудобным. Вы можете использовать XSLT для преобразования полигонов и полилиний в пути:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" exclude-result-prefixes="svg"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<!-- Identity transform: Copy everything
(except for polygon/polyline, handled below) -->
<xsl:template match="@*|node()">
<xsl:copy>
<xsl:apply-templates select="@*|node()"/>
</xsl:copy>
</xsl:template>
<!-- Turn polygons/polylines into paths,
copy all attributes and content
(except for @points: Will be matched
by template below) -->
<xsl:template match="svg:polygon|svg:polyline">
<path>
<xsl:apply-templates select="@*|node()"/>
</path>
</xsl:template>
<!-- Turn the points attribute into a d attribute -->
<xsl:template match="@points">
<xsl:attribute name="d">
<xsl:value-of select="concat('M',.)"/>
<!-- If we have a polygon, we need to make
this a closed path by appending "z" -->
<xsl:if test="parent::svg:polygon">
<xsl:value-of select="'z'"/>
</xsl:if>
</xsl:attribute>
</xsl:template>
</xsl:stylesheet>
Любые атрибуты элементов многоугольника/полилинии будут перенесены в элемент пути. Это также подходит для пакетной обработки. Вы можете запустить это с помощью любого XSLT-процессора (Saxon, Xalan, xsltproc, Altova...) или даже в браузере, используя объект XSLTProcessor
, например:
var xsltProcessor = new XSLTProcessor();
xsltProcessor.importStylesheet(stylesheet);
var transformedSVG = xsltProcessor.transformToFragment(svgDocument).firstChild
(Аналогичный вопрос: Примеры полигонов, нарисованных путем пути к полигону в SVG)
Ответ 3
Маленькое исправление для атрибутов идентификатора многоугольника, заливки и штриха сохранения
var polys = document.querySelectorAll('polygon,polyline');
[].forEach.call(polys,convertPolyToPath);
function convertPolyToPath(poly){
var svgNS = poly.ownerSVGElement.namespaceURI;
var path = document.createElementNS(svgNS,'path');
var points = poly.getAttribute('points').split(/\s+|,/);
var x0=points.shift(), y0=points.shift();
var pathdata = 'M'+x0+','+y0+'L'+points.join(' ');
if (poly.tagName=='polygon') pathdata+='z';
path.setAttribute('id',poly.getAttribute('id'));
path.setAttribute('fill',poly.getAttribute('fill'));
path.setAttribute('stroke',poly.getAttribute('stroke'));
path.setAttribute('d',pathdata);
poly.parentNode.replaceChild(path,poly);
}
Ответ 4
Ответ на щелчок:
- открыть svg в редакторе векторной графики inkscape
- выберите все объекты (ctrl-a)
- в выпадающем пункте меню "путь" выберите первую запись "объект в путь" (shift-ctrl-c)
- сохранить svg и проверить свойства пути
Не может быть подходящего ответа (потому что с большими файлами программа нуждается в некотором времени).