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()
Related
Following the docs around matrix transformations here: http://fabricjs.com/using-transformations
I replicated their demo at the bottom but instead of the new matrix being set to the minions on an event I am programmatically calling .rotate
The minion rotates correctly but it's position is off by a bit even with calling setCoords
What I expect to happen is that the blue minion stays in the same position relative to the red boss as it rotates but instead it moves as it rotates
Codesandbox: https://codesandbox.io/s/sharp-brook-st24pb?file=/src/index.js:812-820
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'm working on a web app where I don't really have web hooks for hovers (think touch device). I can get x coords of exactly where the mouse is at all times.
I need to check to see if the x coords of the mouse is over top of an image, and then grab that image I'm over top of.
What I'm doing
I'm using jQuery right now, and what I do is setup an array (imgCoords) of the offset.left value of each image. I then use
imgCoords.indexOf(mousePosition.x);
(mousePosition.x) is made up, but you get the idea.
I use the above code to grab the image that matches that returned index
fingerCoordToImgIndex = imgCoords.indexOf(mousePosition.x);
$('img').eq(fingerCoordToImgIndex).css({'stuff'});
This only works for the initial entry of mouse over image though (finger x only matches image x, not image x + width), and seems inefficient. I think I could thrash around a little longer to get it right, but I'd love it if one of you pro's could rescue me =p
Thanks tons!
-Ken
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