+ When pressing the buttons, the image is resized by the corresponding
+ percentage of the images natural size, but the map area is only scaled
+ if the percentage of natural size is less than or equal to 99% or
+ greater than or equal to 101%.
+
+
+ Note - Floating point calculations are not precise which could result in
+ otherwise unexpected fractional differences in precision when adjusting
+ image size.
+
+
+
diff --git a/site/src/content/docs/reference/configuration-reference.md b/site/src/content/docs/reference/configuration-reference.md
index caa1e06..16322cf 100644
--- a/site/src/content/docs/reference/configuration-reference.md
+++ b/site/src/content/docs/reference/configuration-reference.md
@@ -1077,7 +1077,8 @@ $('#myimage').mapster({
### scaleMap
**Type:** `boolean`
-**Default:** `true`
+**Default:** `true`
+**See Also:** [`scaleMapBounds`](#scalemapbounds)
Automatically scale image maps to the current display size of the image.
@@ -1093,6 +1094,29 @@ $('#myimage').mapster({
});
```
+### scaleMapBounds
+
+**Type:** `false | { below: number, above: number }`
+**Default:** `{ below: 0.98, above: 1.02 }`
+**See Also:** [`scaleMap`](#scalemap)
+
+The boundary to restrict scaling when [scaleMap](#scalemap) is enabled.
+
+When an image map is resized, it's map area coordinates are scaled to correspond with the displayed image size.
+
+When the percentage of the displayed image size relative to the natural image size is between `below` and `after` (not inclusive), the map area coordinates will be scaled based on 100% of the natural image size. When the percentage is outside of this boundary (inclusive), map area coordinates will be scaled based on the displayed image size.
+
+By default, scaling will occur when the displayed image size is 98% (or less) or 102% (or more) of its natural image size.
+
+Setting this value to `false` will scale the map areas based on displayed image size without any restrictions.
+
+```js
+$('#myimage').mapster({
+ // scale down to any size but restrict scaling up to 105% or greater
+ scaleMapBounds: { below: 1, above: 1.05 }
+});
+```
+
## Bound List Options
ImageMapster supports assocating an image map to an external list in order to simplyfing synchronization of the map and the list. This allows for things such as selecting an item in a list and having the corresponding area in the image map become selected. You can provide a static collection of list items via the [boundList](#boundlist) option or generate the list items dynamically using the data provided in the [onGetList](#ongetlist) callback which supplies the list of all `area` elements ImageMapster found for the image map.
diff --git a/src/core.js b/src/core.js
index 9454719..5c426ce 100644
--- a/src/core.js
+++ b/src/core.js
@@ -66,6 +66,7 @@
configTimeout: 30000,
noHrefIsMask: true,
scaleMap: true,
+ scaleMapBounds: { below: 0.98, above: 1.02 },
enableAutoResizeSupport: false, // TODO: Remove in next major release
autoResize: false,
autoResizeDelay: 0,
diff --git a/src/mapdata.js b/src/mapdata.js
index 021faff..1613a34 100644
--- a/src/mapdata.js
+++ b/src/mapdata.js
@@ -777,7 +777,8 @@
me.scaleInfo = scale = u.scaleMap(
me.images[0],
me.images[1],
- opts.scaleMap
+ opts.scaleMap,
+ opts.scaleMapBounds
);
me.base_canvas = base_canvas = me.graphics.createVisibleCanvas(me);
diff --git a/src/scale.js b/src/scale.js
index 203ab81..de30d1e 100644
--- a/src/scale.js
+++ b/src/scale.js
@@ -11,7 +11,7 @@
u = m.utils,
p = m.MapArea.prototype;
- m.utils.getScaleInfo = function (eff, actual) {
+ m.utils.getScaleInfo = function (eff, actual, scaleMapBounds) {
var pct;
if (!actual) {
pct = 1;
@@ -19,7 +19,11 @@
} else {
pct = eff.width / actual.width || eff.height / actual.height;
// make sure a float error doesn't muck us up
- if (pct > 0.98 && pct < 1.02) {
+ if (
+ scaleMapBounds &&
+ pct > scaleMapBounds.below &&
+ pct < scaleMapBounds.above
+ ) {
pct = 1;
}
}
@@ -34,7 +38,7 @@
};
};
// Scale a set of AREAs, return old data as an array of objects
- m.utils.scaleMap = function (image, imageRaw, scale) {
+ m.utils.scaleMap = function (image, imageRaw, scale, scaleMapBounds) {
// stunningly, jQuery width can return zero even as width does not, seems to happen only
// with adBlock or maybe other plugins. These must interfere with onload events somehow.
@@ -47,7 +51,7 @@
if (!vis.complete()) {
vis = raw;
}
- return this.getScaleInfo(vis, scale ? raw : null);
+ return this.getScaleInfo(vis, scale ? raw : null, scaleMapBounds);
};
/**
@@ -123,7 +127,8 @@
{
width: me.scaleInfo.realWidth,
height: me.scaleInfo.realHeight
- }
+ },
+ me.options.scaleMapBounds
);
$.each(me.data, function (_, e) {
$.each(e.areas(), function (_, e) {
diff --git a/tests/resize.tests.js b/tests/resize.tests.js
index 76e50a9..5fc3748 100644
--- a/tests/resize.tests.js
+++ b/tests/resize.tests.js
@@ -88,6 +88,101 @@ this.tests.push(
})
);
+this.tests.push(
+ iqtest
+ .create('getScaleInfo', 'getScaleInfo scaleMapBounds')
+ .add('respects scale boundaries', function (a) {
+ 'use strict';
+
+ var result,
+ mu = $.mapster.utils,
+ bounds = { below: 0.95, above: 1.05 },
+ actual = { width: 100, height: 100 };
+
+ // scale up
+ result = mu.getScaleInfo(
+ { width: 104.998, height: 104.998 },
+ actual,
+ bounds
+ );
+ a.equals(
+ { scale: result.scale, scalePct: result.scalePct },
+ { scale: false, scalePct: 1 },
+ 'should not have scaled up when less than above bound'
+ );
+
+ result = mu.getScaleInfo({ width: 105, height: 105 }, actual, bounds);
+ a.equals(
+ { scale: result.scale, scalePct: result.scalePct },
+ { scale: true, scalePct: 105 / 100 },
+ 'should have scaled up when equal to above bound'
+ );
+
+ result = mu.getScaleInfo(
+ { width: 105.00000000001, height: 105.00000000001 },
+ actual,
+ 0.04999
+ );
+ a.equals(
+ { scale: result.scale, scalePct: result.scalePct },
+ { scale: true, scalePct: 105.00000000001 / 100 },
+ 'should have scaled up when greater than above bound'
+ );
+
+ result = mu.getScaleInfo(
+ { width: 104.998, height: 104.998 },
+ actual,
+ undefined
+ );
+ a.equals(
+ { scale: result.scale, scalePct: result.scalePct },
+ { scale: true, scalePct: 104.998 / 100 },
+ 'should have scaled up when no boundary'
+ );
+
+ // scale down
+ result = mu.getScaleInfo(
+ { width: 95.0000001, height: 95.0000001 },
+ actual,
+ bounds
+ );
+ a.equals(
+ { scale: result.scale, scalePct: result.scalePct },
+ { scale: false, scalePct: 1 },
+ 'should not have scaled down when greater than below bound'
+ );
+
+ result = mu.getScaleInfo({ width: 95, height: 95 }, actual, bounds);
+ a.equals(
+ { scale: result.scale, scalePct: result.scalePct },
+ { scale: true, scalePct: 95 / 100 },
+ 'should have scaled down when equal to below bound'
+ );
+
+ result = mu.getScaleInfo(
+ { width: 94.999999, height: 94.999999 },
+ actual,
+ bounds
+ );
+ a.equals(
+ { scale: result.scale, scalePct: result.scalePct },
+ { scale: true, scalePct: 94.999999 / 100 },
+ 'should have scaled down when less than below bound'
+ );
+
+ result = mu.getScaleInfo(
+ { width: 95.0000001, height: 95.0000001 },
+ actual,
+ undefined
+ );
+ a.equals(
+ { scale: result.scale, scalePct: result.scalePct },
+ { scale: true, scalePct: 95.0000001 / 100 },
+ 'should have scaled down when no boundary'
+ );
+ })
+);
+
this.tests.push(
iqtest
.create('autoresize', 'autoresize feature')