function map()

in modules/renderer/map.js [114:290]


    function map(selection) {
        _selection = selection;

        context
            .on('change.map', immediateRedraw);

        var osm = context.connection();
        if (osm) {
            osm.on('change.map', immediateRedraw);
        }

        function didUndoOrRedo(targetTransform) {
            var mode = context.mode().id;
            if (mode !== 'browse' && mode !== 'select') return;
            if (targetTransform) {
                map.transformEase(targetTransform);
            }
        }

        context.history()
            .on('merge.map', function() { scheduleRedraw(); })
            .on('change.map', immediateRedraw)
            .on('undone.map', function(stack, fromStack) {
                didUndoOrRedo(fromStack.transform);
            })
            .on('redone.map', function(stack) {
                didUndoOrRedo(stack.transform);
            });

        context.background()
            .on('change.map', immediateRedraw);

        context.features()
            .on('redraw.map', immediateRedraw);

        drawLayers
            .on('change.map', function() {
                context.background().updateImagery();
                immediateRedraw();
            });

        selection
            .on('wheel.map mousewheel.map', function(d3_event) {
                // disable swipe-to-navigate browser pages on trackpad/magic mouse – #5552
                d3_event.preventDefault();
            })
            .call(_zoomerPanner)
            .call(_zoomerPanner.transform, projection.transform())
            .on('dblclick.zoom', null); // override d3-zoom dblclick handling

        map.supersurface = supersurface = selection.append('div')
            .attr('class', 'supersurface')
            .call(utilSetTransform, 0, 0);

        // Need a wrapper div because Opera can't cope with an absolutely positioned
        // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
        wrapper = supersurface
            .append('div')
            .attr('class', 'layer layer-data');

        map.surface = surface = wrapper
            .call(drawLayers)
            .selectAll('.surface');

        surface
            .call(drawLabels.observe)
            .call(_doubleUpHandler)
            .on(_pointerPrefix + 'down.zoom', function(d3_event) {
                _lastPointerEvent = d3_event;
                if (d3_event.button === 2) {
                    d3_event.stopPropagation();
                }
            }, true)
            .on(_pointerPrefix + 'up.zoom', function(d3_event) {
                _lastPointerEvent = d3_event;
                if (resetTransform()) {
                    immediateRedraw();
                }
            })
            .on(_pointerPrefix + 'move.map', function(d3_event) {
                _lastPointerEvent = d3_event;
            })
            .on(_pointerPrefix + 'over.vertices', function(d3_event) {
                if (map.editableDataEnabled() && !_isTransformed) {
                    var hover = d3_event.target.__data__;
                    surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
                    dispatch.call('drawn', this, { full: false });
                }
            })
            .on(_pointerPrefix + 'out.vertices', function(d3_event) {
                if (map.editableDataEnabled() && !_isTransformed) {
                    var hover = d3_event.relatedTarget && d3_event.relatedTarget.__data__;
                    surface.call(drawVertices.drawHover, context.graph(), hover, map.extent());
                    dispatch.call('drawn', this, { full: false });
                }
            });

        var detected = utilDetect();

        // only WebKit supports gesture events
        if ('GestureEvent' in window &&
            // Listening for gesture events on iOS 13.4+ breaks double-tapping,
            // but we only need to do this on desktop Safari anyway. – #7694
            !detected.isMobileWebKit) {

            // Desktop Safari sends gesture events for multitouch trackpad pinches.
            // We can listen for these and translate them into map zooms.
            surface
                .on('gesturestart.surface', function(d3_event) {
                    d3_event.preventDefault();
                    _gestureTransformStart = projection.transform();
                })
                .on('gesturechange.surface', gestureChange);
        }

        // must call after surface init
        updateAreaFill();

        _doubleUpHandler.on('doubleUp.map', function(d3_event, p0) {
            if (!_dblClickZoomEnabled) return;

            // don't zoom if targeting something other than the map itself
            if (typeof d3_event.target.__data__ === 'object' &&
                // or area fills
                !d3_select(d3_event.target).classed('fill')) return;

            var zoomOut = d3_event.shiftKey;

            var t = projection.transform();

            var p1 = t.invert(p0);

            t = t.scale(zoomOut ? 0.5 : 2);

            t.x = p0[0] - p1[0] * t.k;
            t.y = p0[1] - p1[1] * t.k;

            map.transformEase(t);
        });

        context.on('enter.map',  function() {
            if (!map.editableDataEnabled(true /* skip zoom check */)) return;
            if (_isTransformed) return;

            // redraw immediately any objects affected by a change in selectedIDs.
            var graph = context.graph();
            var selectedAndParents = {};
            context.selectedIDs().forEach(function(id) {
                var entity = graph.hasEntity(id);
                if (entity) {
                    selectedAndParents[entity.id] = entity;
                    if (entity.type === 'node') {
                        graph.parentWays(entity).forEach(function(parent) {
                            selectedAndParents[parent.id] = parent;
                        });
                    }
                }
            });
            var data = Object.values(selectedAndParents);
            var filter = function(d) { return d.id in selectedAndParents; };

            data = context.features().filter(data, graph);

            surface
                .call(drawVertices.drawSelected, graph, map.extent())
                .call(drawLines, graph, data, filter)
                .call(drawAreas, graph, data, filter)
                .call(drawMidpoints, graph, data, filter, map.trimmedExtent());

            dispatch.call('drawn', this, { full: false });

            // redraw everything else later
            scheduleRedraw();
        });

        map.dimensions(utilGetDimensions(selection));
    }