Отображение более 100 маркеров в angularjs google maps с вращением - PullRequest
0 голосов
/ 30 июня 2018

Я использовал ngMap с моим кодом angularjs для отображения маркеров. Тем не менее, с более чем 100 маркерами я заметил, что наблюдается значительное снижение производительности, в основном связанное с ng-repeat и двухсторонним связыванием. Я хотел бы добавить маркеры с пользовательскими элементами HTML, похожими на CustomMarker, но используя обычные маркеры и измененные из контроллера при необходимости.

Проблемы, с которыми сталкиваются:

  1. У меня есть изображения SVG, которые должны быть динамически окрашены в зависимости от условий (эти SVG не являются однопутными, поэтому, кажется, не очень хорошо работают, когда я использовал их с Symbol)
  2. Это маркеры транспортных средств и, следовательно, должны поддерживать вращение

1 Ответ

0 голосов
/ 03 июля 2018

Я решил эту проблему, создав CustomMarker с наложением, а затем добавив на карту маркеры, которые присутствуют только в границах текущей карты, чтобы карта не отставала.

Ниже приведен фрагмент кода, с помощью которого я его достиг.

createCustomMarkerComponent();

/**
 * options  : [Object]  : options to be passed on
 *                                          -   position    : [Object]  : Google maps latLng object
 *                                          -   map             : [Object]  : Google maps instance
 *                                          -   markerId    : [String]  : Marker id
 *                                          - innerHTML : [String]  : innerHTML string for the marker
 **/
function CustomMarker(options) {
    var self = this;

    self.options = options || {};

    self.el = document.createElement('div');
    self.el.style.display = 'block';
    self.el.style.visibility = 'hidden';

    self.visible = true;
    self.display = false;

    for (var key in options) {
        self[key] = options[key];
    }

    self.setContent();

    google.maps.event.addListener(self.options.map, "idle", function (event) {
        //This is the current user-viewable region of the map
        var bounds = self.options.map.getBounds();
        checkElementVisibility(self, bounds);
    });

    if (this.options.onClick) {
        google.maps.event.addDomListener(this.el, "click", this.options.onClick);
    }

}

function checkElementVisibility(item, bounds) {
    //checks if marker is within viewport and displays the marker accordingly - triggered by google.maps.event "idle" on the map Object
    if (bounds.contains(item.position)) {
        //If the item isn't already being displayed
        if (item.display != true) {
            item.display = true;
            item.setMap(item.options.map);
        }
    } else {
        item.display = false;
        item.setMap(null);
    }
}

var supportedTransform = (function getSupportedTransform() {
    var prefixes = 'transform WebkitTransform MozTransform OTransform msTransform'.split(' ');
    var div = document.createElement('div');
    for (var i = 0; i < prefixes.length; i++) {
        if (div && div.style[prefixes[i]] !== undefined) {
            return prefixes[i];
        }
    }
    return false;
})();


function createCustomMarkerComponent() {

    if (window.google) {

        CustomMarker.prototype = new google.maps.OverlayView();

        CustomMarker.prototype.setContent = function () {
            this.el.innerHTML = this.innerHTML;
            this.el.style.position = 'absolute';
            this.el.style.cursor = 'pointer';
            this.el.style.top = 0;
            this.el.style.left = 0;
        };

        CustomMarker.prototype.getPosition = function () {
            return this.position;
        };

        CustomMarker.prototype.getDraggable = function () {
            return this.draggable;
        };

        CustomMarker.prototype.setDraggable = function (draggable) {
            this.draggable = draggable;
        };

        CustomMarker.prototype.setPosition = function (position) {
            var self = this;
            return new Promise(function () {
                position && (self.position = position); /* jshint ignore:line */
                if (self.getProjection() && typeof self.position.lng == 'function') {
                    var setPosition = function () {
                        if (!self.getProjection()) {
                            return;
                        }
                        var posPixel = self.getProjection().fromLatLngToDivPixel(self.position);
                        var x = Math.round(posPixel.x - (self.el.offsetWidth / 2));
                        var y = Math.round(posPixel.y - self.el.offsetHeight + 10); // 10px for anchor; 18px for label if not position-absolute
                        if (supportedTransform) {
                            self.el.style[supportedTransform] = "translate(" + x + "px, " + y + "px)";
                        } else {
                            self.el.style.left = x + "px";
                            self.el.style.top = y + "px";
                        }
                        self.el.style.visibility = "visible";
                    };
                    if (self.el.offsetWidth && self.el.offsetHeight) {
                        setPosition();
                    } else {
                        //delayed left/top calculation when width/height are not set instantly
                        setTimeout(setPosition, 300);
                    }
                }
            });
        };

        CustomMarker.prototype.setZIndex = function (zIndex) {
            if (zIndex === undefined) return;
            (this.zIndex !== zIndex) && (this.zIndex = zIndex); /* jshint ignore:line */
            (this.el.style.zIndex !== this.zIndex) && (this.el.style.zIndex = this.zIndex);
        };

        CustomMarker.prototype.getVisible = function () {
            return this.visible;
        };

        CustomMarker.prototype.setVisible = function (visible) {
            if (this.el.style.display === 'none' && visible) {
                this.el.style.display = 'block';
            } else if (this.el.style.display !== 'none' && !visible) {
                this.el.style.display = 'none';
            }
            this.visible = visible;
        };

        CustomMarker.prototype.addClass = function (className) {
            var classNames = this.el.className.trim().split(' ');
            (classNames.indexOf(className) == -1) && classNames.push(className); /* jshint ignore:line */
            this.el.className = classNames.join(' ');
        };

        CustomMarker.prototype.removeClass = function (className) {
            var classNames = this.el.className.split(' ');
            var index = classNames.indexOf(className);
            (index > -1) && classNames.splice(index, 1); /* jshint ignore:line */
            this.el.className = classNames.join(' ');
        };

        CustomMarker.prototype.onAdd = function () {
            this.getPanes().overlayMouseTarget.appendChild(this.el);
            // this.getPanes().markerLayer.appendChild(label-div); // ??

        };

        CustomMarker.prototype.draw = function () {
            this.setPosition();
            this.setZIndex(this.zIndex);
            this.setVisible(this.visible);
        };

        CustomMarker.prototype.onRemove = function () {
            this.el.parentNode.removeChild(this.el);
            // this.el = null;
        };

    } else {
        setTimeout(createCustomMarkerComponent, 200);
    }

}

Функция checkElementVisibility помогает определить, должен ли отображаться маркер.

Если есть лучшие решения, добавьте их сюда. Спасибо!

...