Как я могу наложить SVG-диаграммы на Google Maps? - PullRequest
17 голосов
/ 28 июня 2009

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

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

  • Растеризация SVG
  • конвертировать пути и круги в GPolygons

Но мне не очень нравится 1-е решение из-за низкого качества растрового изображения и времени, необходимого для его генерации с сглаживанием.

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

Ответы [ 3 ]

6 голосов
/ 03 июля 2009

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

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

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 (svgNode.appendChild(node)). Но в моем случае мне нужно добавить непосредственно дерево SVG / XML (добавить все его элементы), и есть разные теги (<defs>, <g>, <circle>, <path> и т. Д.). Это может быть проще, но я не знаю, как это сделать ..: (

6 голосов
/ 05 июля 2009

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

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

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

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

Итак, вот библиотека, основанная на пользовательских наложениях Google Maps :

// 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. Вы можете попробовать мой маленький пример здесь

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

2 голосов
/ 29 июня 2009

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

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

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

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

Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...