I'm using RaphaelJS to implement some event-heavy SVG. I have a set of paths on a canvas, and a point. How can I get all the paths that cross that point? Relatively new at this, but I assumed this would be trivial and I can't find anything about it.
If it helps, the specific implementation is trying to detect on the mousedown event if I've clicked on a path so I can rotate it around another point onmousemove.
Unfortunately, I'm not aware of a portable (supporting both the SVG and VML backends of raphael) way to do this without implementing the math yourself. However, for browsers that support SVG, the SVG spec includes built-in support for exactly what you are requesting:
http://www.w3.org/TR/SVG/struct.html#_svg_SVGSVGElement__getIntersectionList
Vector is math. Find the equations of the lines and see if the point fulfill the equation.
Related
Problem
Hi,
So I have noticed that software like Microsoft Edge and OneNote and Notability, store hand drawn strokes as vector curves or lines. They also provide the ability to erase strokes, by dragging the eraser over them.
I wanted to implement something similar in my software, an SVG Animation and Creation bundle, and I have come up with the logic for the freehand stroke to SVG curve, a demo is available here:
https://phantomzback.github.io/SvgFreehandDrawDemo/polylineTest.html
It uses the polyline tag with the cursor positions, and path simplification is something I also plan to implement. But before that, I need a way to detect if the eraser has gone over the stroke. I have an approach but I am not sure how great of an approach it is. I'd appreciate advice on how this can be improved or alternative methods to tackle the problem.
Current Idea
Find the pixels where the stroke is rendered, and save it in an array. Then, check for if the eraser tool is active and goes over that stroke. If it does, delete this stroke.
Finding the pixels shouldn't be very hard since a polyline is a bunch of points and lines drawn between them. But I plan on adding support for paths later, for which a better approach might be needed.
Thanks in advance!
I have a Network Diagram(Nodes and Edges) in SVG generated by GraphViz tool. I want to make the diagram interactive in the sense, it should be draggable, on click of a node some other nodes to be hidden.ETC. Can any one suggest snapSVG is sufficient for that? I cannot add any thing to the SVG diagram that is my restriction. How can we make existing svg diagrams forced directed? Any help, starting point, fiddle will be helpful. I have hands on in d3.js is it achievable by d3.js?
This should be possible, maybe be aware Snap.svg isn't so compatible with older browsers (in which case you could look at Raphael which is Snaps older brother, d3 is very well established as well). They all have all the basics, handlers, animation etc. However, although its possible, it may well be quite a lot of work (so may want to stick with what you know).
You may want to look into whether you want to autocreate connecting elements and move automatically, or are happy moving endpoints manually.
It may also depend on things like what you want to happen after dragging the elements. Do you want to save them ? Some of that may be quite important as to how you approach it, maybe more important than dragging as most will support that.
Having read the SVG2 draft, I am slightly disappointed to learn that there will be no new line caps than the standard 3. The new arc line join is brilliant however, but not what this question is about (I just wanted to mention that).
I had been hoping for a cap that ends in a triangle. But given my use case, that might not be ideal either.
As far as I can gather, Adobe Illustrator - which I do not use myself - allows the width of a stroke to be variable. This is useful when drawing from a drawing tablet, to highlight the pressure of the lines. It's true, this functionality exists in many bitmap drawing programs, but is there a way to achieve this effect in SVG, without having to draw multiple lines?
The idea is that each node should have a width, and the lines should then 'smoothly' scale the width between each node that had a different width.
Is this possible? And if not, could it be considered?
P.S. I should point out, that this is more a thought experiment and an idea than something that hinders my process. More of a nice to have than need to have.
While this may not be a true answer (SVG standard wise at least), it turns out that in the current trunk version of Inkscape, this feature called PowerStroke already exists. There are some screenshots of PowerStroke.
This should satisfy my quest for the time being.
It turns out - as well - that the arc line joins was actually suggested by Inkscape as well, they are just called extrapolate in Inkscape.
I am trying to draw this svg of europe using raphael. For each path in the svg, I've parsed it and do: r.path([countrypath]). This works, but the problem is that it is gigantic. For example, some of the paths look like M 11689.234, 6005.2561... It isn't even coming close to fitting on a 500x500 canvas. How do I resize this? Raphael's scale/translate don't seem to work, or I don't know how to use it. I noticed in the SVG each path has transform="translate(5.875e-4,7.538462e-5)" Do I need to somehow change the viewBox? Or change the svg path's somehow before it touches Raphael?
you can use scale(Xtimes,Ytimes,centreX,centreY)
where Xtimes,Ytimes are the proportion reduction if you select 0.2 the images would be reduced to 1/5th
and
centreX, centreY are relative coordinates where you should select 0,0 so that all paths/parts of svg are scaled down uniformly and relatively
if you select scale(0.2,0.2,0,0) your image would be properly reduced to 1/5th
I actual picked out quite a large SVG of the world yesterday and fed it through the SVGTOHTML converter.
You will find the tool and associated info #
http://www.irunmywebsite.com/raphael/svgsource.php
I set up a whole load of resources for Raphael #
http://www.irunmywebsite.com/raphael/raphaelsource.php
Amongst these you will find the world map wrapped in the scale pluton provided by Zeven!
The 20minute exercise delivered this...
http://www.irunmywebsite.com/raphael/colourmap2.php
Hopefully this will help you or someone with a similar problem in the future.
Also note that you can simplify paths in SVG editors as well as scale them before you put them in the SVGTOHTML converter.
Quite often maps can be drawn to extreme detail but simplifying them will greatly reduce path length.
You have two options either use what I did, use the .transform("transform string") to scale the paths, the transform string can be sww,hh,xx,yy where ww and hh is by how much you want to scale the path.
.transform("s0.25,0.25,0,0");
You can find an EXAMPLE HERE or jsfiddle HERE.
Or use
paper.scaleAll(n);
where n is the amount by you want to scale the whole paper by. First create the path in the page and then scale the paper object by maybe half
paper.scaleAll(0.5);
You can find the library and examples for the Scale.Raphaeljs library in the link below:
Scale Raphael library
Translating by such a small amount seems a bit wasteful, it's ~0 anyway, I doubt you'd see much of a difference if you stripped off the transform attributes that look like that.
Yes, changing the viewBox could make it fit to whatever you wanted in all viewers that support SVG, but raphael itself doesn't support viewBox (you'd have to provide some VML fallback yourself).
Either preprocess the path data to fit your particular use (probably a good idea anyway, it always helps to keep the filesize down, wikipedia maps are usually quite large) or use raphael's scale function to scale the paths to a proper size.
Update: Raphaƫl v2.0 and later does support viewBox (via the setViewBox method).
You can use the Raphael attribute 'translation', which takes an x,y delta. ie:
r.path([countryPath]).attr({translation:'-11689, -6005'});
To make it more reusable for multiple paths, you could parse the x and y values from the M in your svg path. When I did this, it turned out that I didn't want my path to be exactly on the 0,0 since that sent it over the canvas as well -- might take some adjustment depending on the height and width of your element.
Is there any way to build paths in Cairo by combining two paths together through Boolean operations such as Union, Difference, and Intersection? I'm working on a vector graphics application that uses Cairo to do its rendering and would like to give my users the ability to combine paths together in this manner, but I can't find a way to do it in Cairo.
I haven't found a way to do this with the cairo libraries. But it's a feature I've been looking for too. Would definitely be helpful when (for example) stroking the combination of two paths - compositing operators mentioned by ntd don't seem to be able to do this.
In the meantime, I'm trying to write scripts for inkscape, and letting inkscape do the unioning/differencing. Acceptable for the problem I'm working on but definitely not for yours. Have you had any luck, either with cairo or any other svg library? After a couple days of googling, it doesn't seem to be trivial :/
Combining paths with operators does not make any sense to me. What do you get from "line AND curve OR arc"?
Instead, you can apply compositing operators by using cairo_set_operator(): it will set how the current drawing operation (being it cairo_fill(), cairo_stroke() or whatever) should be mixed with the old content of the surface.