#svg #svg.js
#svg #svg.js
Вопрос:
вот пример SVG:
<svg xmlns="http://www.w3.org/2000/svg" version="1.1">
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="78" y1="269.543" x2="237" y2="269.543">......</linearGradient>
<symbol id="test" viewBox="-16.126 -14.41 32.251 28.819">...</symbol>
<rect x="78" y="203.043" style="fill:url(#SVGID_1_);" width="159" height="133"/>
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
<g>
<use xlink:href="#test" width="32.251" height="28.819" x="-16.126" y="-14.41" transform="matrix(1 0 0 -1 402.9284 846.39)" style="overflow:visible;"></use>
</g>
</svg>
Я хочу извлечь три подэлемента: rect
, circle
, g
, однако, вы знаете, rect
ссылается linearGradient
и g
ссылается symbol
, как извлечь один элемент вместе с его ссылочными элементами?
Ответ №1:
На самом деле я когда-то делал реализацию для node.js библиотека. Полный исходный код см. в svg-icon-toolbox. Он не использует svg.js , но cheerio, библиотека, похожая на jQuery, для анализа XML-источников и управления ими.
Принцип, по которому он работает, аналогичен принципу сборщика мусора: все, что не помечено как допустимая ссылка, подметается и удаляется.
Определите элемент, который будет сохранен, с его идентификатором.
var cheerio = require('cheerio');
// elements always removed
const remove = [
'animate',
'animateColor',
'animateMotion',
'animateTransform',
'cursor',
'script',
'set'
].join(',');
// elements always preserved
const preserve = [
'color-profile',
'font'
].join(',');
// elements whose links are ignored
const ignore = [
'a',
'altGlyph'
].join(',');
// removes everything not needed for a single icon export
function reduceTo ($copy, id) {
var reflist = new Set();
//mark elements for preservation
function mark (ref) {
var $target = $copy.find(ref);
//avoid doubles
if (!$target.parents(preserve).length amp;amp; !reflist.has(ref)) {
reflist.add(ref);
//mark for preservation
$target.prop('refby', id);
//mark as having preserved children
$target.parentsUntil('svg').prop('passedby', id);
}
//find links
$target.find('*').addBack() // descendents and self
.add($target.parents()) // parents
.not([remove, ignore, preserve].join(','))
.each((i, el) => {
var $elem = $(el);
//unpack links and recurse
var link = $elem.attr('xlink:href');
if(link) {
mark(link);
}
funcProps.forEach((prop) => {
var value = $elem.css(prop) || $elem.attr(prop);
link = funcRegex.exec(value);
if (link) {
mark(link[1]);
}
});
});
}
//remove elements not needed
function sweep ($inspect) {
//filter out elements generally preserved
$inspect.children().not(preserve).each((i, el) => {
var $child = $(el);
//elements with children to be preserved: recurse
if ($child.prop('passedby') === id amp;amp; $child.prop('refby') !== id) {
sweep($child);
//elements without mark: remove
} else if ($child.is(remove) || $child.prop('refby') !== id) {
$child.remove();
}
});
}
mark('#' id);
sweep($copy);
return $copy;
}
var $ = cheerio.load(svgString, { xmlMode: true });
var reduced = reduceTo ($, id);
var serialized = $.xml();