Подтвердить что ты не робот

Как я могу накладывать SVG-диаграммы на Google Maps?

Я хотел бы добавить оверлейное изображение на карте Google. Изображение - это SVG файл, который я сгенерировал (Python с SVGFig).

Я использую следующий код:

if (GBrowserIsCompatible()) {
    var map = new GMap2(document.getElementById("map_canvas"));
    map.setCenter(new GLatLng(48.8, 2.4), 12);

    // ground overlay
    var boundaries = new GLatLngBounds(new GLatLng(48.283188032632829, 1.9675270369830129), new GLatLng(49.187215000000002, 2.7771877478303999));
    var oldmap = new GGroundOverlay("test.svg", boundaries);
    map.addControl(new GSmallMapControl());
    map.addControl(new GMapTypeControl());
    map.addOverlay(oldmap);
}

Удивительно, но он работает с Safari 4, но он не работает с Firefox (с Safari 3, фон не прозрачен).

Есть ли у кого-нибудь идея о том, как я могу наложить SVG?

PS1: Я прочитал некоторые работы, такие как этот или исходный код swa.ethz.ch/googlemaps, но кажется, что они должны используйте JavaScript-код для синтаксического анализа SVG и добавьте по одному все элементы (но я не понял всех источников...).

PS2: SVG состоит из разных заполненных дорожек и кругов с прозрачностью. Если нет решения для наложения моего SVG, я могу использовать 2 альтернативных решения:

  • растрировать SVG
  • преобразовать пути и круги в GPolygons

Но мне не очень нравится первое решение из-за низкого качества растрового изображения и времени его создания с помощью сглаживания.

И для второго решения дуги, эллипсы и круги должны быть разложены на небольшие полилинии. Многие из них будут необходимы для хорошего результата. Но у меня есть около 3000 дуг и кругов, чтобы...

4b9b3361

Ответ 1

Вот некоторые новости (я надеюсь, что лучше разместить их здесь в ответе, вместо того, чтобы редактировать мои вопросы или создать новый вопрос. Пожалуйста, не стесняйтесь переместить его, если необходимо, или сказать мне, чтобы я мог исправить):

Моя проблема заключалась в следующем:

var oldmap = new GGroundOverlay("test.svg", boundaries);
map.addOverlay(oldmap);

не работал в Safari 3, Firefox и Opera (IE не позволяет рисовать SVG).

Фактически, этот код создает вставку (в <div>) следующего элемента

<img src="test.svg" style=".....">

И Safari 4 может нарисовать SVG файл в качестве изображения, но это не способ сделать для другого браузера. Поэтому идея состоит в создании пользовательского наложения для SVG, как объясняется здесь.

Вот почему я попросил этот вопрос (извините, но HTML/javascript не мои самые сильные стороны).

И поскольку есть небольшая ошибка с Webkit для рендеринга SVG с прозрачным фоном с элементом <object>, мне нужно использовать <object> или <img> в соответствии с браузером (мне это не нравится, но... на данный момент это все еще быстрые и грязные эксперименты)

Итак, я начал с этого кода (все еще работает):

// create the object
function myOverlay(SVGurl, bounds)
{
    this.url_ = SVGurl;
    this.bounds_ = bounds;
}

// prototype
myOverlay.prototype = new GOverlay();

// initialize
myOverlay.prototype.initialize = function(map)
{
    // create the div
    var div = document.createElement("div");
    div.style.position = "absolute";
    div.setAttribute('id',"SVGdiv");
    div.setAttribute('width',"900px");
    div.setAttribute('height',"900px");

    // add it with the same z-index as the map
    this.map_ = map;
    this.div_ = div;

    //create new svg root element and set attributes
    var svgRoot;
    if (BrowserDetect.browser=='Safari')
    {
        // Bug in webkit: with <objec> element, Safari put a white background... :-(
        svgRoot = document.createElement("img");
        svgRoot.setAttribute("id", "SVGelement");
        svgRoot.setAttribute("type", "image/svg+xml");
        svgRoot.setAttribute("style","width:900px;height:900px");
        svgRoot.setAttribute("src", "test.svg");
    }
    else //if (BrowserDetect.browser=='Firefox')
    {
        svgRoot = document.createElement("object");
        svgRoot.setAttribute("id", "SVGelement");
        svgRoot.setAttribute("type", "image/svg+xml");
        svgRoot.setAttribute("style","width:900px;height:900px;");
        svgRoot.setAttribute("data", "test.svg");
    }


    div.appendChild(svgRoot);
    map.getPane(G_MAP_MAP_PANE).appendChild(div);

    //this.redraw(true);
} 

...

Функция draw еще не записана.

У меня все еще есть проблема (я прогрессирую медленно, благодаря тому, что я читаю/учил везде, а также благодаря людям, которые отвечают на мои вопросы).

Теперь проблема следующая: с тегом <object> карта не перетаскивается. Во всем элементе <object> указатель мыши не является "значком руки" для перетаскивания карты, а просто нормальным указателем.

И я не нашел, как исправить это. Должен ли я добавить новое событие мыши (я только что увидел событие мыши при щелчке или добавлении двойного щелчка, но не для перетаскивания карты...)?

Или есть ли другой способ добавить этот слой, чтобы сохранить возможность перетаскивания?

Спасибо за ваши комментарии и ответы.

PS: Я также пытаюсь добавить один за другим элементы моего SVG, но... на самом деле... Я не знаю, как их добавить в дерево DOM. В этот пример, SVG считывается и анализируется с помощью GXml.parse(), и получают все элементы с заданным именем тега (xml.documentElement.getElementsByTagName) и добавлен в SVG node (svgNode.appendChild(node)). Но в моем случае мне нужно добавить непосредственно дерево SVG/XML (добавить все его элементы), и есть разные теги (<defs>, <g>, <circle>, <path> и т.д.). Это может быть проще, но я не знаю, как это сделать..: (

Ответ 2

Я провожу последний вечер по этой проблеме, и я наконец нашел решение своей проблемы.

Это было не так сложно.

Идея заключается в том, что, как сказал Крис Б., загрузить файл SVG с помощью GDownloadUrl, проанализировать его с помощью GXml.parse() и добавить в дерево DOM все элементы SVG, которые мне нужны

Чтобы упростить, я предположил, что все элементы SVG были помещены в большую группу под названием "mainGroup". Я также предположил, что некоторые элементы могут быть в файле.

Итак, вот библиотека, основанная на Google Custom Custom Overlays:

// create the object
function overlaySVG( svgUrl, bounds)
{
    this.svgUrl_ = svgUrl;
    this.bounds_ = bounds;
}


// prototype
overlaySVG.prototype = new GOverlay();


// initialize
overlaySVG.prototype.initialize = function( map)
{
    //create new div node 
    var svgDiv = document.createElement("div");
    svgDiv.setAttribute( "id", "svgDivison");
    //svgDiv.setAttribute( "style", "position:absolute");
    svgDiv.style.position = "absolute";
    svgDiv.style.top = 0;
    svgDiv.style.left = 0;
    svgDiv.style.height = 0;
    svgDiv.style.width = 0;
    map.getPane(G_MAP_MAP_PANE).appendChild(svgDiv);

    // create new svg element and set attributes
    var svgRoot = document.createElementNS( "http://www.w3.org/2000/svg", "svg");
    svgRoot.setAttribute( "id", "svgRoot");
    svgRoot.setAttribute( "width", "100%");
    svgRoot.setAttribute( "height","100%");
    svgDiv.appendChild( svgRoot);

    // load the SVG file
    GDownloadUrl( this.svgUrl_, function( data, responseCode)
    {
        var xml = GXml.parse(data);
        // specify the svg attributes
        svgRoot.setAttribute("viewBox", xml.documentElement.getAttribute("viewBox"));
        // append the defs
        var def = xml.documentElement.getElementsByTagName("defs");
        //for( var int=0; i<def.length; i++)
            svgRoot.appendChild(def[0].cloneNode(true));
        //append the main group
        var nodes = xml.documentElement.getElementsByTagName("g");
        for (var i = 0; i < nodes.length; i++)
            if (nodes[i].id=="mainGroup")
                svgRoot.appendChild(nodes[i].cloneNode(true));
    });

    // keep interesting datas
    this.svgDiv_ = svgDiv;
    this.map_ = map;

    // set position and zoom
    this.redraw(true);
}



// remove from the map pane
overlaySVG.prototype.remove = function()
{
    this.div_.parentNode.removeChild( this.div_);
}


// Copy our data to a new overlaySVG...
overlaySVG.prototype.copy = function()
{
    return new overlaySVG( this.url_, this.bounds_, this.center_);
}


// Redraw based on the current projection and zoom level...
overlaySVG.prototype.redraw = function( force)
{
    // We only need to redraw if the coordinate system has changed
    if (!force) return;
    // get the position in pixels of the bound
    posNE = map.fromLatLngToDivPixel(this.bounds_.getNorthEast());      
    posSW = map.fromLatLngToDivPixel(this.bounds_.getSouthWest());
    // compute the absolute position (in pixels) of the div ...
    this.svgDiv_.style.left = Math.min(posNE.x,posSW.x) + "px";
    this.svgDiv_.style.top = Math.min(posSW.y,posNE.y) + "px";
    // ... and its size
    this.svgDiv_.style.width = Math.abs(posSW.x - posNE.x) + "px";
    this.svgDiv_.style.height = Math.abs(posSW.y - posNE.y) + "px";
}

И вы можете использовать его со следующим кодом:

if (GBrowserIsCompatible())
{
    //load map
    map = new GMap2(document.getElementById("map"), G_NORMAL_MAP);
    // create overlay   
    var boundaries = new GLatLngBounds( new GLatLng(48.2831, 1.9675), new GLatLng(49.1872, 2.7774));
    map.addOverlay( new overlaySVG( "test.svg", boundaries ));
    //add control and set map center
    map.addControl(new GLargeMapControl());
    map.setCenter(new GLatLng(48.8, 2.4), 12);
}   

Таким образом, вы можете использовать его точно так же, как вы используете функцию GGroundOverlay, за исключением того, что ваш SVG файл должен быть создан с проекцией Меркатора (но если вы примените его на небольшой площади, например, в одном городе или меньше, вы не будете см. разницу).

Это должно работать с Safari, Firefox и Opera. Вы можете попробовать мой небольшой пример здесь

Расскажите мне, что вы думаете об этом.

Ответ 3

Этот вопрос был кратко обсужден в группе API Карт Google. Вот что они сказали:

Я не пробовал, но SVG - это подмножество XML, поэтому вы можете прочитать их с помощью GDownloadUrl() и проанализировать их с помощью GXml.parse(). На некоторых неуклюжих веб-серверах вам может потребоваться изменить файл расширение для XML.

Затем вам нужно просканировать через XML DOM, написание SVG, который вы найдете с document.createElementNS() и .setAttribute() вызывает...

Есть также некоторые примеры SVG для Google Maps здесь и здесь.

Удачи!