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.)
Related
have a question for positioning icons on the here Map V3 with the Javascript framework in the Browser (Chrome, Firefox).
position marker example picture
I create an svg arrow which is possible to rotate.
(green point and the rectangle are just for better recognizing the problem)
But I cannot center the new created Icon on an GeoCoordinate.
The green icon point and the arrow are positioned at the same GeoCoordinate.
I want that my Icon is exact centered on this GeoCoordinate, because if you have different zoom level the arrow seems to move away from the GeoCoordinate.
One of the code snippets I used
var svgArrow = '<svg width="30" height="30" xmlns="http://www.w3.org/2000/svg">' +
'<polyline points="15,2 25,27 15,15 5,27" stroke="#FE6940" fill="#FE6940" transform="rotate('+ PosDirection + ',15,15)"/> </svg>';
var iconSVG = new H.map.Icon(svgArrow);
addMarkerToGroup(iconGroup, {lat:Latitude, lng:Longitude},
'', {icon:iconSVG});
I tried some things with additional css which should work told by other user, but nothing helps to get the correct position.
did anyone had an idea how to solve this issue.
Thanks allot
The CSS styles have no effect in this case because the marker is rendered in the canvas, thus is not itself in the DOM tree.
However you can achieve what you need by specifying options to the H.map.Icon construction, more specifically using the property anchor which takes x and y offsets. Something like the following:
var iconSVG = new H.map.Icon(svgArrow, {
anchor: {
x: svgWidth / 2,
y: svgHeight / 2
}
});
I've been working on this problem for days. I am trying to implement a "free transform" tool for svgs. Similar to that of Raphael.FreeTransform or how you would move/rotate/scale images in MS Word. (Yes, I am aware there are libraries) The following jSFiddle displays my problem: https://jsfiddle.net/hLjvrep7/12/
There are 5 functions in the jsFiddle: rotate-t. shrink-t, grow-t, shrink, grow. The functions suffixed with '-t' also apply the current rotation transformation. e.g.:
grow-t
rect.attr({height : height * 1.25, width : width * 1.25}).transform('r' + degree);
grow
rect.attr({height : height * 1.25, width : width * 1.25});
Once an svg is rotated, then scaled. If you try to rotate the svg again (after scale), the svg jumps. To see this, go top the fiddle:
Hit rotate-t twice. Svg should rotate a total of 30 degrees from the rectangles origin.
Hit grow (not grow-t) twice. Note the top left position of the svg stays the same.
Hit rotate-t once. Note the svg jumps to a different position, then rotates.
Note hitting rotate-t subsequent times will continue to rotate the image around the origin (which is what I want the first time rotate-t is clicked)
One solution I had was to apply the current rotation transformation whenever changing the height and width. This fixes my previous problem, but introduces another problem. To see an example of this, go to the fiddle, and:
Hit rotate-t twice.
Hit grow-t a couple times. Notice the svg grows, but the top left position of the rectangle moves. That's a problem for me. I want the svg to grow without the top left corner to move.
Notes on using the jsFiddle:
Any combination of rotate-t, grow-t, shrink-t will exhibit the ideal rotation behavior (about the origin, no jumping). But this also demonstrates the undesired growing and shrinking (top left position moved when svg is on angle).
Any combination pf rotate-t, grow, shrink will exhibit the ideal scaling behavior (top left corner of svg doesn't move). But this also demonstrates the undesired rotation property (will jump around after different rotations and scales).
Bottom line: I want to be able to the svg rotate around the origin. Then grow the image, while the top left position remains the same. Then rotate the svg again, around the origin without any jumping.
I am aware the how the transform function impacts the local coordinate system of the svg. I'm leaning towards using rotate-t, grow, shrink combo and simply apply some x-y offsets to remove the "jumping" effect. I would imagine there must be some sort of offset I could apply to avoid jumping or shifting during rotation or scaling, but its not clear to me how to calculate such offsets. Any help would be appreciated.
Please don't hesitate to ask anymore questions. Like I said, I've been digging into this for days. Clearly, I don't understand it all, but am somewhat intimate with what's happening and happy to explain anything in more detail.
My solutions for scale, rotate, move back and front etc:
$scope.back = function () {
if($scope.currentImage !==null) {
if($scope.currentImage.prev!=undefined) {
var bot = $scope.currentImage.prev;
$scope.currentImage.insertBefore(bot);
ft.apply();
}
}
};
//Function for moving front
$scope.front = function () {
if($scope.currentImage !==null) {
if($scope.currentImage.next!=undefined) {
var top = $scope.currentImage.next;
if($scope.currentImage.next.node.localName == "image")
$scope.currentImage.insertAfter(top);
ft.apply();
}
}
};
//ZOOM
$scope.zoomIn = function () {
if ($scope.currentImage!= null) {
var ft = paper.freeTransform($scope.currentImage);
if(ft.attrs.scale.y<4) {
$scope.currentImage.toFront();
ft.attrs.scale.y = ft.attrs.scale.y *(1.1);
ft.attrs.scale.x = ft.attrs.scale.x *(1.1);
ft.apply();
ft.updateHandles();
}
}
};
I'm trying to get the style.left and style.top of a rectangular div, after it has been rotated using style.transform=rotate(90deg).
I understand how the div is being rotated, with it being rotated around a 'transform point'. And I also understand that a div could be rotated by 45 degrees, so giving the new top/left of that would be awkward (In effect giving the bounding box left/top).
But back to the original question, rotating the rectangular div by 90 degrees, is there a way to get the 'new' left/top?
The reason I need this, is for a project im working on to upload images, allow the user to zoom, rotate etc, but currently having to do it with PHP to keep all the dimensions correct for the final image (Which is obviously bad, because I'm having to keep loading a new image once PHP has done the rotating/zooming etc)
I've also made a little jsfiddle showing that the top/left position doesn't change when it is rotated
Okay, thanks to the comment left above, I managed to throw together an answer.
Basically using:
newleft = parseInt(div.style.top) + Math.cos(90) * parseInt(div.style.height);
newtop = parseInt(div.style.left) + Math.sin(90) * parseInt(div.style.height);
after the div had been rotated.
I've updated my jsfiddle aswell, because the one in the comment above uses jQuery, but this way uses only javascript.
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()
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