Mapbox how to control map zooming speed in a mouse scroll - javascript

I use mapbox (https://www.mapbox.com) and I want to make the zooming of the map slower during mouse scroll. Apparently, the API doc didn't have the speed control unless it is, for example, a flyTo() method or so.
I tried to control the speed of a zoom event that is triggered during zoom event but that didn't work as well. Could there be a way to control the speed of a zoom during mouse scroll zoom?

I ended up solving this by myself. I disabled the mapbox scroll by
map.scrollWheelZoom.disable();
And then applied the standard jquery on wheel event on the div ID that holds the map.
$(document).on('wheel','#map', function(e){
e.preventDefault();
if(e.originalEvent.wheelDelta/120 > 0) {
scrollZoomMap('up')
}
else{
scrollZoomMap('down')
}
}
and scollZoomMap function could look like this
function scrollZoomMap(dir){
//console.log("dir : " + dir);
var newZoom = null;
var debounce;
var el = map; //the mapbox instance.
latLng = el.getCenter();
var latitude = latLng["lat"];
var longitude = latLng["lng"];
var currentZoom = el.getZoom();
if (debounce) clearTimeout(debounce);
debounce = setTimeout(function(){
debounce = null;
if(dir == "up"){
newZoom = currentZoom + 1;
}else{
newZoom = currentZoom - 1;
}
if( newZoom > 0 && newZoom < 22){
//console.log("newZoom : " + newZoom);
el.setView([latitude, longitude], newZoom);
}
}, 300);
}

Related

How to zoom in/out page in javascript

I want to make a button that zoom in/out the page in Google Chrome.(Like if i'm pressing ctrl and + or ctrl and -). Please help me. I don't want to zoom element(body).
There are many ways to do it,you have to write both ZoomIn and ZoomOut functions for it.
below is the working code.
function zoomIn()
{
var Page = document.getElementById('Body');
var zoom = parseInt(Page.style.zoom) + 10 +'%'
Page.style.zoom = zoom;
return false;
}
function zoomOut()
{
var Page = document.getElementById('Body');
var zoom = parseInt(Page.style.zoom) - 10 +'%'
Page.style.zoom = zoom;
return false;
}
(though it is Copied code).
And make sure you add style=”zoom: 100%” in your <body> tag of web page.
Here is how to zoom in and out.
function zoomIn(){
var body = document.querySelector("body");
var currWidth = body.clientWidth;
if(currWidth == 1000000){
alert("Maximum zoom-in level of 1 Million reached.");
} else{
body.style.width = (currWidth + 50) + "px";
}
}
function zoomOut(){
var body = document.querySelector("body");
var currWidth = body.clientWidth;
if(currWidth == 500000){
alert("Maximum zoom-out level reached.");
} else{
body.style.width = (currWidth - 50) + "px";
}
}
Zoom in by running zoomIn()
Zoom out by runnint zoomOut()
set the zoom property in style of top level html element. Its the closest thing to browser zooming.
document.firstElementChild.style.zoom = 0.85;
You can use a step value of, say 0.05 on - and + buttons.
If you want to do it according to window. you can do it by:
window.onresize = function(){
let zoom = Number((window.innerWidth / window.screen.width).toFixed(3));
document.firstElementChild.style.zoom = zoom;
}

How to position the HERE maps infobubble, so it does not hide the marker

Here's a picture. The default infobubble covers the marker it belongs to (see the bottom right corner of the bubble):
This is from their official example.
Is there an easy way to make the marker appear above the bubble, so the bubble does not hide it?
Currently, it's confusing, because it's not easy to see which marker the bubble belongs to.
Here's my simple solution based on the other answer by Here support:
var xy = map.geoToScreen(coords);
var bubble = new H.ui.InfoBubble(map.screenToGeo(xy.x, xy.y - 30), {
content: 'content'
});
ui.addBubble(bubble);
coords is the marker coordinates, and it places the infowindow 30 pixel above the marker.
This works for me, because in my case the marker is always in the center of map.
Edit: it's not perfect, because if you zoom the map then the marker and bubble point to different places, so there should also be an event handler which updates the bubble position when zooming
You can try this sample code:
// check if info bubble is visible, otherwise move the map center
function checkInfoBubble(infoBubble){
setTimeout(function() {
if(infoBubble && infoBubble.getState() == "open"){
var border = 50;
var objRect = infoBubble.getContentElement().parentElement.getBoundingClientRect();
var objStyleRight = Math.abs(parseInt(infoBubble.getContentElement().parentElement.style.right));
objStyleRight = objStyleRight ? objStyleRight : 0;
var mapRect = map.getElement().getBoundingClientRect();
var shiftX = 0;
var shiftY = 0;
// check, if infobubble isn't too far to up
if ((objRect.top-border) < mapRect.top) {
shiftY = (mapRect.top - (objRect.top-border));
}
// check, if infobubble isn't too far to the left
var objLeft = (objRect.left - objStyleRight);
if ((objLeft-border) < mapRect.left) {
shiftX = (mapRect.left - (objLeft-border));
} // check, if infobubble isn't too far to the right
else if ((objRect.right+border) > mapRect.right) {
shiftX = -(objRect.right - (mapRect.right-border));
}
if ((shiftX == 0) && (shiftY == 0)) {
return;
}
var currScreenCenter = map.geoToScreen(map.getCenter());
var newY = (currScreenCenter.y - shiftY);
var newX = (currScreenCenter.x - shiftX);
var newGeoCenter = map.screenToGeo(newX, newY);
map.setCenter(newGeoCenter, true);
}
}, 20);
}
Furthermore is shown here: https://tcs.ext.here.com/examples/v3/show_info_on_hover

Google maps api V3 - zoom on mouse wheel only if ALT key is pressed

I use google map api v3 in my website: the map is width 100% and height 450px. So, when you scroll the page, it will automatically stop on the map because of the mousewheel event to zoom the map. I don't want to disable it because it's kind of a cool feature so I was looking for a way to zoom on mouse wheel only if ALT key is pressed. First, I did it with jQuery like this:
<div id="my_map" class="Scrollable"
onmouseover="hover_div['my_map']=true;" onmouseout="hover_div['my_map']=false;">
"hover_div" is a global array defined in the head, "map" is a global variable (with "scrollwheel" set to false)
$('.Scrollable').on('DOMMouseScroll mousewheel', function(ev) {
if(ev.altKey && hover_div['my_map']){
var $this = $(this),
scrollTop = this.scrollTop,
scrollHeight = this.scrollHeight,
height = $this.height(),
delta = (ev.type == 'DOMMouseScroll' ?
ev.originalEvent.detail * -40 :
ev.originalEvent.wheelDelta),
up = delta > 0;
var prevent = function() {
ev.stopPropagation();
ev.preventDefault();
ev.returnValue = false;
return false;
}
if (!up && -delta > scrollHeight - height - scrollTop) {
$this.scrollTop(scrollHeight);
var mapZoom = parseFloat(map.getZoom());
if(mapZoom > 0){
mapZoom = mapZoom - 1;
map.setZoom(mapZoom);
}
return prevent();
} else if (up && delta > scrollTop) {
$this.scrollTop(0);
var mapZoom = parseFloat(map.getZoom());
if(mapZoom < 21){
mapZoom = mapZoom + 1;
map.setZoom(mapZoom);
}
return prevent();
}
}
});
It's working, but it zoom from the center without considering the mouse position as the default event does.
I found this fiddle who trigger the Google Maps mouse wheel event: maybe there's a way to launch the default event only if the ALT key is pressed, but I haven't figured it out yet.

Simplest way to detect a pinch

This is a WEB APP not a native app. Please no Objective-C NS commands.
So I need to detect 'pinch' events on iOS. Problem is every plugin or method I see for doing gestures or multi-touch events, is (usually) with jQuery and is a whole additional pluggin for every gesture under the sun. My application is huge, and I am very sensitive to deadwood in my code. All I need is to detect a pinch, and using something like jGesture is just way to bloated for my simple needs.
Additionally, I have a limited understanding of how to detect a pinch manually. I can get the position of both fingers, can't seem to get the mix right to detect this. Does anyone have a simple snippet that JUST detects pinch?
Think about what a pinch event is: two fingers on an element, moving toward or away from each other.
Gesture events are, to my knowledge, a fairly new standard, so probably the safest way to go about this is to use touch events like so:
(ontouchstart event)
if (e.touches.length === 2) {
scaling = true;
pinchStart(e);
}
(ontouchmove event)
if (scaling) {
pinchMove(e);
}
(ontouchend event)
if (scaling) {
pinchEnd(e);
scaling = false;
}
To get the distance between the two fingers, use the hypot function:
var dist = Math.hypot(
e.touches[0].pageX - e.touches[1].pageX,
e.touches[0].pageY - e.touches[1].pageY);
You want to use the gesturestart, gesturechange, and gestureend events. These get triggered any time 2 or more fingers touch the screen.
Depending on what you need to do with the pinch gesture, your approach will need to be adjusted. The scale multiplier can be examined to determine how dramatic the user's pinch gesture was. See Apple's TouchEvent documentation for details about how the scale property will behave.
node.addEventListener('gestureend', function(e) {
if (e.scale < 1.0) {
// User moved fingers closer together
} else if (e.scale > 1.0) {
// User moved fingers further apart
}
}, false);
You could also intercept the gesturechange event to detect a pinch as it happens if you need it to make your app feel more responsive.
Hammer.js all the way! It handles "transforms" (pinches).
http://eightmedia.github.com/hammer.js/
But if you wish to implement it youself, i think that Jeffrey's answer is pretty solid.
Unfortunately, detecting pinch gestures across browsers is a not as simple as one would hope, but HammerJS makes it a lot easier!
Check out the Pinch Zoom and Pan with HammerJS demo. This example has been tested on Android, iOS and Windows Phone.
You can find the source code at Pinch Zoom and Pan with HammerJS.
For your convenience, here is the source code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport"
content="user-scalable=no, width=device-width, initial-scale=1, maximum-scale=1">
<title>Pinch Zoom</title>
</head>
<body>
<div>
<div style="height:150px;background-color:#eeeeee">
Ignore this area. Space is needed to test on the iPhone simulator as pinch simulation on the
iPhone simulator requires the target to be near the middle of the screen and we only respect
touch events in the image area. This space is not needed in production.
</div>
<style>
.pinch-zoom-container {
overflow: hidden;
height: 300px;
}
.pinch-zoom-image {
width: 100%;
}
</style>
<script src="https://hammerjs.github.io/dist/hammer.js"></script>
<script>
var MIN_SCALE = 1; // 1=scaling when first loaded
var MAX_SCALE = 64;
// HammerJS fires "pinch" and "pan" events that are cumulative in nature and not
// deltas. Therefore, we need to store the "last" values of scale, x and y so that we can
// adjust the UI accordingly. It isn't until the "pinchend" and "panend" events are received
// that we can set the "last" values.
// Our "raw" coordinates are not scaled. This allows us to only have to modify our stored
// coordinates when the UI is updated. It also simplifies our calculations as these
// coordinates are without respect to the current scale.
var imgWidth = null;
var imgHeight = null;
var viewportWidth = null;
var viewportHeight = null;
var scale = null;
var lastScale = null;
var container = null;
var img = null;
var x = 0;
var lastX = 0;
var y = 0;
var lastY = 0;
var pinchCenter = null;
// We need to disable the following event handlers so that the browser doesn't try to
// automatically handle our image drag gestures.
var disableImgEventHandlers = function () {
var events = ['onclick', 'onmousedown', 'onmousemove', 'onmouseout', 'onmouseover',
'onmouseup', 'ondblclick', 'onfocus', 'onblur'];
events.forEach(function (event) {
img[event] = function () {
return false;
};
});
};
// Traverse the DOM to calculate the absolute position of an element
var absolutePosition = function (el) {
var x = 0,
y = 0;
while (el !== null) {
x += el.offsetLeft;
y += el.offsetTop;
el = el.offsetParent;
}
return { x: x, y: y };
};
var restrictScale = function (scale) {
if (scale < MIN_SCALE) {
scale = MIN_SCALE;
} else if (scale > MAX_SCALE) {
scale = MAX_SCALE;
}
return scale;
};
var restrictRawPos = function (pos, viewportDim, imgDim) {
if (pos < viewportDim/scale - imgDim) { // too far left/up?
pos = viewportDim/scale - imgDim;
} else if (pos > 0) { // too far right/down?
pos = 0;
}
return pos;
};
var updateLastPos = function (deltaX, deltaY) {
lastX = x;
lastY = y;
};
var translate = function (deltaX, deltaY) {
// We restrict to the min of the viewport width/height or current width/height as the
// current width/height may be smaller than the viewport width/height
var newX = restrictRawPos(lastX + deltaX/scale,
Math.min(viewportWidth, curWidth), imgWidth);
x = newX;
img.style.marginLeft = Math.ceil(newX*scale) + 'px';
var newY = restrictRawPos(lastY + deltaY/scale,
Math.min(viewportHeight, curHeight), imgHeight);
y = newY;
img.style.marginTop = Math.ceil(newY*scale) + 'px';
};
var zoom = function (scaleBy) {
scale = restrictScale(lastScale*scaleBy);
curWidth = imgWidth*scale;
curHeight = imgHeight*scale;
img.style.width = Math.ceil(curWidth) + 'px';
img.style.height = Math.ceil(curHeight) + 'px';
// Adjust margins to make sure that we aren't out of bounds
translate(0, 0);
};
var rawCenter = function (e) {
var pos = absolutePosition(container);
// We need to account for the scroll position
var scrollLeft = window.pageXOffset ? window.pageXOffset : document.body.scrollLeft;
var scrollTop = window.pageYOffset ? window.pageYOffset : document.body.scrollTop;
var zoomX = -x + (e.center.x - pos.x + scrollLeft)/scale;
var zoomY = -y + (e.center.y - pos.y + scrollTop)/scale;
return { x: zoomX, y: zoomY };
};
var updateLastScale = function () {
lastScale = scale;
};
var zoomAround = function (scaleBy, rawZoomX, rawZoomY, doNotUpdateLast) {
// Zoom
zoom(scaleBy);
// New raw center of viewport
var rawCenterX = -x + Math.min(viewportWidth, curWidth)/2/scale;
var rawCenterY = -y + Math.min(viewportHeight, curHeight)/2/scale;
// Delta
var deltaX = (rawCenterX - rawZoomX)*scale;
var deltaY = (rawCenterY - rawZoomY)*scale;
// Translate back to zoom center
translate(deltaX, deltaY);
if (!doNotUpdateLast) {
updateLastScale();
updateLastPos();
}
};
var zoomCenter = function (scaleBy) {
// Center of viewport
var zoomX = -x + Math.min(viewportWidth, curWidth)/2/scale;
var zoomY = -y + Math.min(viewportHeight, curHeight)/2/scale;
zoomAround(scaleBy, zoomX, zoomY);
};
var zoomIn = function () {
zoomCenter(2);
};
var zoomOut = function () {
zoomCenter(1/2);
};
var onLoad = function () {
img = document.getElementById('pinch-zoom-image-id');
container = img.parentElement;
disableImgEventHandlers();
imgWidth = img.width;
imgHeight = img.height;
viewportWidth = img.offsetWidth;
scale = viewportWidth/imgWidth;
lastScale = scale;
viewportHeight = img.parentElement.offsetHeight;
curWidth = imgWidth*scale;
curHeight = imgHeight*scale;
var hammer = new Hammer(container, {
domEvents: true
});
hammer.get('pinch').set({
enable: true
});
hammer.on('pan', function (e) {
translate(e.deltaX, e.deltaY);
});
hammer.on('panend', function (e) {
updateLastPos();
});
hammer.on('pinch', function (e) {
// We only calculate the pinch center on the first pinch event as we want the center to
// stay consistent during the entire pinch
if (pinchCenter === null) {
pinchCenter = rawCenter(e);
var offsetX = pinchCenter.x*scale - (-x*scale + Math.min(viewportWidth, curWidth)/2);
var offsetY = pinchCenter.y*scale - (-y*scale + Math.min(viewportHeight, curHeight)/2);
pinchCenterOffset = { x: offsetX, y: offsetY };
}
// When the user pinch zooms, she/he expects the pinch center to remain in the same
// relative location of the screen. To achieve this, the raw zoom center is calculated by
// first storing the pinch center and the scaled offset to the current center of the
// image. The new scale is then used to calculate the zoom center. This has the effect of
// actually translating the zoom center on each pinch zoom event.
var newScale = restrictScale(scale*e.scale);
var zoomX = pinchCenter.x*newScale - pinchCenterOffset.x;
var zoomY = pinchCenter.y*newScale - pinchCenterOffset.y;
var zoomCenter = { x: zoomX/newScale, y: zoomY/newScale };
zoomAround(e.scale, zoomCenter.x, zoomCenter.y, true);
});
hammer.on('pinchend', function (e) {
updateLastScale();
updateLastPos();
pinchCenter = null;
});
hammer.on('doubletap', function (e) {
var c = rawCenter(e);
zoomAround(2, c.x, c.y);
});
};
</script>
<button onclick="zoomIn()">Zoom In</button>
<button onclick="zoomOut()">Zoom Out</button>
<div class="pinch-zoom-container">
<img id="pinch-zoom-image-id" class="pinch-zoom-image" onload="onLoad()"
src="https://hammerjs.github.io/assets/img/pano-1.jpg">
</div>
</div>
</body>
</html>
detect two fingers pinch zoom on any element, easy and w/o hassle with 3rd party libs like Hammer.js (beware, hammer has issues with scrolling!)
function onScale(el, callback) {
let hypo = undefined;
el.addEventListener('touchmove', function(event) {
if (event.targetTouches.length === 2) {
let hypo1 = Math.hypot((event.targetTouches[0].pageX - event.targetTouches[1].pageX),
(event.targetTouches[0].pageY - event.targetTouches[1].pageY));
if (hypo === undefined) {
hypo = hypo1;
}
callback(hypo1/hypo);
}
}, false);
el.addEventListener('touchend', function(event) {
hypo = undefined;
}, false);
}
The simplest way is to respond to the 'wheel' event.
You need to call ev.preventDefault() to prevent the browser from doing a full screen zoom.
Browsers synthesize the 'wheel' event for pinches on a trackpad, and as a bonus you also handle mouse wheel events. This is the way mapping applications handle it.
More details in my example:
let element = document.getElementById('el');
let scale = 1.0;
element.addEventListener('wheel', (ev) => {
// This is crucial. Without it, the browser will do a full page zoom
ev.preventDefault();
// This is an empirically determined heuristic.
// Unfortunately I don't know of any way to do this better.
// Typical deltaY values from a trackpad pinch are under 1.0
// Typical deltaY values from a mouse wheel are more than 100.
let isPinch = Math.abs(ev.deltaY) < 50;
if (isPinch) {
// This is a pinch on a trackpad
let factor = 1 - 0.01 * ev.deltaY;
scale *= factor;
element.innerText = `Pinch: scale is ${scale}`;
} else {
// This is a mouse wheel
let strength = 1.4;
let factor = ev.deltaY < 0 ? strength : 1.0 / strength;
scale *= factor;
element.innerText = `Mouse: scale is ${scale}`;
}
});
<div id='el' style='width:400px; height:300px; background:#ffa'>
Scale: 1.0
</div>
None of these answers achieved what I was looking for, so I wound up writing something myself. I wanted to pinch-zoom an image on my website using my MacBookPro trackpad. The following code (which requires jQuery) seems to work in Chrome and Edge, at least. Maybe this will be of use to someone else.
function setupImageEnlargement(el)
{
// "el" represents the image element, such as the results of document.getElementByd('image-id')
var img = $(el);
$(window, 'html', 'body').bind('scroll touchmove mousewheel', function(e)
{
//TODO: need to limit this to when the mouse is over the image in question
//TODO: behavior not the same in Safari and FF, but seems to work in Edge and Chrome
if (typeof e.originalEvent != 'undefined' && e.originalEvent != null
&& e.originalEvent.wheelDelta != 'undefined' && e.originalEvent.wheelDelta != null)
{
e.preventDefault();
e.stopPropagation();
console.log(e);
if (e.originalEvent.wheelDelta > 0)
{
// zooming
var newW = 1.1 * parseFloat(img.width());
var newH = 1.1 * parseFloat(img.height());
if (newW < el.naturalWidth && newH < el.naturalHeight)
{
// Go ahead and zoom the image
//console.log('zooming the image');
img.css(
{
"width": newW + 'px',
"height": newH + 'px',
"max-width": newW + 'px',
"max-height": newH + 'px'
});
}
else
{
// Make image as big as it gets
//console.log('making it as big as it gets');
img.css(
{
"width": el.naturalWidth + 'px',
"height": el.naturalHeight + 'px',
"max-width": el.naturalWidth + 'px',
"max-height": el.naturalHeight + 'px'
});
}
}
else if (e.originalEvent.wheelDelta < 0)
{
// shrinking
var newW = 0.9 * parseFloat(img.width());
var newH = 0.9 * parseFloat(img.height());
//TODO: I had added these data-attributes to the image onload.
// They represent the original width and height of the image on the screen.
// If your image is normally 100% width, you may need to change these values on resize.
var origW = parseFloat(img.attr('data-startwidth'));
var origH = parseFloat(img.attr('data-startheight'));
if (newW > origW && newH > origH)
{
// Go ahead and shrink the image
//console.log('shrinking the image');
img.css(
{
"width": newW + 'px',
"height": newH + 'px',
"max-width": newW + 'px',
"max-height": newH + 'px'
});
}
else
{
// Make image as small as it gets
//console.log('making it as small as it gets');
// This restores the image to its original size. You may want
//to do this differently, like by removing the css instead of defining it.
img.css(
{
"width": origW + 'px',
"height": origH + 'px',
"max-width": origW + 'px',
"max-height": origH + 'px'
});
}
}
}
});
}
My answer is inspired by Jeffrey's answer. Where that answer gives a more abstract solution, I try to provide more concrete steps on how to potentially implement it. This is simply a guide, one that can be implemented more elegantly. For a more detailed example check out this tutorial by MDN web docs.
HTML:
<div id="zoom_here">....</div>
JS
<script>
var dist1=0;
function start(ev) {
if (ev.targetTouches.length == 2) {//check if two fingers touched screen
dist1 = Math.hypot( //get rough estimate of distance between two fingers
ev.touches[0].pageX - ev.touches[1].pageX,
ev.touches[0].pageY - ev.touches[1].pageY);
}
}
function move(ev) {
if (ev.targetTouches.length == 2 && ev.changedTouches.length == 2) {
// Check if the two target touches are the same ones that started
var dist2 = Math.hypot(//get rough estimate of new distance between fingers
ev.touches[0].pageX - ev.touches[1].pageX,
ev.touches[0].pageY - ev.touches[1].pageY);
//alert(dist);
if(dist1>dist2) {//if fingers are closer now than when they first touched screen, they are pinching
alert('zoom out');
}
if(dist1<dist2) {//if fingers are further apart than when they first touched the screen, they are making the zoomin gesture
alert('zoom in');
}
}
}
document.getElementById ('zoom_here').addEventListener ('touchstart', start, false);
document.getElementById('zoom_here').addEventListener('touchmove', move, false);
</script>
Its same as commented by Jeffrey Sweeney, Full example to how to implement in your class.
this.touch.isPinch = false;
this.touc.pinchStart = 0;
this.touch.onTouchStart = (e) => {
if (e.touches.length === 2) {
this.touch.pinchStart = Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY);
this.touch.isScaling = true;
}
}
this.touch.onTouchMove = (e) => {
if (this.touch.isScaling) {
const distance = Math.hypot(e.touches[0].pageX - e.touches[1].pageX, e.touches[0].pageY - e.touches[1].pageY);
if (this.touch.pinchStart >= 200 && distance <= 90) this.touchPichOut(); //call function for pinchOut
if (this.touch.pinchStart <= 100 && distance >= 280) this.touchPichIn(); //call function for pinchIn
}
}
this.touch.onTouchCancel = (e) => {
this.touch.isScaling = false;
}
this.touch.onTouchEnd = (e) => {
if (this.touch.isScaling) this.touch.isScaling = false;
}
Regards

The author of this Raphael JS extension has vanished from the face of the internet, help me with his script

The extension I'm talking about is the Raphael-zpd: http://pohjoisespoo.net84.net/src/raphael-zpd.js
/* EDIT The script is added to a Raphael document with this command var zpd = new RaphaelZPD(paper, { zoom: true, pan: true, drag: false}); where paper is your canvas */
The script was originally released at the authors github http://www.github.com/somnidea which no longer exists.
What I wanted to do was run the mousewheel zoom out to the threshold as soon as the raphael is loaded. The zoomthreshold is set at the beginning of the script zoomThreshold: [-37, 20]. In the mousewheel scroll function it is compared to zoomCurrent which is by default 0 me.zoomCurrent = 0;
This is the whole mousewheel event part
me.handleMouseWheel = function(evt) {
if (!me.opts.zoom) return;
if (evt.preventDefault)
evt.preventDefault();
evt.returnValue = false;
var svgDoc = evt.target.ownerDocument;
var delta;
if (evt.wheelDelta)
delta = evt.wheelDelta / 3600; // Chrome/Safari
else
delta = evt.detail / -90; // Mozilla
if (delta > 0) {
if (me.opts.zoomThreshold)
if (me.opts.zoomThreshold[1] <= me.zoomCurrent) return;
me.zoomCurrent++;
} else {
if (me.opts.zoomThreshold)
if (me.opts.zoomThreshold[0] >= me.zoomCurrent) return;
me.zoomCurrent--;
}
var z = 1 + delta; // Zoom factor: 0.9/1.1
var g = svgDoc.getElementById("viewport"+me.id);
var p = me.getEventPoint(evt);
p = p.matrixTransform(g.getCTM().inverse());
// Compute new scale matrix in current mouse position
var k = me.root.createSVGMatrix().translate(p.x, p.y).scale(z).translate(-p.x, -p.y);
me.setCTM(g, g.getCTM().multiply(k));
if (!me.stateTf)
me.stateTf = g.getCTM().inverse();
me.stateTf = me.stateTf.multiply(k.inverse());
}
The reason I can't just draw a smaller SVG to begin with is that I'm using raster images as the background and need them to be higher resolution. I would still like to start at the furthest point I've set at the threshold. Is it possible for me to somehow use this script to do this? I'm naturally using it otherwise to handle mouse zoom/pan.
//EDIT
There is also this function at the end of the script, but so far I've been unable to work it.
Raphael.fn.ZPDPanTo = function(x, y) {
var me = this;
if (me.gelem.getCTM() == null) {
alert('failed');
return null;
}
var stateTf = me.gelem.getCTM().inverse();
var svg = document.getElementsByTagName("svg")[0];
if (!svg.createSVGPoint) alert("no svg");
var p = svg.createSVGPoint();
p.x = x;
p.y = y;
p = p.matrixTransform(stateTf);
var element = me.gelem;
var matrix = stateTf.inverse().translate(p.x, p.y);
var s = "matrix(" + matrix.a + "," + matrix.b + "," + matrix.c + "," + matrix.d + "," + matrix.e + "," + matrix.f + ")";
element.setAttribute("transform", s);
return me;
}
Seems like it's used for panning through the document through say click events so that a click would execute the function with the given coordinates. However, as said I've been unable to work it. I don't know how it's supposed to function. I tried paper.ZPDPanTo(100, 100); as well as just ZPDPanTo(100,100) but nothing happens.
You may also want to check out the working branch for Raphaël 2.0, which supposedly adds support for viewBox and transforms, see https://github.com/DmitryBaranovskiy/raphael/tree/2.0.
This doesn't answer your question fully, but it seems quite possible that Raphaël 2.0 will address your use-case.
If you're using pure svg then you can manipulate the zoom&pan positions via the SVG DOM properties currentTranslate and currentScale, see this example.
An example using RAPHAEL ZPD:
var paper = Raphael("container",800,760);
window.paper = paper;
zpd = new RaphaelZPD(paper, { zoom: true, pan: true, drag: false });
paper.circle(100,100, 50).attr({fill:randomRGB(),opacity:0.95});
paper.rect(100,100, 250, 300).attr({fill:randomRGB(),opacity:0.65});
paper.circle(200,100, 50).attr({fill:randomRGB(),opacity:0.95});
paper.circle(100,200, 50).attr({fill:randomRGB(),opacity:0.95});
http://jsfiddle.net/4PkRm/1/

Categories

Resources