Вопрос по svg, javascript – Как я могу наложить SVG-диаграммы на Google Maps?

17

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

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

<code>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);
}
</code>

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

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

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

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

увеличить SVG конвертировать пути и круги в GPolygons

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

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

GGroundOverlays не использует фоновые изображения CSS. Просто обычный IMG. Я не знаю, почему они не работают. Chris B
Вы можете (попытаться) увидеть результатВо ThibThib
Может ли быть так, что GGroundOverly использует фоновые изображения CSS? FF не обрабатывает (пока 3.5 будет) SVG как фоны. Boldewyn
Какой отличный вопрос. Мне кажется, что ваш второй подход не сработает, но постараюсь ответить, не подтвердив, как работает gmaps с таким объемом полилиний. Я с нетерпением жду встречи с этим. RedBlueThing
Я только что попробовал с FF 3.5, но он тоже не работает. Фактически, когда я просматриваю загруженный носитель (Инструменты / Информация о странице / Носитель), мой SVG вообще не загружается ... ThibThib

Ваш Ответ

3   ответа
6

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

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

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

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

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

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

And 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);
} 

...

Thedraw функция еще не написана.

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

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

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

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

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

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

2

Google Maps API Group. Вот что они сказали:

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

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

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

Удачи

Ладно, спасибо за ссылку. Да, может быть, я могу загрузить свой файл, разобрать его и вставить один за другим все мои элементы SVG. Я попробую, даже если это решение не убедит меня ... И я уже могу загрузить за один шаг с помощью GGroundOverlay ("test.svg", Границы), но только с Safari 4 ... Я расскажу вам, как это идет ThibThib
6

и наконец нашел решение своей проблемы.

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

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

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

Так вот библиотека, основанная на Google Maps 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. Вы можете попробовать мой маленький примерВо

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

Отличный пример! Joseph Lust

Похожие вопросы