Search code examples
angularmapael

How to make my Map work in Mapael while using Vite?


I doubt many will see an actual use for this. In part, I did this post for myself, but if it can help at least ONE more person in need, I would certainly be pleased. As many Angular Devs, I've been eager to switch to the newest Angular version and make the switch to Vite. Which also includes moving some older projects as well. But there is always SOMETHING.

enter image description here

Ouch! But why? The project worked nicely before in Webpack. But using the error message for a quick google search, won't help us much. But... let's inspect the map itself.

(function (factory) {
    if (typeof exports === 'object') {
        // CommonJS
        module.exports = factory(require('jquery'), require('jquery-mapael'));
    } else if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery', 'mapael'], factory);
    } else {
        // Browser globals
        factory(jQuery, jQuery.mapael);
    }
}(function ($, Mapael) { // shortened for brevity... 

It's for the most part the default example from the project itself. So, since Vite wants ES6 Module style imports; we can do that.

import jquery from "jquery"
import mapael from "jquery-mapael"

(function (factory) {
        if (typeof exports === 'object') {
            // CommonJS
            module.exports = factory(jquery, mapael);
        } // the other conditions aren't even necessary...

After we did this... let's hope for the best. And—

enter image description here

Nice! The map loads! And it almost feels perfect, but... apparently dependencies like jquery-mousewheel didn't play nice in this configuration. For some reason the mousewheel delta isn't working as expected, and we can only zoom OUT but never in? Ugh! Sure, one could try to fork it, work through the pain of fixing it and dragging this old project into the future, but we can work around the problem. Sometimes we have to be pragmatic. So in our template we add a template variable...

<article id="map">
    <div #map class="map-canvas">
        <div class="map">
            <span></span>
        </div>
        <div class="areaLegend">
            <span></span>
        </div>
    </div>
</article>

So we can access the instance of the map like this

@ViewChild('map') map: any;

The important part is during our initialization... the object zoom should have the mousewheel explicitly disabled, like this:

zoom: {
  enabled: true,
  maxLevel: 10,
  mousewheel: false
},

With this, we avoid that the library somehow messes with our own custom mousewheel handling.

$(this.map.nativeElement).on("mousewheel", (event) => {
  event.preventDefault();
  event.stopPropagation();

  const deltaY = (event.originalEvent as any).deltaY;

  const mapZoomData = $(this.map.nativeElement).data('mapael').zoomData;

  let zoomLevel = mapZoomData.zoomLevel;

  if (deltaY > 0) {
    zoomLevel++
  } else {
    zoomLevel--
  }
  $(this.map.nativeElement).trigger('zoom', { level: zoomLevel, fixedCenter: true });
})

This is an overall rather simplified and naive zooming functionality, but all of that put together and we have a working zoom!


Solution

  • Since I really didn't want to miss out on Angular + Vite Goodness, it was challenging (to me) to figure out the problem and solution to this VERY particular problem.