Клуб API Карт

map.margin.Accessor.setArea не меняет отступы

Пост в архиве.

Собственно говоря, сабж. Использую апи (упрощенно) таким образом:

let map = new ymaps.Map('map', {
    center: [55.751574, 37.573856],
    zoom: 10,
    controls: ['zoomControl']
}, {
    searchControlProvider: 'yandex#search'
});
let defaultMargins = {
    search: {
        top: 0,
        left: 0,
        width: "100px",
        height: "50px"
    },
    layers: {
        top: 0,
        left: 0,
        width: "380px",
        height: "100%",
    },
    points: {
        top: 0,
        right: 0,
        width: "380px",
        height: "100%",
    }
};
let margins = {};
let setMargins = function (panelStates) {
    "use strict";
    let newMargins = Object.assign({}, defaultMargins);
    switch (panelStates.layers) {
        case 'open':
            break;
        case 'minimized':
            newMargins.layers.height = "120px";
            break;
        case 'closed':
            newMargins.layers.height = "1%";
            break;
    }
    switch (panelStates.points) {
        case 'open':
            break;
        case 'minimized':
            newMargins.points.height = "120px";
            break;
        case 'closed':
            newMargins.points.height = "1%";
            break;
    }
    Object.keys(defaultMargins).forEach((key) => {
        if (!margins[key]) {
            margins[key] = map.margin.addArea(newMargins[key]);
        } else {
            margins[key] = margins[key].setArea(newMargins[key]);
        }
    });
};
setMargins({
    layers: "open",
    points: "open",
});
let objectManager = new ymaps.ObjectManager({
    clusterize: true,
});
let points = [
    ...
];
let collection = {
    "type": "FeatureCollection",
    "features": points.map((point) => ({
        "type": "Feature",
        "id": point.point_id,
        "geometry": {
            "type": "Point",
            "coordinates": [Number(point.lat), Number(point.lon)]
        },
    })),
};
objectManager.add(collection);
map.geoObjects.add(objectManager);

setMargins({
    layers: "closed",
    points: "open",
});

После исполнения этого кода отступы должны измениться, но этого не происходит, getMargin возвращает одинаковые значения до и после исполнения последнего setMargins. Вопрос знатокам: это я дурак, или лыжи не едут?

4 комментария
jsfiddle: https://jsfiddle.net/r4waLm7y/4/
Username,
В map.margin.Accessor сохраняется ссылка на тот объект (screenArea), что вы передаете. Также в коде метода setArea есть проверка, что если поля сохраненного объекта и новой screenArea совпадают – то менять ее не надо.


Меняя внутреннее состояние объекта (поле width объекта), и передавая его заного, вы также меняете сохраненный объект по ссылке и проверка говорит, что объект не изменился.


Я НЕ разработчик АПИ и ответить кто именно тут дурак – вы или лыжи затрудняюсь, однако в своем коде я стараюсь избегать подобных ситуаций, используя принцип неизменяемости данных, сформулированный Аланом Кёртисом Кейем и реализованный в одноименной javascript-библиотеке от Facebook



Итого, ожидаемое поведение можно получить передавая новый объект в setArea


    case 'closed':
        newMargins.layers = ymaps.util.extend({}, newMargins.layers, {width: "1%"});
        break;
}
Обновлено 26 июня 2017, 18:14
dimik,
С вашим решением действительно работает как надо, погуглив выяснил, что Object.assign делает глубокую копию только глубиной в единицу, т.е. в моем случае он копировал референсы. Заменил Object.assign на JSON.parse(JSON.stringify(defaultMargins)); и получил желаемый ответ. Спасибо!
... понятно