问题
I am writing a cross platform web application that displays information using SVG. I need to have a multi-touch interface to pan and zoom the SVG graphic. From my research, it appears that Hammer.js is my best approach, and I am using the jQuery library version.
I am able to pan and zoom the image using the viewBox property of the SVG. The problem I'm having is using the center point information during the pinch zoom (vs. scaling from the top left corner). That center point, wherever it is in my image, should remain in the center of the pinch. Clearly, the solution is to modify the first two parts of the viewBox, but I'm having trouble determining the correct values. The center point (event.gesture.center) appears to be in browser page coordinates, so I need to figure out how to reliably scale this and then calculate the viewBox x and y coordinates. I've looked for examples, but couldn't find anything that quite related.
Is using the viewBox attribute the best way to scale SVG images? Are there better alternatives? Does anyone have sample code of zooming an SVG image from the pinch center?
Also, I'm noticing that even though I'm binding the event handling to the SVG element, the pinch gesture seems to work from anywhere on the page. It isn't the default browser handling of the pinch because it is only zooming the SVG image using my code. Here's the code I'm using for binding the pinch event:
$(window.demoData.svgElement).hammer().on("pinch", function (event) {
event.preventDefault();
...
});
Thanks for any help on these two issues.
回答1:
I'm glad that some one else has been looking to solve these problems. It seems that SVG hasn't so far had enough attention.
I have been looking and working on solutions for several months. Firstly, you have three options for moving an SVG.
- Using the viewBox as you said. This is I think the best solution if you want to treat the image as a single item.
- You can use css transforms of the SVG element. the downside is this causes pixelation but means that you can use solutions that exist for other kinds of elements
- You can use svg transforms on elements or groups of elements within the SVG.
To answer the question of code a centered pinch can be described as follows. First you need to translate the pinch event center point from screen coordinate to SVG coordinates using the screenCTM (coordinate transform matrix). if point has coordinates (x,y) then the origin of you viewbox needs to undergo a transformation equivalent to
- translation(-x, -y)
- scale(scalefactor)
- translation(x, y)
I have made this work 'mostly' in a library I have called hammerhead which runs on top of hammerjs. Here is an example of it in action.I won't give you code to exactly solve your problem as there is too much code to go where you have put '...' I ended up writing a viewBox object to manipulate. Just for reference here is the code I use to manipulate that.
scale: function(scale, center){
var boxScale = 1.0/scale;
center = center || this.center();
var newMinimal = this.getMinimal().subtract(center).multiply(boxScale).add(center);
var newMaximal = this.getMaximal().subtract(center).multiply(boxScale).add(center);
var newViewBox = viewBox(newMinimal, newMaximal, this.getValidator());
return newViewBox.valid()? newViewBox : null;
}
This method is not without problems. Change the viewBox is very computationally intensive I will not make for a pleasant scrolling experience on a phone except for an image with very few elements. It will work nicely if you change the view once in response to an action. for example left right up down keys. I have explored some of other options I mentioned above in these repos
- svg maneuver
- svg agile
- svgViewer
As I mentioned trying for quite sometime. These all use one of the approaches individually. To get both smooth scrolling and no pixilation I think will require a combination of both. For which I am working on yet another library.
回答2:
The best method is to use svg transforms, with a combination of translate and scale you can perform a zoom centered on your pinch. You just need to figure out the formula. This example can help you (it uses css transforms but you get the idea): https://github.com/EightMedia/hammer.js/blob/1.0.x/examples/pinchzoom.html
回答3:
There is another library designed specifically for this task called PanZoom. Unfortunately, it doesn't play well with Hammer. I've used it to zoom in / out of SVG files with great success.
https://github.com/timmywil/jquery.panzoom
来源:https://stackoverflow.com/questions/18275774/zooming-svg-with-hammer-js