I am trying to make a graph which is sort of similar to a map. Here, I use a force-directed graph in which the nodes are locations and the edges are the paths between locations.
However, I can't seem to find any documentation on how to render an edge any different than a line with color attributes. (which I am doing now but looks kind of bland)
Is there some kind of way to have the edges custom rendered, for example, a repeated image of some sorts? Or even more specific, in my case for example, as a dirt path or similar?
Thanks in advance!
You can use <filter>:
<svg>
<filter id="my-filter">
<feFlood flood-color="orange" flood-opacity="0.75" in="SourceGraphic"></feFlood>
<feComposite operator="in" in2="SourceGraphic"></feComposite>
<feGaussianBlur stdDeviation="4"></feGaussianBlur>
<feComponentTransfer result="glow1">
<feFuncA type="linear" slope="4" intercept="0"></feFuncA>
</feComponentTransfer>
<feMerge>
<feMergeNode in="glow1"></feMergeNode><feMergeNode in="SourceGraphic"></feMergeNode>
</feMerge>
</filter>
<path d="M 10,10 L 100,100" filter="url(#my-filter)" stroke="orange" stroke-width="3"/>
</svg>
Related
is there a way to do image processing with javascript on an image or a canvas?
I need to apply a motion blur with length/strength and an angle.
I also need to export the image then. Should also work on mobile devices.
Can I do that in real-time with javascript?
You could use an SVG filter. Within an <svg> it looks like this:
svg{
overflow: visible;
}
<svg>
<filter id="verticalMotionBlur">
<feGaussianBlur in="SourceGraphic" stdDeviation="0 5" />
</filter>
<circle cx="60" cy="60" r="50" fill="green" filter="url(#verticalMotionBlur)" />
</svg>
but you can also apply it to any other DOM element on your page, including an image:
img {
filter: url(#verticalMotionBlur)
}
<svg>
<filter id="verticalMotionBlur">
<feGaussianBlur in="SourceGraphic" stdDeviation="0 5" />
</filter>
</svg>
<img src="https://picsum.photos/200"/>
My question is quite simple : Is it possible to reproduce this effect (the circle distortion animation) with SVG filters ?
I think it would be interesting to use FeTurbulences with FeDisplacementMap because it works on a static way. But actually, I don't which attribute I should tween to make the animation nice.
<feTurbulence type="fractalNoise" baseFrequency="0.01" numOctaves="2" result="warp" seed="0" stichTitles="stitch"></feTurbulence>
<feDisplacementMap xChannelSelector="R" yChannelSelector="G" scale="30" in="SourceGraphic" in2="warp" />
If you have other solutions (js libraries, filters, etc) : please don't hesitate. I'm open to every solutions ;)
Thank you for your consideration.
This is how you do that kind of filter. The baseFrequency controls the granularity of the distortion, the scale controls the size of the displacement and the dur in the Animate controls the speed. I've animated the scale and added a shadow to match the original a bit better.
<svg width="800px" height="600px">
<defs>
<filter id="distort">
<feTurbulence baseFrequency=".015" type="fractalNoise"/>
<feColorMatrix type="hueRotate" values="0">
<animate attributeName="values" from="0" to="360" dur="1s" repeatCount="indefinite"/>
</feColorMatrix>
<feDisplacementMap in="SourceGraphic" xChannelSelector="R" yChannelSelector="B" scale="20">
<animate attributeName="scale" values="0;20;50;0" dur="5s" repeatCount="indefinite"/>
</feDisplacementMap>
<feGaussianBlur stdDeviation="3"/>
<feComponentTransfer result="main">
<feFuncA type="gamma" amplitude="50" exponent="5"/>
</feComponentTransfer>
<feColorMatrix type="matrix" values="0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 1 0"/>
<feGaussianBlur stdDeviation="10"/>
<feComposite operator="over" in="main"/>
</filter>
</defs>
<circle filter="url(#distort)" cx="200" cy="200" r="150" fill="red"/>
</svg>
I have once created a similar effect but not with filters. What I basically did was:
creating coordinates for a »star« shape, or a regular Polygon as array,
animate those coordinates, so that they moved, but not distorted the overall star shape too much,
used a Catmul-Rom algorithm to smooth the edges and converted that result back to bezier path data and applied that to a <path />
Applied a gaussian blur on the resulting path
I came across a strange problem using svg filter and masks.
Let's say I have an svg file containg these filters and masks:
<filter id="om-outline">
<feMorphology result="offset" in="SourceGraphic" operator="dilate" radius="3"/>
<feComposite in="offset" in2="SourceGraphic" operator="out" result="stroke" />
<feFlood flood-color="#79868d" result="COLOR-red-2" />
<feComposite in="COLOR-red-2" in2="stroke" operator="in" result="BEVEL_41" />
</filter>
<mask id="outline-mask">
<rect cx="0" cy="0" width="341" height="375" fill="black"/>
<!-- some more elements here that create the silhouette of my actual svg graphic -->
</mask>
using this filter and mask, creates a nice outline arround my animating svg graphic
everything is working as expected so far now, but when I add another graphic, using the same technic to create an outline, this happens:
somehow the second graphic uses the mask and outline of the first graphic, even though I used different ids for the reference.
This only happens in Firefox and Internet Explorer, Safari and Chrome seem to work as expected.
So trying to get my head around how to change a SVG using javascript (I tried d3js library. And I have some issues because I am not sure wether to use it or not).
I have created a simple icon (a star and a circle, to have something).
As far as I understand, what I need to do is to change the attributes of the <g> tag.
The icon have three id's, start circle(should be the whole picture), star (which is the star) and circle
Here is the SVG image.
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="120"
height="120"
viewBox="0 0 120 120"
id="starcircle"
version="1.1"
inkscape:version="0.91 r13725"
sodipodi:docname="starcircle.svg">
<defs
id="defstarcircle-def" />
<sodipodi:namedview
id="starcircle"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.32"
inkscape:cx="53.146552"
inkscape:cy="47.894737"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1440"
inkscape:window-height="821"
inkscape:window-x="0"
inkscape:window-y="1"
inkscape:window-maximized="1" />
<metadata
id="metadata5539">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="scLayer"
transform="translate(0,-932.36216)">
<path
sodipodi:type="star"
style="opacity:0.5;fill:#00aeef;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
id="star"
sodipodi:sides="5"
sodipodi:cx="59.05172"
sodipodi:cy="992.44832"
sodipodi:r1="49.260658"
sodipodi:r2="24.630329"
sodipodi:arg1="-0.27469391"
sodipodi:arg2="0.35362463"
inkscape:flatsided="false"
inkscape:rounded="0"
inkscape:randomized="0"
d="m 106.46551,979.08623 -24.307496,21.89157 4.253455,32.4346 -28.331542,-16.3529 -29.532743,14.0681 6.79764,-31.99826 -22.505694,-23.74002 32.532715,-3.42306 15.623459,-28.74026 13.308684,29.88267 z"
inkscape:transform-center-x="-0.60060082"
inkscape:transform-center-y="-4.1291064" />
<ellipse
style="opacity:0.5;fill:#0d00ef;fill-opacity:1;stroke:#ffffff;stroke-opacity:1"
id="circle"
cx="58.620693"
cy="991.80182"
rx="16.379311"
ry="16.594828" />
</g>
</svg>
So lets say that I want to rotate the star, for now only rotate it 180 degrees.
I would need to get the SVG image, then the shape, then append something like
rotate(180 , 50 , 50)
I tried doing it using d3, because it seemed like you needed a library to do it, but nothing I do seem to change the actual document. So what is the easiest way.
I created a jsfiddle with this example, and my attempt to do the rotate, but so far no luck.
I also hid the circle, mostly just to prove that the code is at least finding the objects, even if the hide function is a css option, and I want to do it using SVG transform
https://jsfiddle.net/qyt5o0s7/
Your javascript code was appending a <g> element to the #star element and then rotating the #star element. Remove the append() function and your code will then rotate the #star element. If you want to rotate the #star element around its center then you will also have add tranlate operation before and after the rotate operation. For example, change...
vard3star = d3.select("#star").append("g")
.attr("transform","rotate("+10 + "," + 15 +","+ 15 +")");
to...
var d3star = d3.select("#star").attr("transform","translate(60,992) rotate(10,15,15) translate(-60,-992)");
Also note that you were missing a space between var and d3star which was resulting in a global variable called vard3star.
Well your approach in the fiddle is wrong, Since you are not sure what the library to use or how to use it I like to give you the steps.
Use d3.js, It's great.
You just have to add a <g>, then create the star inside the <g>.
Give the <g> and id of something like starGroup
<g id="starGroup"></g>
then you can use d3 to translate the group.
d3.select('#starGroup')
.style(...);
I have these icons and I'd like to procedurally add a drop shadow (basically, something, anything) to them on hover so they don't look so hokey.
They are SVG's so in theory I can prepend something like this:
<filter id="f1" x="0" y="0" width="200%" height="200%">
<feOffset result="offOut" in="SourceAlpha" dx="20" dy="20" />
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="10" />
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" />
</filter>
and some javascript magic to apply it on mouse over. This could possibly save ages of design work.
Problem is, the svg's are presented as <a style='background-image:url(icon.svg)' />.
Is there a way to get into the SVG element?
No, it's not directly possible. A workaround if you need this would be to use inline svg in html, or reference the svg files with either <object>, <iframe> or <embed>.
An example of using inline svg and a filter effect on hover here. The svg part looks like this essentially:
<svg width="400" height="400" viewBox="-2 -2 36 32">
<defs>
<style>
#stack polygon:hover { filter: url(#glow); }
</style>
<filter id="glow">
<feMorphology radius="0.7"/>
<feGaussianBlur stdDeviation="1"/>
<feColorMatrix type="matrix"
values="0 0 0 0 0
0 0 0 0.9 0
0 0 0 0.9 0
0 0 0 1 0"/>
</filter>
</defs>
<g id="stack" class="icon" fill="#850508">
<polygon points="0,20 16,24 32,20 32,24 16,28 0,24"/>
<polygon points="0,12 16,16 32,12 32,16 16,20 0,16"/>
<polygon points="0,4 16,0 32,4 32,8 16,12 0,8"/>
</g>
</svg>
If you're using SVG as an image then you can't get to the image's DOM and manipulate it via javascript.
While you could load them using XMLHTTPRequest and then insert them into the main document as inline data using the DOMParser object, this exposes you to the security issues that the browsers are trying to protect you from by locking down image access i.e. the image could change and you may be loading arbitrary javascript into your page.
What would seem simplest and safest to me is if you just alter the image files directly using an editor and add the filter into them then use the modified images.
What if you use jquery addclass and simply link to another svg that has your changes?
You can also create an svg element with html code (right click on file --> view with notepad) and you will have the code there -- there are online converters that can make all neccessary tweaks and then you can enter the svg code with javascript
I don't know how to do it in the way you show... as a background image... but if you can load the svg file inside a div as in this example you can you can use my importer (a modified version of others importers founded on github) that it's here: http://www.dariomac.com/Document/Raphael-Utils. You can also see this storify where I describe all the steps followed by me to import SVG directly from file.