From 868ff07a1343489596fcd40a5d9c4848cd640858 Mon Sep 17 00:00:00 2001 From: Indigo744 Date: Thu, 2 Nov 2017 22:36:04 +0100 Subject: [PATCH 1/3] Add plot scaling option --- js/jquery.mapael.js | 133 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 125 insertions(+), 8 deletions(-) diff --git a/js/jquery.mapael.js b/js/jquery.mapael.js index 66ac943..f43e86f 100644 --- a/js/jquery.mapael.js +++ b/js/jquery.mapael.js @@ -66,7 +66,8 @@ zoomX: 0, zoomY: 0, panX: 0, - panY: 0 + panY: 0, + scaling: false }; self.currentViewBox = { @@ -530,6 +531,9 @@ var self = this; var $mapElem = $(elem.mapElem.node); + // Store element id + elem.id = id; + // If an HTML link exists for this element, add cursor attributes if (elem.options.href) { elem.options.attrs.cursor = "pointer"; @@ -603,7 +607,8 @@ $.extend(self.zoomData, { zoomLevel: 0, panX: 0, - panY: 0 + panY: 0, + scaling: false }); // init zoom buttons @@ -939,7 +944,94 @@ panX: panX, panY: panY, zoomX: panX + panWidth / 2, - zoomY: panY + panHeight / 2 + zoomY: panY + panHeight / 2, + scaling: false + }); + + // Check if we should scale plots + if (self.options.map.zoom.scalePlots === true) { + // Scaling: inverse fn of zoom value since we need to reduce size when increasing zoom + self.zoomData.scaling = 1 / relativeZoomLevel; + self.handlePlotsScaling(animDuration); + } + }, + + /* + * Get the plot scaling transform string + * + * @param id int plot id + * @return string + */ + getPlotScalingTransform: function(id) { + var self = this; + + // Assign scale string + var scaleStr = 's' + self.zoomData.scaling; + + // If text is defined, we need to udpdate the transform string to add center x,y + if (self.plots[id].textElem) { + // Get BBox of malelem to get the center coordinates (cx, cy) + var mapElemBBox = self.plots[id].mapElem.getBBox(); + // Transform strinf format is + // s[Scale on x],[Scale on y],[Scale center on X],[Scale center on Y] + scaleStr += "," + self.zoomData.scaling + "," + mapElemBBox.cx + "," + mapElemBBox.cy; + } + + return scaleStr; + }, + + /* + * Handle scaling of plots + * Apply a scaling transformation on plots depending on zoom level + * + * @param animDuration int animation duration in ms + */ + handlePlotsScaling: function(animDuration) { + var self = this; + + $.each(self.plots, function(id) { + // Assign scale string + var scaleStr = self.getPlotScalingTransform(id); + + // Save once transform if defined + if (self.plots[id].mapElem.transformWithoutZoomScaling === undefined) { + if (self.plots[id].options.attrs.transform) { + self.plots[id].mapElem.transformWithoutZoomScaling = self.plots[id].options.attrs.transform; + } else { + self.plots[id].mapElem.transformWithoutZoomScaling = ''; + } + } + + // If text is defined, we need to update the transform string to add center x,y + if (self.plots[id].textElem) { + + // Save once transform if defined + if (self.plots[id].textElem.transformWithoutZoomScaling === undefined) { + if (self.plots[id].options.text.attrs.transform) { + self.plots[id].textElem.transformWithoutZoomScaling = self.plots[id].options.text.attrs.transform; + } else { + self.plots[id].textElem.transformWithoutZoomScaling = ''; + } + } + + // Set text transform value + self.plots[id].options.text.attrs.transform = self.plots[id].textElem.transformWithoutZoomScaling + scaleStr; + + // Update text Hover options + self.setHoverOptions(self.plots[id].textElem, self.plots[id].options.text.attrs, self.plots[id].options.text.attrsHover); + + // Apply text transform + self.animate(self.plots[id].textElem, {transform: scaleStr}, animDuration); + } + + // Set base transform value + self.plots[id].options.attrs.transform = self.plots[id].mapElem.transformWithoutZoomScaling + scaleStr; + + // Update Hover options + self.setHoverOptions(self.plots[id].mapElem, self.plots[id].options.attrs, self.plots[id].options.attrsHover); + + // Apply transform + self.animate(self.plots[id].mapElem, {transform: self.plots[id].options.attrs.transform}, animDuration); }); }, @@ -1360,6 +1452,8 @@ * @param plot object plot element */ setPlotAttributes: function(plot) { + var self = this; + if (plot.options.type === "square") { plot.options.attrs.width = plot.options.size; plot.options.attrs.height = plot.options.size; @@ -1386,12 +1480,21 @@ // The base transform will resize the SVG path to the one specified by width/height // and also move the path to the actual coordinates - plot.mapElem.baseTransform = "m" + (plot.options.width / plot.mapElem.originalBBox.width) + ",0,0," + - (plot.options.height / plot.mapElem.originalBBox.height) + "," + - (plot.coords.x - plot.options.width / 2) + "," + - (plot.coords.y - plot.options.height / 2); + var baseTransform = "m" + (plot.options.width / plot.mapElem.originalBBox.width) + ",0,0," + + (plot.options.height / plot.mapElem.originalBBox.height) + "," + + (plot.coords.x - plot.options.width / 2) + "," + + (plot.coords.y - plot.options.height / 2); + + // Handle plot scaling + if (self.options.map.zoom.scalePlots === true && self.zoomData.zoomLevel > 1 && plot.id) { + plot.mapElem.transformWithoutZoomScaling = baseTransform + plot.options.attrs.transform; + if (plot.textElem) { + plot.textElem.transformWithoutZoomScaling = plot.options.text.attrs.transform; + } + baseTransform += self.getPlotScalingTransform(plot.id); + } - plot.options.attrs.transform = plot.mapElem.baseTransform + plot.options.attrs.transform; + plot.options.attrs.transform = baseTransform + plot.options.attrs.transform; } else { // Default : circle plot.options.attrs.x = plot.coords.x; @@ -2522,6 +2625,15 @@ var self = this; // Check element if (!element) return; + // We will keep + var oldStrokeWidth; + // Check if scalePlots option is set, if we are zoomed in and a stroke width is defined + // This is needed because Raphael does not scale the stroke-width when applying a transform + if (self.options.map.zoom.scalePlots && self.zoomData.zoomLevel > 0 && attrs['stroke-width'] !== undefined) { + // Element is scaled, apply it to stroke width + oldStrokeWidth = attrs['stroke-width']; + attrs['stroke-width'] *= self.zoomData.scaling; + } if (duration > 0) { // Filter out non-animated attributes // Note: we don't need to delete from original attribute (they won't be set anyway) @@ -2536,11 +2648,15 @@ element.attr(attrsNonAnimated); // Start animation for all attributes element.animate(attrs, duration, 'linear', function() { + // Restore old stroke-width + if (oldStrokeWidth) attrs['stroke-width'] = oldStrokeWidth; if (callback) callback(); }); } else { // No animation: simply set all attributes... element.attr(attrs); + // Restore old stroke-width + if (oldStrokeWidth) attrs['stroke-width'] = oldStrokeWidth; // ... and call the callback if needed if (callback) callback(); } @@ -2659,6 +2775,7 @@ touch: true, animDuration: 200, animEasing: "linear", + scalePlots: false, buttons: { "reset": { cssClass: "zoomButton zoomReset", From 1c7d9422f4b0546f1104cc3ef8ef3a5df36aaee7 Mon Sep 17 00:00:00 2001 From: Indigo744 Date: Thu, 2 Nov 2017 22:36:59 +0100 Subject: [PATCH 2/3] Add examples --- examples/advanced/transformations_on_svg_plots.html | 7 ++++--- examples/advanced/zoom_event_on_specific_area.html | 3 ++- examples/basic/zoom_features.html | 10 ++++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/examples/advanced/transformations_on_svg_plots.html b/examples/advanced/transformations_on_svg_plots.html index 9c7e919..68fef72 100644 --- a/examples/advanced/transformations_on_svg_plots.html +++ b/examples/advanced/transformations_on_svg_plots.html @@ -100,7 +100,8 @@ name: "usa_states" , zoom: { enabled: true, - maxLevel: 20 + maxLevel: 20, + scalePlots: true } , defaultArea: { attrs: { @@ -202,7 +203,7 @@ var deletedPlots = ["paris", "lyon"]; $(".mapcontainer").trigger('update', [{ - mapOptions: {map: {defaultPlot:{attrs:{transform:'r55'}}}}, + mapOptions: {map: {defaultPlot: {attrs: {transform: 'r55'}}}}, animDuration: 1000 }]); }); @@ -217,7 +218,7 @@

Map with some transformations performed on SVG plotted points

- +
Alternative content for the map diff --git a/examples/advanced/zoom_event_on_specific_area.html b/examples/advanced/zoom_event_on_specific_area.html index 7a2498e..3178dd3 100644 --- a/examples/advanced/zoom_event_on_specific_area.html +++ b/examples/advanced/zoom_event_on_specific_area.html @@ -102,7 +102,8 @@ name: "france_departments", zoom: { enabled: true, - maxLevel: 25 + maxLevel: 25, + scalePlots: true }, defaultPlot: { attrs: { diff --git a/examples/basic/zoom_features.html b/examples/basic/zoom_features.html index 0068332..f756230 100644 --- a/examples/basic/zoom_features.html +++ b/examples/basic/zoom_features.html @@ -100,7 +100,8 @@ // Enable zoom on the map , zoom: { enabled: true, - maxLevel: 10 + maxLevel: 10, + scalePlots: true } // Set default plots and areas style , defaultPlot: { @@ -166,10 +167,11 @@ latitude: 48.86, longitude: 2.3444, attrs: { - opacity: 1 + opacity: 1, + transform: "s0.75" }, attrsHover: { - transform: "s1.5" + transform: "...s1.5" } }, // SVG plot @@ -258,4 +260,4 @@

Map with zoom-in, zoom-out buttons and zoom on mousewheel

All example for jQuery Mapael are available here.

- \ No newline at end of file + From 9a87bdb2be5f938c0fa76bc8adde980eeb2d8cc9 Mon Sep 17 00:00:00 2001 From: Indigo744 Date: Sat, 11 Nov 2017 23:26:34 +0100 Subject: [PATCH 3/3] Fix update issue on zoom level 1 --- js/jquery.mapael.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/js/jquery.mapael.js b/js/jquery.mapael.js index f43e86f..e28a9f3 100644 --- a/js/jquery.mapael.js +++ b/js/jquery.mapael.js @@ -1486,7 +1486,8 @@ (plot.coords.y - plot.options.height / 2); // Handle plot scaling - if (self.options.map.zoom.scalePlots === true && self.zoomData.zoomLevel > 1 && plot.id) { + // Note: plot.id may not be defined (usually at beginning, from initElem) + if (self.options.map.zoom.scalePlots === true && plot.id) { plot.mapElem.transformWithoutZoomScaling = baseTransform + plot.options.attrs.transform; if (plot.textElem) { plot.textElem.transformWithoutZoomScaling = plot.options.text.attrs.transform;