SVG/Vector map indoor navigational routing - javascript

I've been searching the web for tutorials or methods on how to to implement my own point to point navigation system for an SVG-based indoor floor plan map. I have searched the web but the only options work with google maps. However I created my map using Illustrator as an SVG image using paths/vectors. I don't need to implement any navigational instructions for the user, just a simple route from one point to another. There must be a way to use the vectors to plot points on the map that the navigational path can take for turns etc.
Any advice appreciated
Thanks

Yes! You can do this with JavaScript, as well as add event listeners and do other DOM manipulation similar to with a normal HTML page. (See the bottom of this answer for how to draw a line on the SVG given two points.)
I am working on a project that does exactly this. The user is able to enter their starting room number and destination room number, and the route is plotted on the SVG.
It was a bit tedious, but what we did was put circle elements on the SVG. There were elements outside of each doorway, and also at hallway intersections.
A typical element is as follows.
<circle
id="route3287-1"
style="fill:#000000;stroke:none"
cx="2014.0000"
cy="239.6"
r=".05"
data-neighbors="route3296-1,06-07" />
Note that the radius attribute is small enough to where it won't be seen on the SVG (unless the user decides to zoom in alot). We also manually entered into the data-neighbors attribute the ids of adjacent points. This is because our back end parses the SVG file, builds a graph using these points, and uses Dijkstra's algorithm to generate the route. We used the cx and cy attributes to calculate the distance between nodes on the graph.
Here is a close up of what the points look like (when the radius is big enough to see them)
Now, when a route is generated we are simply drawing lines on the SVG between each of the points. We put each of the lines in a group so that we can reference it by id later and remove the entire route when we decide to draw a new one.
Here is an example. Where "svg" is a reference to the SVG element, here is how we draw a line between two points (x1,y1,x2,y2), you could easily iterate through a list of points and draw all the lines in a similar fashion.
var newElement = svg.createElementNS('http://www.w3.org/2000/svg', 'path');
newElement.setAttribute('d', 'M' + x1 + ',' + y1 + 'L' + x2 + ',' + y2);
newElement.style.stroke = '#000000';
newElement.style.strokeWidth = '15px';
svg.appendChild(newElement);

You can manipulate the SVG with JS and CSS and this way add more interactions with the SVG. SVG is XML an can be traversed with JS as normal DOM tree, so you can create functions to handle your requirements. You can even place the SVG you've created as Layer in Google Maps.
The article uses simple example for FloorMaps. Interface with SVG

You can draw a SVG and with javascript add be interative
https://echarts.apache.org/examples/en/editor.html?c=geo-svg-lines

Related

How to add points to already created polygon using svg.js

I've written some code which determines when user clicks on a polygon near to edges. I collect the mouse coordinates and want to add this point to polygon. For this, I'm adding points to poly.array().value on proper location. But I'm not able to understand how should it be reflected on the screen.
Sample code
poly.on('mousedown', function(event){
var points = myCanvas.point(event.x, event.y);
var polyArray = poly.array().value;
polyArray.splice(i+1, 0, [points] );
});
Possible approach that I can think (seems a hack not the proper solution) is to add points to polygon SVG element manually. I was wondering if there is a method in svg.js element to update the element and replot it.
I checked the source code of svg.draw.js, and found that there is a method plot which can re-plot the polygon with new points poly.plot(polyArray);

animating a path on click - css timeframes or js/jquery?

I want to create an animation of a path, like a journey/timeline. The user is shown a circle (eventually to be an image), when they click this circle the animation begins and shows a path animating/traveling to another circle with a fade in effect. I have attached an image which I think explains my idea best.
My question is - what would be the recommended way of doing this? css animation or is there a jquery library that would be helpful?
Thank you
I would take svg as base. With Inkscape (or similar) like that, you can design the path visually and include the blue circle.
Than you can inject the svg-code in your html like so (copy the svg code from the generated file):
<div class="svg-container">
<svg>…</svg>
</div>
Finally you can use javascript to reference the circle and the path:
var path = document.querySelector('.path'), //these selectors are just arbitrary
circle = document.querySelector('.circle');
To get a point on the path, you can use:
var point = path.getPointAtLength();
For animation, I assume that you basically know how to do that, since this would be too much to explain here. But lets say that p is the progress of you animation and will be in the range [0,1]. To calculate a point at a given p could be done like so:
let pointAtT = (path, t) => {
let l_total = path.getTotalLength();
return path.getPointAtLength(l_total * t);
}
Having that, you can use the x and y coordinate to manipulate the circle. Be aware of possibly applied transformations, that is why I recommend to transform everything to global coordinate space, calculate there and transform the result back to the item's coordinate space.
Documentation on mdn
There are a some svg libraries that might help you: svg.js, snap.svg and Raphaël.

Creating interactive floor plan using d3.js (or similar)

I'm trying to make an interactive floor plan. When the user hovers a room I want to display some sort of message.
All my floor-plans are in JPEG format.
I would like to make something like this: http://dciarletta.github.io/d3-floorplan but I need to also make a tool in the backend that would create those overlays.
My questions is, how can I do it? Ideally I would just click around the room to create the overlay, but I don't think d3.js allows it. I'm also having a problem getting the correct coordinates:
$('#floor').click(function(e) {
var $this = $(this);
var offset = $this.offset();
var pos = [];
pos.x=(e.pageX-offset.left);
pos.y=(e.pageY-offset.top);
console.log('x: '+pos.x+' | y: '+pos.y);
});
http://jsfiddle.net/5nTEk/
So, not only I don't think I'm getting the correct coordinates as I don't know how to add an overlay as the link above... Any suggestions?
You can probably do it by overlaying an SVG over your <img>. D3 would render into this svg panel. You can create a polygon in the SVG based on the user clicks.
If you use the d3.event mouse locations (mouseX and mouseY, I think), you can get click positions relative to the SVG element, and then use those as vertex locations on a polygon. Checking for click proximity to the original point will allow you to decide when to close the polygon.

Interactive area for Z shaped paths in SVG

We have code that loads SVG via Ajax and interacts via Javscript. The SVG represents wiring diagrams - that is paths ('wires') and text ('labels for wires'). The paths and text objects are grouped under a node - each node also contains a node: using ID's we place in the desc node we can respond to the click - e.g. by popping up details of the ;selected wire'.
In general the system works perfectly - but occasionally the SVG click event we get back seems to belong to 'another wire'. Here is an example of the geomtry when this happens:
---------------
-
-
....... -.....Wire1....
-
-
-
------Wire2--
(I hope this is clear - Wire1 runs horizontal, Wire 2 is a zig zag shape, running vertically as it crosses Wire1)
In this geometry the behaviour we see is:
Click on Wire1 Path --> event points at Wire1 Path
Click on Wire1 Text --> event points at Wire2 Path (!Wrong)
Click on Wire2 Path --> event points at Wire2 Path
Click on Wire2 Text --> event points at Wire2 Text
Changing the z order (Writing Wire1 After Wire2 in the SVG file) has no effect.
Representing wires by a series of short paths (rather than one long path) fixes this issue but increases the files size (and these wiring diagrams are massive).
One would like to thing this was just one bug in one SVG browser - but it is observable in Safari 5 and Mozilla. (Which I assume do not share a common code base). Which suggests that under some circumstance SVG defines the 'active clickable area' of a Z shaped path to be its bounding rectangle.
How can we control this? Is there a header tag attribute or other work round that would restrict the active area of any path to the path itself?
If you have a fill on your paths (even one the same color as your background) that would clearly explain this. Do you have a test case you can share showing the problem?

Get Line co-ordinates in Javascript

I am drawing lines using Canvas (HTML 5), since lines/shapes are not stored as objects in Canvas, I cannot attach unique events to it (eg onmouseclick)
I wish to attach a onmouseover event to a line, is it possible by getting to know if the mouse if over a particular line (using its 2 X and 2 Y co-ordinates) in Canvas using Javascript. Would this work for different line widths (eg: 2,5 pixels)
Want to avoid using SVG as the entire project is built on Canvas
Please advise.
You would need to use math formulas to calculate the area of the line and whether a certain point intersects with it.
Here's a basic example:
Find mouse coordinates relative to position of the canvas (How to find mouse pos on element)
Calculate whether mouse x/y is inside some rectangle (Point in rectangle formula)
Done.
There is a function isPointInPath(x,y). It will return true if a point is on the current path.
You will have to call that for every line you want to check and the best way to do that is at the same time as you draw.
The best way is using some canvas frameworks. Look at "LibCanvas :: Creating Lines" (dont forget to dblClick at canvas)

Categories