How to pan and zoom to fit an element with SvgPanZoom - javascript

I'm using svg-pan-zoom library and I need to pan/zoom the view to fit a particular element.
I could use fit method but it fits the whole content in this case I need to fit only one particular element.
Another option can be to calculate the pan and zoom required and use the custom control, but how to get the pan/zoom of an element to fit the window?
UPDATE
I tried to follow the #bumbu "easier" solution. That was my first thought but I have encountered some troubled with the zooming point position.
This is a fiddle to show the expected behaviour and the calculation attempt.
http://jsfiddle.net/mgv5fuyw/2/
this is the calculation:
var bb=$("#target")[0].getBBox();
var x=bb.x+bb.width/2;
var y=bb.y+bb.height/2;
But somehow the zooming center expected (225,225) is not the right one.

I found a solution panning before zooming, I could not find the right way to use zoomAtPoint() method.
http://jsfiddle.net/mgv5fuyw/3/
var bb=$("#target")[0].getBBox();
var vbb=panZoomInstance.getSizes().viewBox;
var x=vbb.width/2-bb.x-bb.width/2;
var y=vbb.height/2-bb.y-bb.height/2;
var rz=panZoomInstance.getSizes().realZoom;
var zoom=vbb.width/bb.width;
panZoomInstance.panBy({x:x*rz,y:y*rz});
panZoomInstance.zoom(zoom);

Without going into detail I'd try 2 approaches:
Easier:
Init the svg-pan-zoom library
Fit and center you SVG
Calculate positions (top-left and bottom-right, or center and size) of the elements you're interested in
Now based on viewport size you should be able to calculate zoom level and center point of each element
Harder:
Figure out relative position of the original objects relative to original viewport
Based on current viewport size you should be able to calculate zoom level and center point of each element

Related

Wrong position of absolute elements when browser zoom != 1?

I have a full screen div containing a map with absolutely positioned elements within it (cities, armies etc).
It all works fine with the default browser zoom, but if I change the browser zoom level, the positions change in seemingly random ways. Sometimes they're a pixel left/down/right/up with no rule I can figure out.
The absolute element positions are calculated based on their coordinates within the map, so for example if an element has coordinates x: 5, y: 8 and one map quadrant has dimensions of width=20px, height=20px, then its position is calculated as:
var pos={
"x": 5*20,
"y": 8*20
};
My best guess is that the browser is rounding off these pixel values when the browser zoom is changed. For example, if browser zoom==0.911 then the real quadrant size comes out to 18.22 x 18.22. If the browser rounds this value to 18.2 for example, then pos would be a few pixels off.
Is my assumption correct and is there a solution that will work consistently regardless of browser zoom level?
EDIT: one simple solution (that worked) was to structure the map as a table with fixed td width/height, but this creates an immense number of useless HTML nodes and slows down the load time of the page, which is unacceptable to the client. I need to keep the map as a simple div with just the absolutely positioned elements inside it.

leaflet icon size based on meters

I want to display objects on a map in their exact dimensions.
I have reference data about these objects, containing the length and width of the object in meters, now I need to convert the meters into pixels for the leaflet icon size based on the zoom level.
var meterlength = 50;
var meterwidth = 40;
//convert meters to pixels
var icon = L.divIcon({html:"<svg>..</svg>",iconSize:[xx,yy]});
I found this https://github.com/makinacorpus/Leaflet.GeometryUtil/
GeometryUtils with the length and distance function, but could not get it working.
Any ideas ? Thank you very much !
EDIT:
This answer solved my original problem:
https://gis.stackexchange.com/a/198444
But I'm sacling the icons on map zoom using the "zoomanim" event - unfortunately the map.containerPointToLatLng() Methode applies to the old zoom level not to the new one.
Is there a Workaround ?
If you want your image to represent the object real size, then you should probably better use an L.imageOverlay instead of a marker and trying to adjust its size based on zoom level.
See https://gis.stackexchange.com/questions/171609/resize-divicons-svgs-at-zoom-levels-leaflet
Then you would need to find the appropriate coordinates for your Image Overlay bounds, not pixels.
Now if you really want to change your marker icon size depending on the zoom level, you have several posts on SO and GIS SE that cover this topic.
E.g. Best way to make marker resizable in leaflet

move rotated ol.style.text relative to a given point in openlayers 3

I will try to explain what I'm trying to accomplish.
I have a point feature to which I set an array of 2 styles: 1 style represents a rotated image at the given point, the second one should be a rotated text at a fixed distance of the given point.
To clarify things I've created an image. I want to achieve the situation on the right. (the x,y,z lines and labels are for explanation purposes). I want to move the text over a fixed distance z. The rotation angle is also variable.
So what I did was give a rotation to the ol.style.text object and then give the text an offset for Y but then the text gets pulled straight below the point.
What I am looking for is a method to offset the text for a given distance, taking the rotation in account, without having to manually set the ofssetX and offsetY.
One solution here is indeed to use geometry.. calculate x and y offset based on the angles and the given z , using the sin formulas and the Pythagorean theorem, but I would like to avoid those calculations and find a more simple resolution.
I am using the latest version of openlayers3, currently v3.16.0
Thanks in advance.

Scale to a specific point in PIXI.js

I am trying to zoom to a specific point on a PIXI.js Sprite object. I can achieve a similar effect by changing the anchor to correspond to that point, however, that screws up the coordinate system which I can't have happen. Does anyone have any ideas as to how I can do this by repositioning the sprite object?
This example is what I am looking to achieve, but in the code they use some functions that don't exist in the new versions of pixi.
http://anvaka.github.io/ngraph/examples/pixi.js/03%20-%20Zoom%20And%20Pan/
Thanks!
I would suggest you put your sprite in a PIXI.container, and scale the container:
var container = new PIXI.Container();
myStage.addChild(container);
container.addChild(mySprite);
container.position.set(x,y); // Position of the container in the main container (stage) (where you previously had the sprite)
mySprite.position.set(x,y); // Your "pivot point"
container.scale.set(1.2);
You can't set an anchor on a container, when you scale the container it will scale the center. So, place the sprite in the container as such that the zoom-center is aligned with the containers center. You can then move the container (instead of the sprite) in order to have a coordinate system that works for you.
(Depending on PIXI version you should use PIXI.Container or PIXI.DisplayObjectContainer.)

Spot the ball game, zooming problems, jQuery

I am trying to create a spot the ball game, so it will (eventually) be an image of a player kicking a ball but the ball has been removed and the player needs to click where the ball should be.
The first version went well and works.
http://enjoythespace.com/sites/game/test.html
But what I need to add is some sort of zooming so you can see more accurately where you are clicking. I been playing around and have come up with this
http://enjoythespace.com/sites/v2/demo.html
But once you click it looks great when zoomed in but when you go back to the image its way off.
I think its todo with how the image is setup, the #webpage is half the original size of the image and the #retina uses the full size of the image.
Any help?
The first problem is that you aren't setting the retina backgroundPosition correctly.
This code works (I added a zoom variable to make it clear how changing the zoom would change the calculation, but it would need other changes too):
/* Moving the retina div with the mouse
(and scrolling the background) */
zoom = 2.0;
retina.css({
left : left - sizes.retina.width/2,
top : top - sizes.retina.height/2,
backgroundPosition : ""+(-zoom*left+sizes.retina.width/2)+'px '+(-zoom*top+sizes.retina.height/2)+'px'
});
Test this by checking that all four corners are seen correctly in the retina, i.e. when you're over the corner of the main image, the corner should be in the center of the retina circle.
The second problem is if you resize the browser the position calculations are out because the offset variable isn't updated for the new size. A simple way to do this is to put this as the first line of webpage.mousemove() so the offsets are updated every time:
var offset = { left: webpage.offset().left, top: webpage.offset().top };
It looks like you are passing the top/left position click point of the zoomed image to highlight where you have clicked. What you will need to do is alter your top/left position based on whether the fisheye is over the image or not.
Does the un-zoomed image have to be part of the news page or can it be a standalone image?
If it can be standalone then the solution should be quite simple. If the zoomed in image is twice the size of the unzoomed one then you can just set the top/left values of the highlight to half the value of the zoomed, when looking at the unzoomed.
Jquery position will allow you to accurately get the position.
jQuery Position()

Categories

Resources