SVG интерактивная карта плана помещения с маршрутом
Есть два svg плана здания: 1й этаж и 2й этаж. На каждом этаже некоторое кол-во офисов и точка "вы находитесь тут" (как на плане эвакуации).
Задача - на сайте при клике по названию / номеру офиса проложить маршрут из точки "вы находитесь тут" до выбранного офиса.
Как это можно реализовать, при условии что маршрут может быть с первого этажа на второй и обратно (то есть когда маршрут дошел до лестницы, то первый план должен исчезнуть и появится второй). ???
Пошерстив гугл я понял, что можно в редакторе нарисовать линии безье (маршруты до офисов) и вставить их в path svg, а далее анимировать, но я не могу понять как отловить анимацию при переходе между этажами ну и собственно сам переход.
Буду рад подсказке по реализации или маленькому примеру.
Ответы (3 шт):
svg -- это представление. Программу поиска я бы писал по упрощенным отдельным данным (варианты):
- 3-мерный массив
- граф А уже потом превращал данные ответа в svg
Это имеет смысл, если прокладывать путь между двумя произвольными точками из многих.
Если стартовых/конечных точек всего 2, а соответственно и возможнух путей-решений не много -- можно нарисовать пути заранее вручную.
Решение для одного этажа
Допустим у нас есть растровая картинка плана этажа.
Для того, чтобы нарисовать маршруты, загрузим её в векторный редактор и с помощью инструмента Рисовать кривые Безье (на рисунке обозначена красной стрелкой 1)
создадим path (указаны стрелками 2) маршруты движения.
Сохраним файл и скопируем path`
Далее вычисляем длину траекторий движения с помощью метода JS getTotalLength()
В моем примере она получилась 761px
Пишем команду анимации path для каждой трассы движения
<animate id="an1" attributeName="stroke-dasharray"
begin="start1.click" dur="1.5s" values="0,761; 761,0" fill="freeze" restart="whenNotActive" />
где start1 это id красного эллипса, обозначающего место нахождения
Анимация начнется после клика по красным эллипсам
#trace1 {
fill:none;
stroke:crimson;
stroke-width:2;
stroke-dasharray:0,761;
}
#trace2 {
fill:none;
stroke:#0000ef;
stroke-width:2;
stroke-dasharray:0,761;
}
#trace3 {
fill:none;
stroke:#19a61b;
stroke-width:2;
stroke-dasharray:0,761;
}
.s0{
fill:#f00800;
stroke-width:2;
stroke:#19a6eb;
}
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
width="900" height="900" viewBox="0 135 770 770" preserveAspectRatio="xMinYMin meet">
<!-- Растровая картика плана помещения -->
<image xlink:href="https://i.stack.imgur.com/dinW1.png" width="100%" height="100%"/>
<path id="trace1" d="m508.8 276.2c0 0 98.2-15.1 105.9 20 11.1 50.6-45.5 96.1-75.9 130.2-26.8 30.1-83.9-13-120.9 2.9-53.3 22.8-65.9 113.4-123.1 123.1-29.2 5-50.5-38-80.1-38.6-30.9-0.7-85.2 36.5-85.2 36.5">
<!-- Анимация красной трассы движения -->
<animate id="an1" attributeName="stroke-dasharray" begin="start1.click" dur="4s" values="0,761; 761,0" fill="freeze" restart="whenNotActive" />
</path>
<path id="trace2" d="m388.6 218.3c0 0 40.4 14 42.2 31.5 1.3 12.6-24.9 15.9-25 28.6-0.2 18.1 31.1 23.8 35.1 41.5 6.5 28.9-9.2 59.6-22.9 85.9-21 40.4-51.6 77.2-88 104.5-26.1 19.5-57.2 43.7-89.5 39.4-21.3-2.9-28.6-39.9-50.1-40.8-24.5-1-60.8 41.5-60.8 41.5v0" >
<!-- Анимация синей трассы движения -->
<animate id="an2" attributeName="stroke-dasharray" begin="start2.click" dur="4s" values="0,761; 761,0" fill="freeze" restart="whenNotActive" />
</path>
<path id="trace3" d="m617.6 503.1c0 0 11.1-54.2-5.7-70.8-44.7-44.3-101.8-6.5-188.2-13.6-52.9-4.4-48.6 102.9-96.6 123.8-28.3 12.4-63.5 3.2-92.3-7.9-18.4-7.1-27.5-36.6-47.2-35.8-25.8 1-58 51.5-58 51.5" >
<!-- Анимация зелёной трассы движения -->
<animate id="an3" attributeName="stroke-dasharray" begin="start3.click" dur="3s" values="0,761; 761,0" fill="freeze" restart="whenNotActive" />
</path>
<!-- Место старта красной трассы -->
<ellipse id="start1" cx="513.8" cy="277.7" rx="6.4" ry="5.7" class="s0"/>
<!-- Место старта синей трассы -->
<ellipse id="start2" ry="5.7" rx="6.4" cy="218.3" cx="390.7" class="s0"/>
<!-- Место старта зелёной трассы -->
<ellipse id="start3" ry="5.7" rx="6.4" cy="500.2" cx="618.3" class="s0"/>
</svg>
Вариант с анимированными фигурками
Смотрите комментарии в коде, надеюсь они помогут понять основные моменты
Анимация каждого маршрута начинается после клика по красным кругам местонахождения
#trace1 {
fill:none;
stroke:crimson;
stroke-width:2;
stroke-dasharray:0,761;
}
#trace2 {
fill:none;
stroke:#0000ef;
stroke-width:2;
stroke-dasharray:0,761;
}
#trace3 {
fill:none;
stroke:#19a61b;
stroke-width:2;
stroke-dasharray:0,761;
}
.s0{
fill:#f00800;
stroke-width:2;
stroke:#19a6eb;
}
<svg id="svg1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1"
width="900" height="900" viewBox="0 135 770 770" preserveAspectRatio="xMinYMin meet">
<defs>
<!-- Фигурка человека с анимацией ног и рук -->
<g id="Man" transform="translate(0,0) scale(1,-1)">
<path fill="none">
<animate
attributeName="d"
begin="0.1s"
dur="0.3s"
repeatCount="indefinite"
values="M-3,0 0,10 3,0 M0,10 0,16 l 4,-5 M0,16 l-4,-5 M0,16 c4,4 -4,4 0,0;
M 0,0 0,10 0,0 M0,10 0,16 l 0,-5 M0,16 l 0,-5 M0,16 c4,4 -4,4 0,0;
M-3,0 0,10 3,0 M0,10 0,16 l 4,-5 M0,16 l-4,-5 M0,16 c4,4 -4,4 0,0"/>
</path>
</g>
</defs>
<!-- Растровая картика плана помещения -->
<image xlink:href="https://i.stack.imgur.com/dinW1.png" width="100%" height="100%"/>
<path id="trace1" d="m508.8 276.2c0 0 98.2-15.1 105.9 20 11.1 50.6-45.5 96.1-75.9 130.2-26.8 30.1-83.9-13-120.9 2.9-53.3 22.8-65.9 113.4-123.1 123.1-29.2 5-50.5-38-80.1-38.6-30.9-0.7-85.2 36.5-85.2 36.5">
<!-- Анимация красной трассы движения -->
<animate id="an1" attributeName="stroke-dasharray" begin="start1.click" dur="1.5s" values="0,761; 761,0" fill="freeze" restart="whenNotActive" />
</path>
<path id="trace2" d="m388.6 218.3c0 0 40.4 14 42.2 31.5 1.3 12.6-24.9 15.9-25 28.6-0.2 18.1 31.1 23.8 35.1 41.5 6.5 28.9-9.2 59.6-22.9 85.9-21 40.4-51.6 77.2-88 104.5-26.1 19.5-57.2 43.7-89.5 39.4-21.3-2.9-28.6-39.9-50.1-40.8-24.5-1-60.8 41.5-60.8 41.5v0" >
<!-- Анимация синей трассы движения -->
<animate id="an2" attributeName="stroke-dasharray" begin="start2.click" dur="1.5s" values="0,761; 761,0" fill="freeze" restart="whenNotActive" />
</path>
<path id="trace3" d="m617.6 503.1c0 0 11.1-54.2-5.7-70.8-44.7-44.3-101.8-6.5-188.2-13.6-52.9-4.4-48.6 102.9-96.6 123.8-28.3 12.4-63.5 3.2-92.3-7.9-18.4-7.1-27.5-36.6-47.2-35.8-25.8 1-58 51.5-58 51.5" >
<!-- Анимация зелёной трассы движения -->
<animate id="an3" attributeName="stroke-dasharray" begin="start3.click" dur="1.5s" values="0,761; 761,0" fill="freeze" restart="whenNotActive" />
</path>
<!-- Анимация движения человечка по красной трассе -->
<use xlink:href="#Man" transform="translate(0,0) scale(1.4)" style="stroke:black; fill:black;">
<animateMotion id="Man_an1"
begin="an1.end"
dur="9s"
repeatCount="1"
restart="whenNotActive" >
<mpath xlink:href="#trace1"/>
</animateMotion>
</use>
<!-- Анимация движения человечка по синей трассе -->
<use xlink:href="#Man" transform="translate(0,0) scale(1.4)" style="stroke:black; fill:black;">
<animateMotion id="Man_an2"
begin="an2.end"
dur="9s"
repeatCount="1"
restart="whenNotActive" >
<mpath xlink:href="#trace2"/>
</animateMotion>
</use>
<!-- Анимация движения человечка по зелёной трассе -->
<use xlink:href="#Man" transform="translate(0,0) scale(1.4)" style="stroke:black; fill:black;">
<animateMotion id="Man_an3"
begin="an3.end"
dur="9s"
repeatCount="1"
restart="whenNotActive" >
<mpath xlink:href="#trace3"/>
</animateMotion>
</use>
<!-- Место старта красной трассы -->
<ellipse id="start1" cx="513.8" cy="277.7" rx="6.4" ry="5.7" class="s0"/>
<!-- Место старта синей трассы -->
<ellipse id="start2" ry="5.7" rx="6.4" cy="218.3" cx="390.7" class="s0"/>
<!-- Место старта зелёной трассы -->
<ellipse id="start3" ry="5.7" rx="6.4" cy="500.2" cx="618.3" class="s0"/>
</svg>
