Is it possible to work with jquery and Svg directly (no plugins)?

Asked
Active3 hr before
Viewed126 times

4 Answers

possible
90%

I'm trying to work with Jquery and Svg together. But I don´t want to use any plugin. , possible duplicate of jquery's append not working with svg element? – givanse Feb 22 '14 at 20:53 , Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers , Stack Overflow Public questions & answers

Haven't been able to try, but I bet this would work. Instead of

$(mySvg).append("
<circle />");

Do

$(mySvg).append(document.createElementNS("http://www.w3.org/2000/svg", "circle"));

If you plan on doing this more than once, maybe

function svgEl(tagName) {
   return document.createElementNS("http://www.w3.org/2000/svg", tagName);
}

$(mySvg).append(svgEl("circle"));
load more v
88%

The problem I am dealing now is that when I try to work using the traditional append mode to add a child to the svg document, the object is not rendered. Let´s check out what I tried to do:,In case you haven't worked something out since March (and for anyone else having this problem), try getBoundingClientRect() on your SVG node.,Returns a ClientRect object that gives you top, bottom, left, right, width, and height relative to the document. Was able to use this to position Twitter Bootstrap popovers (divs) next to SVG rects.,This is the same as the old trick of getting better performance via $(document.createElement("div")) instead of $("<div />").

The problem I am dealing now is that when I try to work using the traditional append mode to add a child to the svg document, the object is not rendered. Let´s check out what I tried to do:

/* Creating the svg container using pure JS */
var container = document.getElementById("svg_space");
mySvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
mySvg.setAttribute("version", "1.2");
mySvg.setAttribute("baseProfile", "tiny");
container.appendChild(mySvg);

/* Adding a child and setting attributes to the SVG container using pure JS */
Circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
Circle.setAttribute("cx", "60");
Circle.setAttribute("cy", "30");
Circle.setAttribute("r", "13");
Circle.setAttribute("class", "class1");
mySvg.appendChild(Circle); /* After this, the circle is rendered */

/* Then, I tried to use jQuery to perform the same action... */
$(mySvg).append("
<circle />");
$(mySvg).find("circle").attr("cx","160");
$(mySvg).find("circle").attr("cy","70");
$(mySvg).find("circle").attr("r","30");
$(mySvg).find("circle").attr("class","class1" );
load more v
72%

Of course, this only works for simple, one-color icons. If you want more nuanced control, you’ll need to get into the code and get to know the SVG style cascade rules.,svg-builder/Gruntfile.js a working Grunt configuration customized specifically for inline SVG,The biggest downside of using an external SVG is that you can’t finely control the CSS colors of the individual SVG elements.,If you’re wondering about the $patchCurrentColorForIE parameter, I have that there for the icons that won’t require multiple colors, and thus don’t need the shim applied.

In order to achieve caching using an external SVG file (you seriously don’t want to dump ~1.5kb * 50 icons on your page in a non-cacheable way right?!), you need to include the svg4everybody library on your page. Essentially, this shiv will use UA sniffing to detect if you’re running a “problemattic version” of IE or Android that doesn’t properly cache external definitions files, and, if so, removes all svg use elements, and replaces them with embedded elements containing the corresponding SVG definition data pulled in via ajax. At the end of the day, we just care about the fact that our original SVG that might have looked like:

<svg viewBox="0 0 16 16">
   <use xlink:href="/path/to/svgdef.svg#your-icon" …></use>
</svg>

Will get replaced with an embedded element that looks something like this:

<svg viewBox="0 0 16 16">
   <path> ... </path>
</svg>

Just to make the above points crystal clear, here’s a CSS selector that would work in browsers that fully support external SVG definitions but fails when svg4everybody pollyfills IE:

.my - svg use {
   fill: red;
}

It turns out there’s no real need or gain to target use, so just change that to the following to work for all cases:

.my - svg {
   fill: red;
}

While we’re talking about selectors, we should take this opportunity to point out you won’t be able to “reach in” to original SVG definition with something like:

svg.parent path.child {
   /* won't work! */ }
  • If you don’t define a fill or stroke, or, you define only a fill, but that fill is black (completely black as in #000), the exported SVG paths and shapes will not contain a fill or stroke attribute:
<path ... positional information ...>
   <rect ... positional information ...>
  • If you define a non-black fill, or, if you define a stroke (of any color including black), the exported SVG’s corresponding paths and shapes will contain stroke and/or fill attributes like:
<path stroke="#000000" ...>
   <rect fill="fabdad" ...>

In this first example (note I’m using SCSS syntax), we apply a CSS fill and stroke to the cloned instance:

.filled - instance {
   stroke: #cc8ac1;
   stroke - width: 5 px;
   fill: lighten(#cc8ac1, 20 % );
}

You’ll also be able to achieve an outlined effect by simply turning off the fill and applying a stroke via CSS:

.filled - instance - off {
   stroke: #d08aaf;
   stroke - width: 5 px;
   fill: transparent;
}

So the bad news here, is that you cannot apply a style to the stroke on the cloned instance (remember, our cloned instance, in this example, in turn, points to an SVG def that we created with “stroke only”). We can’t apply a fill to our cloned instance either, since our SVG shapes now have fill="none" on them and that will take precedence):

.stroked - instance {
   stroke: green; /* nothing happens */
   fill: red; /* nothing happens */
}

It’s similar to HTML/CSS, like:

<div id="very-strong">
   <span>still green.</span>
</div>
#very - strong {
   color: red;
}
span {
   color: green;
} /* I'm the actual element, so I win. */

You probably should just avoid this situation altogether by exporting black fills with transparent strokes, or just paths, but, if you, for some reason, do still need to have your styles take affect, you’ll instead have to style the SVG symbol directly with something like:

symbol #completed - copy - stroked[stroke] {
   stroke: #dd6435;
   stroke - width: 5 px;
}

Another technique you can always use, is to just add classes within the source SVG and apply CSS to those directly. These styles will be global which may or may not be a problem–you’ll have to decide that for your case. This technique works regardless of how you exported the SVG. Because you’re hand adding a CSS class, it’s there for you to hook into (albeit directly–we’re targetting the SVG definition’s sub-element directly and not styling through a cloned instance):

.ibestrokin {
   stroke: magenta;
   stroke - width: 5 px;
}
.istrokeittotheeast {
   stroke: green;
   stroke - width: 7 px;
}

We start with our base fill which might look something like:

.icon - primary {
      fill: #ccc;
      color: #3bafda;
}

Those classes would get dropped on the non-exposed svg clone instance:

<svg class="icon-primary"> ...

Now here’s where the magic starts to happen–our fill defines the icon’s general fill color (in this case #cc), but now our font color defines the inherited accent color we defined as described above like:

<path fill="currentColor" ... />

I’ve created a Sass mixin (purposely compatible down to 3.2) for doing this:

@mixin svgColors($fill: false, $color: false, $patchCurrentColorForIE: false) {
   @if $fill {
      fill: $fill;
   }
   @if $color {
      color: $color;
   }
}

And I call it with something like:

.icon - primary {
   @include svgColors($neutralColor, $primaryColor, true);
}

If you’ve included jQuery on your page, clicking directly on a rendered svg use element will likely result in jQuery throwing an error that’s documented in their bug tracker. It’s actually a bit tricky to reproduce this bug since you’ll likely have a containing block element that serves as an anchor or button–and that element will have the larger hit area–but, again, it happens if you click directly on the icon itself. Here’s the preferred workaround:

svg {
   pointer - events: none;
}

Depending on how your system is set up, you may need to use sudo before the two npm install commands below

# Install the Buttons example and set up npm dependencies
git clone - b svg - inline - experiments--single - branch https: //github.com/unicorn-ui/Buttons.git Buttons && cd Buttons && npm install

   # Install the SVG specific dependencies and run example
pushd svg - builder && npm install && grunt && popd && grunt dev
load more v
65%

jQuery Color SVG Color Names 2.2.0 - uncompressed, minified,jQuery Color 2.2.0 - uncompressed, minified, Showing the latest stable release for jQuery Color. See all versions of jQuery Color. ,jQuery Core 2.2.4 - uncompressed, minified

<script
			  src="{{link}}"
			  integrity="{{hash}}"
			  crossorigin="anonymous"></script>
		
load more v

Other "possible-undefined" queries related to "Is it possible to work with jquery and Svg directly (no plugins)?"