Related
I am trying to create a svg image with 2 paths, where the outer shape is filled with a color, while the inside one is not. I am using React, and the code is the following:
<SvgIcon
className={className}
nativeColor={theme.palette[color] ? theme.palette[color].main : color}
style={{
height: `${size}px`,
width: `${size}px`,
}}
viewBox="0 0 32 32">
<g fillRule="evenodd">
<path
d="M16,0 C9.372583,0 4,5.0144108 4,11.2 C4,19.6 16,32 16,32 C16,32 28,19.6 28,11.2 C28,5.0144108 22.627417,0 16,0 Z"
fill={color}
fillOpacity="1"
fillRule="nonzero"
stroke="none"
/>
<path
d="M15.5,4 L6,9.18181818 L15.5,14.3636364 L23.2727273,10.1231818 L23.2727273,16.0909091 L25,16.0909091 L25,9.18181818 M9.45454545,12.7918182 L9.45454545,16.2463636 L15.5,19.5454545 L21.5454545,16.2463636 L21.5454545,12.7918182 L15.5,16.0909091 L9.45454545,12.7918182 Z"
fill="none"
/>
</g>
This displays the entire shape filled, so the inner shape is not visible. However, if instead of fill="none" I have fill="#FFFFFF", this works, and I see the shape displayed. Any idea why and how I can fix it, without filling the inner shape with a color?
You will need to join the 2 d attributes in one and use fill-Rule="evenodd"
<svg
style="height: 100px"
viewBox="0 0 32 32">
<path
d="M16,0 C9.372583,0 4,5.0144108 4,11.2 C4,19.6 16,32 16,32 C16,32 28,19.6 28,11.2 C28,5.0144108 22.627417,0 16,0 Z
M15.5,4 L6,9.18181818 L15.5,14.3636364 L23.2727273,10.1231818 L23.2727273,16.0909091 L25,16.0909091 L25,9.18181818
M9.45454545,12.7918182 L9.45454545,16.2463636 L15.5,19.5454545 L21.5454545,16.2463636 L21.5454545,12.7918182 L15.5,16.0909091 L9.45454545,12.7918182 Z"
fill="red"
stroke="none"
fill-rule="evenodd"
/>
</svg>
I am trying to place an arrow on the midpoint of the bezier curve. The solution using <animateMotion> in the question How properly shift arrow head on cubic bezier in SVG to its center , which moves a <path> which is the arrow and freezes it at the middle of the bezier curve, works only in Firefox. As the curve's points keep changing frequently in my case, I didn't want to use marker-mid as it is costly for me to calculate the midpoint of the bezier curve everytime.
<svg viewBox="0 0 500 500">
<g>
<path id="path1" d="M291.698 268.340 C321.698 268.340, 411.904 93.133 441.904 93.133"></path>
<path class="path_arrow" d="M0,0 L6,6 L0,12" transform="translate(-3,-6)">
<animateMotion dur="0s" rotate="auto" fill="freeze" keyTimes="0;1" keyPoints="0.5;0.5">
<mpath xlink:href="#path1"></mpath>
</animateMotion>
</path>
</g>
<g transform="translate(166.698,243.340)">
<circle r="5" class="p1"></circle>
</g>
<g transform="translate(441.904,68.133)" >
<circle r="5" class="p2"></circle>
</g>
</svg>
Is there any way to do this using CSS Animations so as to avoid using <animateMotion> ?
EDIT 1:
The endpoints of the curve here is draggable and so the points of the curve tend to change frequently. The animation is to move the arrow to the center of the curve without calculating the midpoints.
EDIT 2:
Thanks to Kaiido's comment, I added calcMode="linear" and the arrow is now placed on the path as expected. But When I reposition the end point by dragging, the arrow stays in its initial position(as shown) in Chrome but it is expected to move along the parent path. In Firefox this is working fine as before.
You could achieve the same with CSS offset-path, offset-distance and offset-rotate properties:
#path1 {
fill: none;
stroke: black;
}
.path_arrow {
transform: translate( -3px, -6px );
offset-path: path("M220 104C220 144,400 180,400 224");
offset-rotate: auto;
offset-distance: 50%;
}
body { background: white; }
<svg width="500" height="500" >
<path id="path1" d="M 220 104 C 220 144 400 180 400 224"
fill="none" stroke-width="2" stroke="black" />
<path class="path_arrow" d="M0,0 L0,12 L12,6 z" />
</svg>
But their browser support is far lower than the one of SMIL, so I wouldn't recommend it.
Note that I did fix the answer there where they were missing a calcMode="linear" attribute to make Blink browsers happy.
If you need IE support, you may want to try this js implementation which seems to support <animateMotion> and rotate, keeping in mind I didn't test it myself.
Regarding the question's "EDIT 2":
Chrome indeed seems to need an explicit call to update the <mpath>. This can be done by calling the beginElement() method of the <animationMotion> element after each update:
document.querySelector('svg').onmousemove = function(e) {
const rect = this.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
path1.setAttribute( 'd', `M ${x} ${y} C 220 144 400 180 400 224` );
// Chrome requires an explicit update
document.querySelector('animateMotion').beginElement();
}
<pre style="position: absolute;pointer-events:none">move your mouse to change the path</pre>
<svg width="500" height="500" >
<path id="path1" d="M 220 104 C 220 144 400 180 400 224"
fill="none" stroke-width="2" stroke="black" />
<path d="M0,0 L0,12 L12,6 z" transform="translate(-3,-6)">
<animateMotion dur="0s" rotate="auto" fill="freeze"
keyTimes="0;1" keyPoints="0.5;0.5" calcMode="linear" >
<mpath xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#path1"/>
</animateMotion>
</path>
</svg>
You have to use webkit animation inside the css. Also i would recommend https://codepen.io/collection/yivpx/. Is an open source project for SVG optimization. I also encourage you to name all your classes within your SVG in order to do cool CSS stuff with animate, like:
animation: kaboom 5s ease alternate infinite;
I have an icon in an external svg file which I can not edit. It is black and white.
I am including this external SVG in my own SVG via
<image x="1mm" y="1mm" width="7mm" height="7mm" xlink:href="myExternal.svg" />
Now I need to invert the "colors" of the external SVG (i.e., make white black and black white). My assumption was, that this certainly must be possible using pure SVG. I tried:
filter: invert(100%);
Setting the external SVG up as a mask for a rect with fill color in different combinations
Any ideas?
CSS filters can be expressed in terms of SVG filters; here is a list.
The one thing you need to consider in addition is that if you have a simple icon file defining a path (that by default is filled black), the default background is transparent black. So a filter that works on the RGB channels sees no contrast between the path and its background.
(For the following examples I've inserted the image as a data uri instead of an external image.)
The simple solution for this sort of icon would be to invert the opacity:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
<defs id="defs6">
<filter filterUnits="objectBoundingBox" id="invert" x="0" y="0" height="1" width="1">
<feComponentTransfer>
<feFuncA type="table" tableValues="1 0"/>
</feComponentTransfer>
</filter>
</defs>
<image filter="url(#invert)" xlink:href='data:image/svg+xml,%3c?xml version="1.0" encoding="UTF-8" standalone="no"?>%3csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">%3cpath d="M 425.403,330.939 C 408.414,314.154 390.857,296.796 390.857,214.856 390.857,131.83 329.899,62.782 250.39,50.094 A 31.843,31.843 0 0 0 256,32 C 256,14.327 241.673,0 224,0 206.327,0 192,14.327 192,32 A 31.848,31.848 0 0 0 197.609,50.095 C 118.101,62.783 57.143,131.831 57.143,214.857 57.143,296.79 39.592,314.149 22.6,330.935 -25.496,378.441 9.726,448 66.919,448 H 160 C 160,483.346 188.654,512 224,512 259.346,512 288,483.346 288,448 H 381.08 C 438.27,448 473.495,378.417 425.403,330.939 Z M 224,472 C 210.766,472 200,461.234 200,448 H 248 C 248,461.234 237.234,472 224,472 Z M 381.092,400 H 66.9 C 50.138,400 41.765,379.61 53.566,367.809 82.151,339.224 105.143,312.085 105.143,214.857 105.143,149.319 158.462,96 224,96 289.538,96 342.857,149.319 342.857,214.857 342.857,312.507 366.078,339.431 394.425,367.809 406.278,379.661 397.783,400 381.092,400 Z" />%3c/svg>' y="50" x="50" height="100" width="100" />
</svg>
For a more complete solution, you would place a white flood-filling behind the image and then invert all colors:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
<defs id="defs6">
<filter filterUnits="objectBoundingBox" id="invert" x="0" y="0" height="1" width="1">
<feFlood flood-color="rgb(255,255,255)" result="background" />
<feBlend mode="normal" in="SourceGraphic" in2="background" />
<feComponentTransfer>
<feFuncR type="table" tableValues="1 0"/>
<feFuncG type="table" tableValues="1 0"/>
<feFuncB type="table" tableValues="1 0"/>
</feComponentTransfer>
</filter>
</defs>
<image filter="url(#invert)" xlink:href='data:image/svg+xml,%3c?xml version="1.0" encoding="UTF-8" standalone="no"?>%3csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512">%3cpath d="M 425.403,330.939 C 408.414,314.154 390.857,296.796 390.857,214.856 390.857,131.83 329.899,62.782 250.39,50.094 A 31.843,31.843 0 0 0 256,32 C 256,14.327 241.673,0 224,0 206.327,0 192,14.327 192,32 A 31.848,31.848 0 0 0 197.609,50.095 C 118.101,62.783 57.143,131.831 57.143,214.857 57.143,296.79 39.592,314.149 22.6,330.935 -25.496,378.441 9.726,448 66.919,448 H 160 C 160,483.346 188.654,512 224,512 259.346,512 288,483.346 288,448 H 381.08 C 438.27,448 473.495,378.417 425.403,330.939 Z M 224,472 C 210.766,472 200,461.234 200,448 H 248 C 248,461.234 237.234,472 224,472 Z M 381.092,400 H 66.9 C 50.138,400 41.765,379.61 53.566,367.809 82.151,339.224 105.143,312.085 105.143,214.857 105.143,149.319 158.462,96 224,96 289.538,96 342.857,149.319 342.857,214.857 342.857,312.507 366.078,339.431 394.425,367.809 406.278,379.661 397.783,400 381.092,400 Z" />%3c/svg>' y="50" x="50" height="100" width="100" />
</svg>
I'm trying to download some icons from http://game-icons.net/ and I need all black pixels to be transparent. All the techniques I've found on google have not worked, they have only turned them white.
Thanks for your time.
Am I missing something? Assuming you are using the SVG versions, why can't you just select the black rectangle and delete it?
Assuming for the moment you are correct, and perhaps it is some issue with importing the SVG into AI, it is easy enough to do it manually in a text editor.
Here are the contents of the "electric.svg" icon file:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="m0,0h512v512h-512z"/>
<g transform="matrix(15 0 0 15 -5924 -6649.4327)">
<use width="744.094" height="1052.362" transform="translate(432 440.36218)"/>
</g>
<g fill="#fff" transform="matrix(-3.75 0 0 3.75 2295.9997 -3330.35765)">
<path d="m512,944.3622 32,0 0-52 32,76-32,0 0,52z"/>
</g>
</svg>
http://jsfiddle.net/Hp8dT/
There is a <g> and a <use> in there that are not doing anything, so you could get rid of them if you like.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="m0,0h512v512h-512z"/>
<g fill="#fff" transform="matrix(-3.75 0 0 3.75 2295.9997 -3330.35765)">
<path d="m512,944.3622 32,0 0-52 32,76-32,0 0,52z"/>
</g>
</svg>
http://jsfiddle.net/Hp8dT/1/
The first <path> element is the one that is creating the black background, so just delete it. But in order for the lightning symbol (which is currently white) to be visible, we will need to change its colour. We'll use red.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<g fill="red" transform="matrix(-3.75 0 0 3.75 2295.9997 -3330.35765)">
<path d="m512,944.3622 32,0 0-52 32,76-32,0 0,52z"/>
</g>
</svg>
http://jsfiddle.net/Hp8dT/2/
I have an svg defining a path drawn on a transparent background -- a pretty basic svg.
I need to convert this svg so that the background is white and the text is transparent and cutout of the white background. I have been playing around with clip-path but to no avail. How is the right way to make this modification?
<svg width="138" xmlns="http://www.w3.org/2000/svg" height="40" viewBox="0 0 138 40">
<g transform="translate(2 30)">
<path d="m6.12,0 5.88,0 0-2.46-.6,0-2.535-9.21-5.46,0-2.535,9.21-.6,0 0,2.46 5.13,0 0-2.46-.9,0 .24-1.2 2.025,0 .255,1.2-.9,0 0,2.46m-.435-8.235 .15,0 .615,2.985-1.38,0 .615-2.985"/>
<path d="m12.3696-9.21 .66,0 0,6.75-.66,0 0,2.46 4.77,0 0-2.46-.66,0 0-9.21-4.11,0 0,2.46"/>
<path d="m17.5552-5.88 .66,0 0,3.42-.66,0 0,2.46 5.28,0 0-2.46-1.17,0 0-3.42 1.17,0 0-2.46-1.17,0c0-.63 .255-.87 1.035-.87 .735,0 1.47,.075 1.47,.075v-2.355c0,0-.78-.39-2.43-.39-2.205,0-3.495,1.035-3.495,3.54h-.69v2.46"/>
<path d="m28.518,0 4.11,0 0-2.46-.66,0 0-2.46c0-2.415-.945-3.63-4.155-3.63-2.385,0-4.155,.525-4.155,.525v2.58c.99-.225 2.295-.435 3.48-.435 1.125,0 1.38,.3 1.38,.87-3.735,0-5.4,1.02-5.4,2.88 0,1.515 1.065,2.34 2.775,2.34 1.44,0 2.25-.75 2.625-1.23v1.02m0-3.42c0,.645-.33,.96-.915,.96-.57,0-.825-.135-.825-.48 0-.48 .675-.57 1.74-.57v.09"/>
<path d="m41.9899-2.685c-.75,0-.93-.285-.93-.885h-3.3v2.97c0,0 1.815,.81 4.695,.81 3.21,0 4.95-1.29 4.95-3.855 0-2.58-1.935-3.375-4.26-4.125-.615-.195-.93-.3-.93-.645 0-.42 .27-.57 .93-.57 .465,0 .825,.18 .825,.75h3.15v-2.685c0,0-1.485-.96-4.38-.96-3.84,0-5.115,1.38-5.115,3.615 0,2.34 1.44,3.135 4.41,4.245 .705,.255 .87,.465 .87,.735 0,.39-.255,.6-.915,.6"/>
<path d="m47.8481-9.21 .66,0 0,6.75-.66,0 0,2.46 4.77,0 0-2.46-.66,0 0-9.21-4.11,0 0,2.46"/>
<path d="m58.2837,0 4.11,0 0-2.46-.66,0 0-2.46c0-2.415-.945-3.63-4.155-3.63-2.385,0-4.155,.525-4.155,.525v2.58c.99-.225 2.295-.435 3.48-.435 1.125,0 1.38,.3 1.38,.87-3.735,0-5.4,1.02-5.4,2.88 0,1.515 1.065,2.34 2.775,2.34 1.44,0 2.25-.75 2.625-1.23v1.02m0-3.42c0,.645-.33,.96-.915,.96-.57,0-.825-.135-.825-.48 0-.48 .675-.57 1.74-.57v.09"/>
<path d="m66.9288-11.67-4.11,0 0,2.46 .66,0 0,6.75-.66,0 0,2.46 4.11,0 0-1.02c.375,.48 1.185,1.23 2.325,1.23 2.07,0 3.075-1.62 3.075-4.38 0-2.76-1.005-4.38-3.075-4.38-1.14,0-1.95,.75-2.325,1.23v-4.35m1.74,8.25c0,.675-.3,.96-.87,.96-.57,0-.87-.285-.87-.96v-1.5c0-.675 .3-.96 .87-.96 .57,0 .87,.285 .87,.96v1.5"/>
<path d="m83.0515-2.46c-.675,0-1.02-.33-1.02-1.11v-4.53c0-.78 .345-1.11 1.02-1.11 .675,0 1.02,.33 1.02,1.11v4.53c0,.78-.345,1.11-1.02,1.11m5.73-3.375c0-4.38-2.235-6.045-5.73-6.045-3.495,0-5.73,1.665-5.73,6.045 0,4.38 2.235,6.045 5.73,6.045 3.495,0 5.73-1.665 5.73-6.045"/>
<path d="m94.4339,0 4.77,0 0-2.46-.66,0 0-2.46c0-2.505-1.02-3.63-2.655-3.63-1.35,0-2.055,.75-2.535,1.23v-1.02h-4.11v2.46h.66v3.42h-.66v2.46h4.77v-2.46h-.66v-2.46c0-.675 .3-.96 .87-.96 .57,0 .87,.285 .87,.96v2.46h-.66v2.46"/>
<path d="m103.732-8.55c-2.775,0-4.53,1.455-4.53,4.38 0,2.925 1.755,4.38 4.53,4.38 2.385,0 3.735-.75 3.735-.75v-2.4c-.72,.24-1.86,.48-3.18,.48-1.05,0-1.425-.36-1.425-1.08v-.09h4.86v-1.08c0-1.89-.915-3.84-3.99-3.84m0,2.67c.57,0 .87,.285 .87,.96v.09h-1.74v-.09c0-.675 .3-.96 .87-.96"/>
</g>
</svg>
Try using a mask instead of a clip path.
<mask id="m"> ... </mask>
Inside the mask, create a white rectangle, followed by (under) your black paths. The brightness of different areas of the mask determines the opacity of the corresponding areas of the element the mask is applied to, with white areas being fully opaque and black areas being fully transparent.
<rect width="100%" height="100%" fill="white" />
<g transform="translate(2 30)"> ... </g>
After the mask, add another rectangle and set its mask attribute to your mask. This rectangle is the white background you wanted, so give it a white fill.
<rect width="100%" height="100%" fill="white" mask="url(#m)" />
This should give you the effect you want. Check out this fiddle: http://jsfiddle.net/9tT6T/