因BWiki近期更新,普通用户无法直接访问除重定向、编辑表格外的特殊页面(如最近更改等),进行3次有效编辑后即可恢复。
全站通知:
地图工具
来自战争雷霆WIKI_BWIKI_哔哩哔哩
跳到导航
跳到搜索
此模板为一键安装导入,不建议手动修改。
简单说明
说明:大地图工具,用于开放世界类型的游戏
说明:本工具属于大型工具,本页面不对源码进行展开,需要二改的可以前往原址自行研究
使用说明
第一步:搬运框架
将如下两个文件导入您的WIKI(特殊:导入页面)
Map3.0Widget.xml
包含如下页面:
<style>
.animate-fast{
transition: all 300ms;
}
#map-wrap #map-menu.toggle-active{z-index:99999}
#map-wrap #map-menu .wiki-logo{
padding: 6px 0;
width: 60%;
}
#map-wrap #map-menu .wiki-logo img{
width: 100%;
}
#map-wrap #map-menu .menu-search-box {
padding: 14px 0px 0 0;
width: 40%;
}
#map-wrap #map-menu .menu-search-box input {
padding: 7px 12px;
width: 100%;
border: 1px solid rgba(0,0,0,0.2);
border-radius: 20px;
text-align: right;
outline: none;
margin-right: -4px;
}
#map-wrap #map-menu .menu-search-box .map-icon.search{
filter: brightness(0.5);
}
#map-wrap #map-menu .menu-btn-group{
display: flex;
text-align: center;
color: rgba(0,0,0,0.85);
font-size: 14px;
border: 1px solid rgba(0,0,0,0.1);
line-height: 18px;
padding: 9px 0;
border-radius: 6px;
width: 100%;
}
#map-wrap #map-menu .menu-btn-group> div{
cursor: pointer;
width: 25%;
border-right: 1px solid rgba(0,0,0,0.1);
}
#map-wrap #map-menu .menu-btn-group> div:hover{
color: rgba(0,0,0,1);
}
#map-wrap #map-menu .menu-btn-group> div:last-child{
border-right: none;
}
#map-wrap #map-menu .menu-tab-nav{
display: flex;
text-align: center;
font-size: 16px;
font-weight: bold;
color: rgba(0,0,0,0.35);
width: 100%;
justify-content: space-around;
}
#map-wrap #map-menu .menu-tab-nav> div{
cursor: pointer;
width: 30%;
padding: 10px;
}
#map-wrap #map-menu .menu-tab-nav> div:hover{
color: rgba(0,0,0,0.55);
}
#map-wrap #map-menu .menu-tab-nav > div.toggle-active{
color: rgba(0,0,0,0.85);
position: relative;
}
#map-wrap #map-menu .menu-tab-nav:after{
content: "";
position: absolute;
display: inline-block;
width: 20px;
border-bottom: 2px solid rgba(0,0,0,0.85);
height: 0;
bottom: -1px;
left: 20%;
margin-left: -10px;
transition: all 300ms;
}
#map-wrap #map-menu .menu-tab-nav.tab-1.tab-index-1:after{ left: 50%; }
#map-wrap #map-menu .menu-tab-nav.tab-2.tab-index-1:after{ left: 27%; }
#map-wrap #map-menu .menu-tab-nav.tab-2.tab-index-2:after{ left: 72%; }
#map-wrap #map-menu .menu-tab-nav.tab-3.tab-index-1:after{ left: 20%; }
#map-wrap #map-menu .menu-tab-nav.tab-3.tab-index-2:after{ left: 50%; }
#map-wrap #map-menu .menu-tab-nav.tab-3.tab-index-3:after{ left: 80%; }
#map-wrap #map-menu .menu-tab-nav.tab-4.tab-index-1:after{ left: 12.5%; }
#map-wrap #map-menu .menu-tab-nav.tab-4.tab-index-2:after{ left: 37.5%; }
#map-wrap #map-menu .menu-tab-nav.tab-4.tab-index-3:after{ left: 62.5%; }
#map-wrap #map-menu .menu-tab-nav.tab-4.tab-index-4:after{ left: 87.5%; }
#map-wrap #mapSetting{
box-shadow: 0 1px 5px rgba(0, 0, 0, 0.65);
border-radius: 6px;
}
#map-wrap .map-setting-btn{
zoom: 0.8;
width: 24px;
height: 24px;
color: #CED3DE;
line-height: 24px;
background: rgba(0, 0, 0, 0.8);
padding: 4px;
white-space: nowrap;
cursor: pointer;
}
#map-wrap .map-setting-btn:first-child{
border-radius: 6px 6px 0 0;
}
#map-wrap .map-setting-btn:last-child{
border-radius: 0 0 6px 6px;
}
#map-wrap .map-setting-btn.toggle-active{
color: white;
background: #98c138;
}
#map-wrap #map {
background-color: #fff !important
}
#map-wrap .mark-wrap {
max-width: none
}
#map-wrap .BMap_bubble_title {
word-wrap: break-word;
word-break: keep-all;
white-space: normal !important
}
#map-wrap .BMap_bubble_content .map-header {
line-height: 20px
}
#map-wrap .BMap_bubble_content .map-header .map-info-id {
display: inline-block;
line-height: 36px
}
#map-wrap .BMap_bubble_content .map-header .map-info-mark {
background: #000;
font-size: 14px;
color: #fff;
text-align: center;
padding: 6px 14px;
float: right
}
#map-wrap .BMap_bubble_content .map-header, #map-wrap .BMap_bubble_content .map-info-des, #map-wrap .BMap_bubble_content .map-info-image-wrap {
margin: 10px 0
}
#map-wrap .BMap_bubble_content .map-info-image-wrap img {
width: 100%
}
#map-wrap .BMap_bubble_content .map-info-footer {
margin-top: 30px
}
#map-wrap .BMap_bubble_content .map-info-footer .map-info-wikilink {
display: inline-block;
border: 1px solid #00b6ff;
font-size: 14px;
color: #00b6ff;
text-align: center;
padding: 8px 44px
}
#map-wrap .BMap_bubble_content .map-info-footer .map-info-videolink {
background: #000;
font-size: 14px;
color: #fff;
text-align: center;
padding: 8px 44px;
float: right
}
#map-wrap .anchorBL, #map-wrap .BMap_cpyCtrl {
display: none
}
#map-wrap .toggle-type {
display: none;
position: absolute;
right: 100px;
top: 20px
}
#map-wrap .toggle-json {
display: none;
position: absolute;
right: 200px;
top: 20px
}
#map-wrap .toggle-id {
display: none;
position: absolute;
right: 300px;
top: 20px
}
#map-wrap .BMap_pop {
margin-top: -40px
}
#map-wrap .map-link, #map-wrap .map-mark {
float: right;
box-sizing: border-box;
display: block;
border-radius: 5px;
margin-right: 10px;
text-align: center;
line-height: 30px;
font-size: 14px;
font-weight: 700;
height: 30px;
margin-top: 10px;
padding: 0 10px;
text-decoration: none;
cursor: pointer;
color: #fff
}
#map-wrap .map-mark {
background-color: #242424
}
#map-wrap .map-link {
background-color: #0069f8
}
#map-wrap #map-menu {
width: 400px;
max-width: calc(100vw - 66px);
position: absolute;
left: -400px;
top: 0;
box-shadow: 0 2px 8px rgba(0, 0, 0, .5);
box-sizing: border-box;
flex-direction: column;
transition: transform .5s;
transform: translate(0%, 0%);
background: white;
z-index: 9999;
padding-top: 150px;
height: 100%;
}
#map-wrap #map-menu .mapMenu {
width: 100%;
height: 150px;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
padding: 0 20px;
border-bottom: 1px solid rgba(0,0,0,0.08);
position: absolute;
top: 0;
align-content: space-between;
justify-content: space-between;
box-sizing: border-box;
}
#map-wrap #map-menu .mapShrink {
width: 48px;
height: 60px;
position: absolute;
right: -48px;
top: 24px;
cursor: pointer;
border-radius: 0 6px 6px 0;
}
#map-wrap #map-menu .mapShrink .shrink-inner {
width: 36px;
height: 48px;
border-radius: 0 6px 6px 0;
color: rgba(206,211,222,1);
background: rgba(0,0,0,0.8);
text-align: center;
}
#map-wrap #map-menu .mapSearch {
margin: 0 20px 10px;
}
#map-wrap #map-menu .mapSearch span {
font-size: 18px;
color: #333;
font-weight: 700
}
#map-wrap #map-menu .markerList {
box-sizing: border-box;
flex: 1;
overflow-x: hidden;
overflow-y: auto;
margin: 0 auto;
padding: 10px ;
height: 100%;
}
#map-wrap *::-webkit-scrollbar {
width: 6px;
background: rgba(225,229,235,1);
}
#map-wrap *::-webkit-scrollbar-thumb {
background: rgba(174,183,201,1);
}
#map-wrap #map-menu .markerList .orderItem {
margin-bottom: 15px;
padding-bottom: 10px;
border-bottom: 1px solid rgba(0,0,0,0.08);
}
#map-wrap #map-menu .markerList .orderItem .order-h5 {
height: 24px;
line-height: 24px;
color: #333;
cursor: pointer;
position: relative;
margin: 0 0 10px;
}
#map-wrap #map-menu .markerList .orderItem .order-h5 span{
font-size: 16px;
color: rgba(0,0,0,0.85);
font-weight: bold;
padding-left: 10px;
}
#map-wrap #map-menu .markerList .orderItem .order-h5 .pcRun {
display: block;
width: 78px;
height: 24px;
line-height: 24px;
position: absolute;
right: 25px;
top: 0;
font-size: 12px;
text-align: center;
color: rgba(152,162,171,1);
}
#map-wrap #map-menu .markerList .orderItem .items-wrap {
display: flex;
flex-wrap: wrap;
font-size: 13px;
}
@media screen and (max-width: 768px) {
#map-wrap #map-menu .markerList .orderItem .items-wrap > div {
font-size: 12px
}
}
#map-wrap #map-menu .markerList .orderItem .items-wrap > div:hover {
background: rgba(242,244,246,0.5);
}
#map-wrap #map-menu .markerList .orderItem .items-wrap > .item-active {
border-radius: 6px;
background: rgba(242,244,246,1);
color: rgba(0,0,0,0.85);
}
#map-wrap #map-menu .markerList .orderItem .items-wrap > div {
display: flex;
justify-content: space-between;
padding: 10px;
width: calc(50% - 4px);
margin: 2px;
align-items: baseline;flex-wrap: wrap;
}
#map-wrap #map-menu .markerList .orderItem .items-wrap .catTit .list-img {
width: 20px;
padding-right: 12px;
margin-top: -3px;
box-sizing: content-box;
}
#map-wrap #map-menu.toggle-active {
transform: translate(100%, 0%);
}
#map-wrap .allHide {
background: url(https://patchwiki.biligame.com/images/ys/f/f5/h3d1ij0241voanqcxcf682gbijlq7ko.png);
}
#map-wrap .allScreen {
background: url(https://patchwiki.biligame.com/images/ys/2/28/qhi5h9t3yqclpmf72vgp708abm41b51.png)
}
#map-wrap .btn-clearStorage {
background: url(https://patchwiki.biligame.com/images/ys/0/0a/guety3byfxw1rjnwtswsbtd4cu2ooa6.png)
}
#map-wrap .logo {
width: 112px !important;
height: 116px !important;
margin: 0px !important;
background: url(https://patchwiki.biligame.com/images/ys/9/90/d8dtw61n8v9xj69x7wj45jxjx6wmdue.png) no-repeat center;
}
@media screen and (max-width: 1200px) {
#map-wrap .logo {
display: none;
}
}
.custom-select {
position: relative;
font-family: Arial;
}
.custom-select select {
display: none;
}
.select-selected {
background: url(https://patchwiki.biligame.com/images/ys/3/39/p9cztxdzn8dknr3ii4ohhf481acvi5z.png);
}
.select-items div, .select-selected {
color: #445566;
font-size: 16px;
font-weight: bold;
text-align: center;
line-height: 32px;
width: 108px;
height: 32px;
cursor: pointer;
user-select: none;
}
.select-items {
position: absolute;
top: 100%;
left: 0;
right: 0;
z-index: 99;
border: #702e00 3px double;
border-radius: 5px;
}
.select-items div {
width: 102px;
}
.select-hide {
display: none;
}
.select-items div:hover, .same-as-selected {
background-color: #8b7449;
color: #fff;
}
/* -- 地图全屏css -- */
/* full screen */
.fs {
object-fit: contain;
position: fixed !important;
top: 0px !important;
right: 0px !important;
bottom: 0px !important;
left: 0px !important;
box-sizing: border-box !important;
min-width: 0px !important;
max-width: 100% !important;
min-height: 0px !important;
max-height: 100% !important;
width: 100% !important;
height: 100% !important;
transform: none !important;
margin: 0px !important;
z-index: 9999999;
}
@media screen and (max-width: 539px) {
#map-wrap #map-menu .markerList .orderItem .items-wrap > .item-active {
background: rgba(237,237,237,1);
}
#map-wrap #map-menu {
left: calc(-100vw + 65px);
}
#map-wrap #map-menu .menu-btn-group {
font-size: 12px;
}
#map-wrap #map-menu .menu-tab-nav {
font-size: 14px;
}
#map-wrap #map-menu .markerList .orderItem .order-h5{margin:4px}
#map-wrap #map-menu .markerList .orderItem .order-h5 span{font-size:14px;}
#map-wrap #map-menu .mapMenu{padding:0 10px;}
#map-wrap #map-menu .markerList .orderItem{padding-bottom:2px}
#map-wrap > .swipe-panel.toggle-active:before {content: "";height: 4px;width: 42px;background: #E1E1E1;position: absolute;top: 6px;left: 50%;margin-left: -21px;border-radius: 50px;}
#map-wrap > .swipe-panel {padding: 18px 14px;box-shadow: 0 -2px 8px rgb(0 0 0 / 50%);box-sizing: border-box;padding-bottom: 120px;}
.swipe-panel{
top: 100%;
}
.swipe-panel.toggle-active {
top: 80%;
}
.leaflet-popup-tip-container{
padding-top: 66px;
box-sizing: border-box;
margin-left:-21px;
}
.leaflet-popup-content-wrapper, .leaflet-popup-close-button{
visibility: hidden;
}
.leaflet-popup.leaflet-zoom-animated {
top: -26px;
margin-left: 1px;
}
.leaflet-popup.leaflet-zoom-animated .leaflet-popup-tip-container {
animation-name: likes;
animation-direction: alternate;
animation-timing-function: linear;
animation-delay: 0s;
animation-iteration-count: infinite;
animation-duration: 1s;
}
@keyframes likes {
0%{
transform: scale(1);
}
25%{
transform: scale(0.9);
}
50%{
transform: scale(0.85);
}
75%{
transform: scale(0.9);
}
100%{
transform: scale(1);
}
}
}
@media screen and (max-width: 320px) {
#map-wrap #map-menu .menu-btn-group {
font-size: 10px;
padding: 5px 0;
}
#map-wrap #map-menu .menu-btn-group .map-icon:first-child{
display:none!important;
}
#map-wrap #map-menu .menu-tab-nav {
font-size: 12px;
}
#map-wrap #map-menu .markerList .orderItem .order-h5 span{font-size:13px;}
}
</style>
<style>
.map-icon{
width: 1.4em;
height: 1.4em;
margin: -0.2em -0.2em 0 -0.4em;
display: inline-block!important;
background-size: contain;
vertical-align: middle;
transition: all 300ms;
}
.map-area-tab .shrink-inner {
border-radius: 0!important;
}
.map-area-tab .shrink-inner:first-child{
border-radius: 0 6px 0 0!important;
}
.map-area-tab .shrink-inner:last-child {
border-radius: 0 0 6px 0!important;
}
.map-area-tab .shrink-inner .map-icon{
background-image:url(https://patchwiki.biligame.com/images/sesbq/b/b0/0w44s0dc5l16jkyhcc96vqq0mkhmoir.png);
background-size: auto 30.4px;
width: 2.2em;
height: 2.2em;
margin-top: 7px;
opacity: 0.6;
}
.map-area-tab .shrink-inner:hover .map-icon {opacity:1}
.map-area-tab .shrink-inner.item-active .map-icon {opacity:1}
.map-icon.world { background-position: -1.2px; }
.map-icon.mengde { background-position: 209.8px; }
.map-icon.liyue { background-position: 383.2px; }
.map-icon.xueshan { background-position: 351.5px; }
.map-icon.daoqi { background-position: 174px; }
.map-icon.h-flip{transform: scaleX(-1);}
.map-icon.v-flip{transform: scaleY(-1);}
.shrink-inner:hover .menu-arrow{color:white}
.map-icon.search{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAACXBIWXMAAAsTAAALEwEAmpwYAAAF6GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjA6NDQ6MzArMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjA6NDQ6MzArMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MmM0ZjUwMDEtMzM3Yi0xMDQxLWExZjQtNTY0Mzk3ZThhYmI3IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjUxRTk4QjBEQzZDNDExRUI4MEU1REE5MzM0ODFEQjU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTFFOThCMERDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUU0QzE1NUM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUU0QzE1NkM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoyYzRmNTAwMS0zMzdiLTEwNDEtYTFmNC01NjQzOTdlOGFiYjciIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDQ6MzArMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz4ywwiXAAAF6UlEQVR42u2a+U9cVRTHKRatW2u1auJexbXWpHGJrbGmNTFajdVEMVrtD9I2UrWttmDnH2LfJwwkbAHCNkDCFiAQwr5DMizDvvR+kneT2xdI6Zv3mIfcH25me+/OPd9zzvd8z70vYmNjI2IvjwgNgAZAA6AB0ABoADQAGgANgAZAA+DoWFtbe2B1dXW/MaJ45bv19fXI/x0Awqh9MzMzTw0PD0d3dXV90NLS8llTU9MZMc42NjZ+LgefW1tbP+Uace3rs7OzT+40ILZOhmfn5uaeGB0dPSoMO11eXv6j1+uNS0pK+i8xMfG2aXh4TU5Ojs/Nzb0qro0BDO4NBoMHiZBdBQDGBwKBZ9rb20/m5eVdSUlJiTcbDRDqMP8uwEjw+XyXxBynmGsnQLAr5CNHRkZeq6ys/D4tLe1fDJEeVoyLz8jIuCG8HccQ769vBQLXVVVVfcecrgeAfO/p6XmvrKzsp8zMzOuqMTk5OX+SBoR2f3//O+S5CPFXCXPei++OyVThWvVeMdc15uzt7T1OdLkSABaGl1hoenr6PzLM8S5GtbW1fcLvkJtg/MjNKoP47TBkybUVFRU/4H0ZGcxZWlr6M6AtLy8fcBUAGD89Pf00YW943kP4Zmdn/1VTU/Mthi8tLT283fm4dmxs7JXq6urzpAgpAwipqak3mW9qaup5AHMNALA9hEfOS89jvN/v/3p+fv4gqWGFS8S9j9fX13/JXCovdHR0fMxvrgCAhRKWsL1BeLcJXbzHIq0Yb9IQRwAB70sQioqKfoNHXAEAC4S8RKm7JRdIzhP2dggZ0mtoaOgN5pSaAT5AOC0sLDwWdgBgcIhPZXtI7H5y/l6DSOrs7PwQww1S9AAIkRd2AJCuEJXJ+9F2h+fExMSLhYWFF2Wa5efnx8IFYQcAba+KGOo85cxuACif9BCSaCmvkGxYAaAUsShV4UFOTpQoUmpgYOBtDJeVhp7BzobJCkHth4xU0QMnOCFS+K/JyckXVIWJMAIYu0CwtChaWQkAXGA3ManlVoitI1lZWX9LAIqLi39Fg4QTgCgTAFedBICSKwC4puoBY99gnysiAAGElncoBaKEBH5OTYGSkpILi4uLj4QNAIMEz6o9Pl2dEySIoWYSRH/Y+V+WwhIVKJsVowyeJiwdLIM3ZYtcV1d3zg1C6H1yXxVCdqcBQI+Pj79Mzksh5PP5LrtCCGGsotMdkcJofhSnIoUBOsbuXSLLoWmkQYIEgc0MqoEd5YkcR1swp5yfzhDusRPkUNvho4SkBAFPsY9n7AWEBEIgEHhW5PpXpnb4IorTLvYPeUMkGAweYveWMigZmlSgj+dMwMqOLp7H+IaGhi8kxzAvvQC5z3+6akuMxeJ12Fn2BezkAAL9PNGw3Ygi5+EWPI/xwvAECYDX6/2D31y1JaZsikaL2hwjN0Xp2wldSJJ+XrS0L9EpkrtEBcYyuJc6D5/A9hAeOa+GvQJAHHMhgV15LsDWNU2KWPwtdfGAQj/f3Nx8ZnBw8E0aG6QtRrPJiciB2Ch1CoB3HaLIz/ANILiCBDeLBCpAbW3tN4pA8mAAJEkOwxWkCo0N2h55y3fyIEU1lu/wOqEv52JeNkQot2FVglsN9u3xKmS1mUe3OhtU3xP+3MtuMzkvPP4RR2Wy0hBhBQUFv9upOWw/Aof4KFeENjwgvHZJPewwhzlRQXhzLff09fW9S64zF6+EPXNIbuCVzwYnHA615Dp25garc9AhIuKk3+8/h4GCJ34R/fwFenq6OsgT1idqSKHNNjr4Do8Lz8caIHiMQ9TLEGeoxLhj5/AIGGHMAbwGCVIBtpvLXCdAOIXnVfVJepAmoaTDjj6NIUsgYNxv6GKk5AR1PxJQQiHGXfU8D+FO2KsSHGIkpRBeVk6RdxUARI5CjLFSd1AySRFRiR7aE0+JSWLE82gFCLW7u/vEysrKg3vmMTlyXqjLtwAC4wWpPmqlJO7qZ/zIecIez1vVA/pBSQ2ABkADoAHQAGgANAAaAA2ABmBvjjt3Q/HrYNErDQAAAABJRU5ErkJggg==);}
.map-icon.menu-arrow{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGtWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjE6MTU6MzgrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjE6MTU6MzgrMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6YjAwYTA1YjYtMjY5OS02YjRiLThjNWItMWYyYjE5MWExZGYzIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjUxRUY2QzE1QzZDNDExRUI4MEU1REE5MzM0ODFEQjU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTFFRjZDMTVDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUU5OEIxNkM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUVGNkMxM0M2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDplYWZkZDkzYy0wZWVkLTQ0NDItOGIyMC1mYWEwNDBjZWYxYzciIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDM6MjgrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6YjAwYTA1YjYtMjY5OS02YjRiLThjNWItMWYyYjE5MWExZGYzIiBzdEV2dDp3aGVuPSIyMDIxLTA2LTA2VDIxOjE1OjM4KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+2C6caQAAApFJREFUaN7tmD1PVEEYhS8X2A0C4QdYsgHEQCJCpECgAG3AQmIHDZRa2IidCgUWgo0mhE2gooNACJ8L+8HvMLHlbyxnyBkzWfbjHTN3Es0UT7LJ5mTPmXnPzN0blcvl6F8mCgFCgBAgBAgBQoD/OsCv3zdp8BS8AD2gFURCUmAITINeS62zAA/BR7AL3tFQi9CEqX1rqXUW4DHYBJcgDz6AARALTDwytFdg2ULrLEAbR2APFMEJ+Az6BUaUdgrsgxI4pbYPNPkKoEy2g1mQBQVwQCODDUZCmeygdqtCO9CoE64CaDrBa/CDo3TKkXgiKKcKMUdtQap1HUDRxRBZjpOa6/fCcnYxhNbmG2mTCKBX8xU7kSfLHKdYsBOz7ESBC6APhSZfAbSRlzRS5Eh8EhZba/cMbdVDIckAMY3MGMU+NMpZb5xiYyey9YqdZABzNVUnftLICUdiSFDsTkNrHgp/tD4C1CvnoOCs19qtikPhTusrgF7NOd642sgCn4Ui4U5cGgswr7Q+A6R54x7RhLp1F3kT22hLZElpfQXQBta5itdgBTwTnEjVtKtgVGl9BNAG1kAOXPDzBHggeNRW2q/U5Qxtm48SK/NjXL0cT6AN8JzfSbTf6mmTDKB+ZBjscOtzhgHJ2NTSNvu4yFJcPW2gxK2/Z8BSG/t4lDBLd0UDK5zbtGVhi9SO1zpuXQdI1SjsuOC4rNTeK2zSAczCKuPH4Du3PiUsrC77sbTsrgK08q3ENrf+gubHBIXV2r8pu7MA3Vy9c87tmtQAyBi7ZlN2pwEyXLUz8IUznxY+YmSM8LZap28lJsEbMCK4YSvfSmjtsKXW+SnUbPPjVf7EWOvCu9EQIAQIAUKAECAECAES5haiMD3NvrnvzwAAAABJRU5ErkJggg==);}
.map-icon.lang{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGtWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjA6NTY6MjkrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjA6NTY6MjkrMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6YWE2NGZhZmItMjY5ZC00YjQ3LTkwMTMtMjkyN2E1ZTZiYjI5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjUxRjVDQ0NDQzZDNDExRUI4MEU1REE5MzM0ODFEQjU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTFGNUNDQ0NDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUYyMEU5M0M2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUYyMEU5NEM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpmOGY3MzMxNi04MGJkLTBlNGEtODI1NS1hODg5YzE2NTU3MWEiIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDQ6MTgrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6YWE2NGZhZmItMjY5ZC00YjQ3LTkwMTMtMjkyN2E1ZTZiYjI5IiBzdEV2dDp3aGVuPSIyMDIxLTA2LTA2VDIwOjU2OjI5KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+XqcavQAABaZJREFUaN7tmfdvHFUQx01AtECIg0RovuRAwQiEQJgONgj4JZEiuIASSAQxAhsIkAQck/APufcq994tuXfLsi33Lvdu3sfah17We3d79q0R4n4Y7e2+3Zk3b75Tz29nZ8fvv0x+PgV8CvgU+J8psLW1de/a2tpDS0tLjy0uLh5fWFjwF3RCIaN7f4PnuwQPeMET3pYpsLGxcf/c3NwTQ0NDgb29va93dHS829bWFtza2gqFKNcQ5T5Yd79nDR6C13vwhDcykOVVBWA4OTkZUFdXdzYpKelGVFTUnejo6D9jYmKgSI30v9V1Z2u7JHjdhie8hYxzyDKrhKnN9/X1vZaXl/dtXFxcBMKghISE3zMzM8NzcnJCBX3nglyth8IDXpIvMoSsq0Lmq2aUMHPyNhgKxrcSExNvFhUVfd3T0/PG8PDwC+Pj43ZOi3d0V7NkEzxOwwue8EYGsnJzc0PNWMKlAgKPJ4GN3HxlZeXn4HR1dfXh7e3te7wVSeAFT3gjQ1MiAjjhE2L9iMcKEBEEwxcFLq9jWk6HeytDIhtFBrKQieyBgYGXXVnBKTPCGpFBOiwmFqd01OxGOID19fUHBT2wubl5n6tTVAlLIEs6NpGKcOuxAsRmQqV0WHBqFjZsGvw2Nzd/1NDQ8CnQWF5eftQsnJAlHRsYTU9PP+OxAiLB+IsY/QFhjkiBs5lNdP39/a8Ag7S0tGupqam/EHHEqQZhETM8kCVkhiEbn5iYmLB5rABmI9nAhA0QMcwIx+lqa2vPxcbGRgIBDYK3y8vLv3C1EZWwHjKRXVFR4RgbG3tuPwr4gz9FgQAzwmXOUDfPFStiUTMw1Clw4SAKBHuiAJurr6/fzdZsHCvEx8f/QQYmLGIFM8kJa3tDAQmhSDMKsHm+KSwsvCwdnwSILxAOsQKWETA65a5oM4CQ3XIf4GRF2A0CKmw2PT39J6JQe3v7+xkZGT/yTDj1z/AkSh0GhE54AqGVlZVHgAhZlM1SCnByU1NTz+bn53/DM+CEhQiprvKCDkKOgygQYgZCJKqZmZmnOHWECuzfKisr+5JkiGVEKHSweaCVnJz8m7sax8AH7JZagBMlewrc754+sb+xsfETuU7NL2GEIsCKPHOYPhDqygc4/dLS0osy9hcUFFyhhpHrZNbi4uKvWMM6AkZXgJYJBSIPagEJIacKaEVfINCQMV/4woXR0dHnKUcgNgSMZF7ATwYHB18Celb7gFsI0dOSoCj4ZPLKysoKq66uPk8pTi1TU1NzPjs7+3u5DrW0tHw4Pz//uNV5wK0Tc9LAR92cC/pL/i4pKbk0MjJyxo0CXoGQUwsQCru6ut4STntNLR10/fA/PbGEGIqkpKT8Kr592yicWmUBm1HJTemgbOwOG6OS1ChcJaKTfJcr38LDqmLOrQ/I7kluiJKhs7PzHcphjewa7d53d3e/iSLw5Butywu0yon9dWF0jwJAQDon4ZFQ6ar5mJ2dPVlVVfUZhR3fiG9/gIeJUsK+n4bmuLuGhtKZmE71yTtsxggSSsI7xje8SyilxKB+ctLQhCsNzan9tJTHmJjpWsojeisBC0JmU1PTx+5qHNboq8nS5AoOSFjlSYOW8gxZXWkpn95vUx8k8W3U1LMhahrepcI007jzDu/SvNNi6ktrrzX1MsPqxiqBhzBWCfTKWEU32IrQBlsObbB11OyYxOzGlcGWQ8i6oQ22zu57sKUOdeVcVBstXlZGi6e1caI6WrQ5GTXaDO4DnIwWI0Q/cZV3DjRaVIe7NCgGw90wN4Ndo0HvXcNebbh7Ux3uIguZBx7uOhmvX9eVDIYjcxfP96zLQtCS8br+Dw6cigSHIPBKotHIoVz1v9Vndz0nzsMLnvC25A8OfdgkrJFxSTCkeY3sym8jshu9Bw/iPDzh7Wlw8P1L6VPAp4BPgX+X/gYyBN4R3cx1lAAAAABJRU5ErkJggg==);}
.map-icon.lang-arrow{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAF6GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjA6NDM6MDIrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjA6NDM6MDIrMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6YzA2MjNlM2QtY2E0NC1lOTRjLTgwODAtNzgwNDNiM2FhMjkzIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjUxRjVDQ0Q0QzZDNDExRUI4MEU1REE5MzM0ODFEQjU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTFGNUNDRDRDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUY1Q0NEMUM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUY1Q0NEMkM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpjMDYyM2UzZC1jYTQ0LWU5NGMtODA4MC03ODA0M2IzYWEyOTMiIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDM6MDIrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7iBht7AAABU0lEQVRYCWP4//8/w0BihlEHjDpg1AGjDhj0Dvj48aPovXv3DC5duuQAxY5IbGQxFHGgHn2QXood8Pr1a9mTJ0/6rFq1qmTZsmUVxGCg2mKQHpBeih3w9+9f5hcvXijt2LEjacWKFWVACyrxWQ5UUwpUmwzSA9JLlTTw48cPrsePH2usX78+d/ny5WW4LAfKlYPUANVqgvRQLRH++/eP6du3b7yguN20aVMWLgeA5EBpAaiWD6iHkaq5ABScHz58EDt+/LjfunXr8tEtB4kB5fxBaogJerKzISh4Dxw4ELFy5cpSmOVAdglIDCRH83Lgz58/rLdv3zbZsmVLOswBQHbGrVu3zEBydCmIvnz5Inj9+nUrUCiAfH/t2jVroJgA3UpCUBy/fftW+uzZs+4gDGKTEu9UKYp//frF8e7dO0kQBrFHK6NRB4w6YNQBow4Ysg4AAIT0yfupLSRxAAAAAElFTkSuQmCC);}
.map-icon.windowed{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGtWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjA6NTc6MDUrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjA6NTc6MDUrMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MGQ1MWRhZWItOWZlYy0wMjRmLTg3ZjgtNzY0YmZmY2Q2MThlIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjUxRkFDRTFEQzZDNDExRUI4MEU1REE5MzM0ODFEQjU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTFGQUNFMURDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUY4NzVGMUM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUZBQ0UxQkM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpjZDg5NWViOC05MDA4LWU1NDYtOTliMy1jYTdhMTlmNTVkODUiIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDM6NDMrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MGQ1MWRhZWItOWZlYy0wMjRmLTg3ZjgtNzY0YmZmY2Q2MThlIiBzdEV2dDp3aGVuPSIyMDIxLTA2LTA2VDIwOjU3OjA1KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+xx+gXgAAA9VJREFUaN7tmFtLVFEUx50TBFFNWGm9VdI3KAMvxYxlQb0X1HMXumGo5HwhRR2YkdFXwVfBywzqwOi7lxdvqAyitn+xl2w35+hxPGfEOg+bsc66/ddea+21Vs3BwUHNRT41EYAIQAQgAhABqAqA/f39GCdsg7QeJ3AAOzs717a3t6/v7u5eDst4ZKMDXYEBwCNK4NWpqakXY2NjbwuFQmJra+vGabzkQ4eDTCU7qXS8Qxcg/OjwJRyvYPzAwEDX8PDwZxRtbm7e3Nvbu3RW45GBLBwzMjLyUenoBAQ6AwEgV4sCjO/v7+/OZDI/5ubmWtbX128LCH7598bGxq1yuXzFlsH/KUNr1Xebp65YLDZns9nvSnaXAvEJB/kNVd+e0lecwPi+vr7f6XT6l1LcJDfBlU9OTrZPT08/X15evm/zr6ys3INfhUc7tOJ5jEcWMpXsnxivdMVDqUIoxPOiEK9h1NraWv3S0tKDoaGhb4ODg50zMzPPzIrF37Ozs63wQQMtPPAiQxyiZDejI5QqZF15k1w5YTU+Pv6mVCo1YkRvb29PPp9P2gAwlm/QQAsP4YIMIyTrTptXZ0o6nRNdgBkdHf3A38rIlALQZgMAFN+gUbTvuQlxALIqLQoVVw5CAC9iPJ4lDPjVN+AGoE2+Cy0gkKFk3am0olVkPEm4uLj4UIXCEzxvGJ8yQsjxAiAg4EWGyokGSezQARCnVBu8RzzrsOkxzzEhdISOkiyJzeNFCQ4dALGKgZKw9snlcl/m5+cf23wLCwuPiHc3HmRJHoQOgAeJmk5ZRClgzIPxq6urd20+cgYQ3IRBn6TuIwuZbg9gaO00Me5yYn67Wus40Tzw3wGwQ8fvwCMhc24h5JLESeO0kagkrM1HYpPgkrxykFHVJJY2wquMUioBYfNhPCXWq4wChnY7dAA8Njw6p3zIHPsl1n3R34eMdkQ9ji95JKvWSvD801VarUSPWysBzzGtRCNtSdVaCbuZUzfx1aWZO9JOGwBSJi2e181cfVWbOWOGpZ/vBoTRTrvNA470QtBDq+eJbqOdrg39BtwGGkAoL76mq5TEpj2wutHDHFA0HTLQHDdjhzFSOnjppJGSb5RF+wbUmPmUcVOPlA0eI2WLHiljgQOQod5Q2CEKJbEZ2KGhptv8DPoM/BMTE6+8hnpxCLoCBaDXKkn2Nl4zLL+sTDDKa61CCbZ5rLXKYU4EtlbhOs3Flt7bVJx0J83YxmIr7ieUfMW+hAeC9RXHg1z0GqvFBI4yVouxoJe78Qu33D2H9boT2mIrGmgiABGACEAE4J8D8Aczok9ZTSEvewAAAABJRU5ErkJggg==);}
.map-icon.fullscreen{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGx2lUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjA6NTk6MTErMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjA6NTk6MTErMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTM2NTlmYTItNGExMC04ZDQ5LTkxOGEtY2EzNDFkNTM3MTg5IiB4bXBNTTpEb2N1bWVudElEPSJhZG9iZTpkb2NpZDpwaG90b3Nob3A6YTkyZjJiNDgtOWZlMi0wYjQ2LThhOGItODRlMjhiODAwYmQzIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTFGQUNFMURDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUY4NzVGMUM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUZBQ0UxQkM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpjZDg5NWViOC05MDA4LWU1NDYtOTliMy1jYTdhMTlmNTVkODUiIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDM6NDMrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MTM2NTlmYTItNGExMC04ZDQ5LTkxOGEtY2EzNDFkNTM3MTg5IiBzdEV2dDp3aGVuPSIyMDIxLTA2LTA2VDIwOjU5OjExKzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8++Fe+UgAAA8hJREFUaN7tmNtLVEEcx90Ngqg1su3yVkb/QSVkFzxbFtR7QT13oRuGG7X/kLKr4Ir6Kuyr4BV1QX1X98VV0UVEbT4xvxgPe/TsOsc2mIfh7OXMd37fme9vfpemg4ODpv95NDkCjoAj4Ag4Ao5ALWN/fz+mRlw/ZcTrWVzjxP14kRBYW1u7vri4eHd6ejqlhidjZmamY25u7mGpVLqxs7NzLgwW7/E+85hv4oG/tLR0p1wuX7VKAOOHhoY+9vT0/PKP/v7+7yy+ubl5KQyWeq8Fw5lXDW94ePgDJKwR4IjZGd9CmWw2+wMj8vn8l4mJiWfr6+tXwuBtbGxcnpycfDo4OPiZ+Qon7SfBemHkFIrA3t7eGT+B3t7en6Ojo28XFhbuLS8v365UKhd4Lywe76+srNxiPjjg+Qh4YXyrVgIZMZ4nOz82NvYSvYY13sRkHvPVSXwycQ0CMZsS8gBGNuwYxvMZvaJn9F/LCYgfjIyMvAcHEuCKnKIgkNIO28Wxs3MYz+IDAwNf5+fnHygfSB5Hgv/xlWKxeF9vQhoSCu+Fwm0Tx1bk7EkIoNnZ2Ud9fX3dOB7a5fjZQYzg6FkYEuxs0M6Bw0nxHu8zj/nggKdwW8WxuWKtnQBjdXX15tTU1JPx8fHn4rAYq3ay3W/M1tbWxWoY/O4j3SWkxbHV7dTJO8QJq3GA4MP1x/GLTAw5tPt9Ynd396w5n+/IQsnlHbIxZHcIT62RhFDYoHjiXMR0SIzP5XLdhULh9fb2drNIgKf6nlC/v1L//9F8rY4faTKHtkUeGEmQQg4GgbjIA3JaZs215j2RZ6PIhJ3G2Gr/8zsn45dXQ6XTkl26euAfnkBgfVBPvt+IPpBoOB8wbiGPW8a4heKy8+r7eX7nlpJgZ8NXrMYBgpQRBxIGgbgZB3Sw8yQCnwoBIiOBh0h5RCSWIOUFROKOoxJAjZck4luPxOQmGEAwCsqFlFHfMJ4gdVQuhPGSAJKVmrmQquw6ybnIvWyWlDGyQxbU2WhrQDbarrPRwFuI/4/LRsl6Vfb72GY9EGMRKeClHtDFSNXErJZ6AFmBB67UA7YLmpiuyCjk06pyesNOyeI6MWuppyLTPpGGjFGRZawW9ZpAyizoeUJC18TXTlITY3yVmjg6Ar6uRBsVWj1dCboZzPd1JTLWuxKGhA71bqQvxEkQpLj+wuDhA9w2p9YXYtApQ69BnTnxg7CdOQwM6szRAaQTaDUOoFdISP9SeqTc+xZ6oylzYDy92Ci707EIutN/u9SuHnAEHAFHwBFwBMKO32LMT11ZWJ89AAAAAElFTkSuQmCC);}
.map-icon.visible{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAF6GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjA6NDQ6NDQrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjA6NDQ6NDQrMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MWViMmUwMGItZDU1ZC1mZjRhLTllMmEtODQyYTU2N2QyMDcwIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjUyMDI0REU4QzZDNDExRUI4MEU1REE5MzM0ODFEQjU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTIwMjRERThDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MjAyNERFNUM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MjAyNERFNkM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDoxZWIyZTAwYi1kNTVkLWZmNGEtOWUyYS04NDJhNTY3ZDIwNzAiIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDQ6NDQrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz6vrQMdAAAFQklEQVRo3u1Y+0/TVxSHAkONsLlkUzADg+KWzB/oZrIN/W0Ph3tkyxbRuliyJRtEQJD5AHV/yBAdDKw82gq2YB8R6cAidirqmIDjWdtC3wrFlrbsfORb9rW0uvAoW/L94SY39557zvncc8/rRs3MzET9n0cUB4ADwAHgAHAAOAAcAA7ACgPw+fwxrqnHCSMPjK/f+bNvh1Z3a/fl9mtfK9uu7qWxD3OsYW9Eb3iDaNfizIoD8Hq9sVa7Y0Pv/cG3ScGslsu/fdMgU+ZVN1w8fOacpKy8uv4kBuZYwx5oQIszOAseEQfg9/ujJ11TCaMGY3rn790fi2WqvPLqhpO/1F44WnuhpUDarP6+SdH6XbNac4CGEHOJXP0D7RWCBrR0JhdnRw2mrS7iRTx5EQEA00P5e3SDULSCbpduuJRuuETR2rGfnkmm3mBKtzucr7o9nlUYmGMNT4hoBIyFSnEWPGANgCDevGUH4HA+fEWr694NJXCTIqn8UJtW96XeMJZOwBI9nulVeBY+ny8GlsLNYo417IEGtBqt7guRRF50mngAPPHMAu9lBTBmtqRcvX7zkxqxDMqfkqmu5Ny91/+ezeFcj5uGwo8mJl8aGB7ddu3G7Y9aO7q+wqD5LqzR3jrQgNZmd27AWeIhxEUQz2LwHjNbU5YFgNlq24g3K5I2Hzp7XnpceaVjX9/AEB9KzT4tXwyE627dfV+masupkciKz4gkpRg0L8Ia9kADWpzBWfAgXgLieQy8IQOylgwAnsDEpOvF6zfvfFjb2JJfSU54qbV9P970Y7d7TUD5h48mXm7vuvEplK2qazoCJ5Wr2oQYmFfVNR7BLXcQDWgDIIjHar3RtAU8wZtkFHSRLMiEtRYNAObu6b3/bl3jpfyKc+IyubpNaBo3p3oZBTCmKK73DwzzK0nJsyLpcRXF/8Fh/TbEewzMsYZbrqxtPEq0GVifC8fEi3huAu+KGvEJklVAMt9xuz2r/f6Z6AUD8ExPv2AkxvWk/OmahhMXFa3f9g8MZbCVn31e9o0KelIQrtZo9yChTXu9cbAeBs1jaW0r9oimjGgFwc+EeMaCN2RAFkCQ7FTosGAAFpsjWa3p3INEhCSEEIkQGkxnMI2nnacYT0nrVHdP706YP5gGa7d7+nYgsRFtwQPT+OZgGvCGDDHJgkzIttjsSQsGYByj229SHESUQLQYHNG/GYoO/lBV3/Tjz7/W/9T719BbFC7j51mT1vpoDzREW4IEFooXZCC6QSZkG0zmtMVYIIluIZuxQC5jgcQQFtiMW8XtPscCOxkLFJIF0v6FBbLJAsmL9YFU8oGDLB/gh/EBAeMD2XjvLB+Ixhx+gb3n+ACf5QP58D/SIX7BACgC8BAJ5kchyyY2CBc7ClGkYUWhhDBRiM+OQr4nUciSSrwPQAZk/bEUUShMHjj2jDzwGRIYYv78PNAULg+sYfKAgMkD+aw8wFuyTGyx2pOZTFyIm2QycUZQJn5N1/0kEwtDZGIhZeIPQmTiDPBatkz8dC1kDdRCxYHIFKIWWsfUQrvC1EI8oo2nWmg9UwvlPF0LWVIiUY1moYIMVKOaTt3neuPYFheqUXJ8r9cXh7I74MSYUzUaB4cEDWhnq9HmovJIVqOsfiCR+oHtQf3AYSXV+nP9gJPVDzjn+oFM5Ww/UBLUD2xn+oGYSHZkicEdWeUzOjKsoSOr/Kcjy2M6svSIdmRBPXFciJ44N0xPXBKiJ05akZ44zK/EWuZXIhMKsn4l9jK/Eln/uV8J7mOLA8AB4ABwADgAHAAOAAdgZcffjhZLtD3yt4UAAAAASUVORK5CYII=);}
.map-icon.hidden{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGtWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjA6NTc6MTUrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjA6NTc6MTUrMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6NDkyMjI3NTQtZTVmMi05ZDRlLThmMTUtMGM2YjlhNDM3YTg2IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjUyMDZFOUYzQzZDNDExRUI4MEU1REE5MzM0ODFEQjU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTIwNkU5RjNDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MjA2RTlGMEM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MjA2RTlGMUM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpiMDk1ODU3Ni0yMTYwLWI4NDQtYjc1MS04MGQ2Y2I4MWM4MTUiIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDQ6MDYrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6NDkyMjI3NTQtZTVmMi05ZDRlLThmMTUtMGM2YjlhNDM3YTg2IiBzdEV2dDp3aGVuPSIyMDIxLTA2LTA2VDIwOjU3OjE1KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Rbx5lgAABX5JREFUaN7tmPdvl1UUxlsEQZEiiiuR4oh71BUqaiRBhkHFGY0TjKC4aBWL/kXde6Y7Heme6d57N917ej7mHnJj2ui3344Y3x/eUL7v/b73PM95nufc9+uxurrq8V++PBwADgAHgAPAAeAAcAD8nwGsrKzsWl5evmlHAVDE4uLizVNTU7ePjIzcNzg46N3X1/dwT0/Po729vY/09/c/NDQ0dGR0dPSe6enpg0tLS7vN9zxnZma8WDs+Pn4Xz9hWABQuxeyRIg5Igd41NTWv5ebmfpCYmHgpIiLCLyQk5LfQ0NBrsbGx36empn6Vl5f3Xl1d3SsC5N7Z2dnbANPa2vqcrL9cXl5+ChDbCmB+fv6Wzs7OJ6XoD6Oion4OCwv7VYoOCA4Ovh4UFPR7YGDgH1z8zWeACQ8P/yUmJubH/Pz88wACLN8BBJ1wVU4bKpxNkERpaenZ5OTkr4VtfwqMj4//jqIqKytP1tfXv9zW1vZse3v7M01NTS9VVVWd4F5CQsK3dCYyMvIqF4D4jE4gJ2S1pQBoPaxTTHR09E8Un5KScrG4uPhcc3PzCwMDAw8gBdYhL665ubn9k5OTd3Cvtrb2VTqgHeG7DQ0NvqxHklsqIbQOo5mZmZ/SdgAgHwqnQNhbWFjYNzExcViMfBRJYGL+BtTY2NjdMC2dugLzFI8nkCIAFPiWACAhkARmRNOi92slJSVvDg8P32+vodiKioo3jLT8pFD/pKSkb+gQRhVD/4CERDaXhfljAngvqdTV1fVEWVnZGQjSlNpUABSfkZHxOZtjWDQuTN+ppqN46cSLsIqZRSIBALUNrCYHhHTCB7b5vnTvkAC+SFdkj88AsWkA2EBy/MGsrKxPYBOjStuPIxn0zRpYhHktHsaFzdMtLS3PA1T+fwkghnkM6yMR6qWaR0L4gHt0LTs7+2P88m8S6R+Lh2WJvHdJDPKcNhu93zAca0Q2J7X46urq1xlorGM2AJp7AvACsjGG9bTmiSdDkPRiLXsVFBSctzu8IQAMGpghaWCmsLDwHeLz7+sYYmge2cA8xdtDyjLscdiWVLp1rcIYcPgKAOzH3jxnwwCQBW2lsPT09C8w2lrrSBs2RCbIBuYpno7pkGpsbDxG8aRUd3f34yTaWs+Se4/hA/Zkb6TkDgBv0gITYuD1ABCVsAwANI9sdMICQg0L8zxDkuzCeoVxH7LY020ATEaYk5b60daioqJzdmzanYJlNsUD6NiesBhWJYWUiOJ1pHhEZPq2kay/kZCXWyZGDmQ40RkXF3eFLMdwtokZQALuLaLSzAg1rK8e2ohYmAUYcwKD2iZmHwKCiIUwgsNtEysIWM/JyfmIzZmiyMTE6G42Z8ICTHOe4u0JC/MUr8DoGNHL84li5gAG184R2US3xvSmDDKGC+aiQOSkgwwzWob9K+eJSmPYvWiaojWJ6ISe+zWmeZZ0+CrPZg8Zmj5bcpTo6Oh4mnOQyOQ6Q43TKPJC/xRvTdj9GJZEQe+YFtlgSJ6jM4DOEpsaAKyFDFdebFw+icIok5KCOczhDcuwTNiDFAi7dIeimRMwTYTiHeRHJ5Alz4B5iKHL68Xrph6nORexMayZI/GNCQvzpBdHaD1Om5PmYcBQOF3T9wieI0fz9zmiu3oSdRmAvsPCNHIxptQj8T59VwAM8Quj6Jk04phgXmiI2wCKB4TI8Awd2uiLvctvYkxd1bwxrK8eibmXlpb2JffWeqXkc0ATk7xHCNinMPu2/qxC5hOZTFoMp29SAIBt3nUZZhRJwegbtlmP5pnSDCw6aWJ417YCkITYAwjYtt9h+RcDm59VjurPKlz8zWfckyF4yE6iHfthCzm5y57z06IDwAHgAHAAOAAcAA6AHb7+BNCOQ1ssyDZCAAAAAElFTkSuQmCC);}
.map-icon.list-arrow{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAF6GlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjA6NDM6MTMrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjA6NDM6MTMrMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6YzY3ZGNiODctYThmYi1hYTRiLWE2NTctYmUyNGUzYWIzMzFiIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjUyMDRBQjFGQzZDNDExRUI4MEU1REE5MzM0ODFEQjU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTIwNEFCMUZDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MjA0QUIxQ0M2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MjA0QUIxREM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDpjNjdkY2I4Ny1hOGZiLWFhNGItYTY1Ny1iZTI0ZTNhYjMzMWIiIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDM6MTMrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8L3JkZjpTZXE+IDwveG1wTU06SGlzdG9yeT4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7lIMfHAAACAElEQVRYw+2VyUubURTFY9WaYgUHxHZXS0FBceGmOKAWOmBXoi0UFbqo4lRFK61/UhIyDyQQSAhk2IQkkJFAIARCSDYJGcg8eM8i8BE0fFbUzVtklXff+d1zzuMTtFotwVP+BAyAATAABvA/Q81m81mhUBiORqNzkUhkPpvNjtfr9b5HAYB4LpcbC4fD7w0Gw55Wqz3y+XyrmUzmVaPR6H1wgFKp9DIYDC6S8KFIJLoSi8X/FArFmcfj+ZjP50cA+GAAtVrtudfrXdPpdAdSqfSPWq0+0ev1+zKZ7EKlUv12Op1fAXgXCN6242IS/0CCe3K5/NxkMu3GYrHZRCLxzmq1flMqlacajeaYINbJiVG+cfAR70HmZPsSbX4IcYvF8gMFrFarA1S+/ng8PmW32zcBAScQB3ViAv/dC6AtHgqFFpA5bDebzTtt8fY5bEsQ0+TEd8SBTiAqPsXkU7gliEskkr/U+l/YlsSFnWchlEqlJglwm0AvOcUcxSJ3Bugo3CXEk8nk20ql8uK2kmEmnU6/hkucYq53K+at4oFAYBnvHJnjQmzeTZw7S0684RbT5XJ9wSxvADostNlsWxjmFE7YzcrOOADscDg2cIfRaPxZLBaHeAOgYH6/fwXk9NRmbsqcDwSeqNvt/kT3fC6Xy4NP9jHqFhv7HDMABsAAGMA1oQnP+8t8SiAAAAAASUVORK5CYII=);}
.map-icon.refresh{background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAACXBIWXMAAAsTAAALEwEAmpwYAAAGtWlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDggNzkuMTY0MDM2LCAyMDE5LzA4LzEzLTAxOjA2OjU3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1sbnM6c3RFdnQ9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZUV2ZW50IyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bWxuczpwaG90b3Nob3A9Imh0dHA6Ly9ucy5hZG9iZS5jb20vcGhvdG9zaG9wLzEuMC8iIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIDIxLjAgKFdpbmRvd3MpIiB4bXA6Q3JlYXRlRGF0ZT0iMjAyMS0wNi0wNlQyMDo0MDowNSswODowMCIgeG1wOk1vZGlmeURhdGU9IjIwMjEtMDYtMDZUMjA6NTc6MDYrMDg6MDAiIHhtcDpNZXRhZGF0YURhdGU9IjIwMjEtMDYtMDZUMjA6NTc6MDYrMDg6MDAiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MDExODc5NDMtOGZlZi1mNDQ4LTg5N2UtNmIwNmU4MjYwNTkwIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjUxRjg3NUVDQzZDNDExRUI4MEU1REE5MzM0ODFEQjU5IiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InhtcC5kaWQ6NTFGODc1RUNDNkM0MTFFQjgwRTVEQTkzMzQ4MURCNTkiIGRjOmZvcm1hdD0iaW1hZ2UvcG5nIiBwaG90b3Nob3A6Q29sb3JNb2RlPSIzIiBwaG90b3Nob3A6SUNDUHJvZmlsZT0ic1JHQiBJRUM2MTk2Ni0yLjEiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1MUY4NzVFOUM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1MUY4NzVFQUM2QzQxMUVCODBFNURBOTMzNDgxREI1OSIvPiA8eG1wTU06SGlzdG9yeT4gPHJkZjpTZXE+IDxyZGY6bGkgc3RFdnQ6YWN0aW9uPSJzYXZlZCIgc3RFdnQ6aW5zdGFuY2VJRD0ieG1wLmlpZDo3MWQ2Yzc1MS0xMDM3LTU1NDQtOTZmZi04MWQ5YzUzODA2ZWUiIHN0RXZ0OndoZW49IjIwMjEtMDYtMDZUMjA6NDM6NTQrMDg6MDAiIHN0RXZ0OnNvZnR3YXJlQWdlbnQ9IkFkb2JlIFBob3Rvc2hvcCAyMS4wIChXaW5kb3dzKSIgc3RFdnQ6Y2hhbmdlZD0iLyIvPiA8cmRmOmxpIHN0RXZ0OmFjdGlvbj0ic2F2ZWQiIHN0RXZ0Omluc3RhbmNlSUQ9InhtcC5paWQ6MDExODc5NDMtOGZlZi1mNDQ4LTg5N2UtNmIwNmU4MjYwNTkwIiBzdEV2dDp3aGVuPSIyMDIxLTA2LTA2VDIwOjU3OjA2KzA4OjAwIiBzdEV2dDpzb2Z0d2FyZUFnZW50PSJBZG9iZSBQaG90b3Nob3AgMjEuMCAoV2luZG93cykiIHN0RXZ0OmNoYW5nZWQ9Ii8iLz4gPC9yZGY6U2VxPiA8L3htcE1NOkhpc3Rvcnk+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+L+v5uQAABQ9JREFUaN7tmfdvVmUUx1ssAqIIgoCrmhBAEcRgJCoaFRVXKBQEkamCytCyStV/qHvvvVe690r3TPfei/Mx701umtb3vu+9DX2T+8OTt/cdz3O+53zPOd/z1GlxcdHJkZeTCcAEYAIwAZgA1iSAhYWFdfPz808pi2eHATA3N7d+fHx8y+Dg4O6BgYGXhoeHX5ycnHxWQDivSQAYhoGtra0HSkpKvsjMzDybnJx8KTEx8UpCQsJVXlNSUn7Kyso6U1ZW9nl7e/t+Afj8EwcgnnYZGRnZ3tTU9E5xcfGXGB0WFnbbz8/vkbe39z/q5ePj87e/v//D8PDw24Dh+wCemJjYoicydhs/Ozv7dH9//8uVlZUfx8bG/orRrNDQ0D9jYmKui+evAQhjk5KSLsfHx1+Ljo7+LTg4+K6vr69XYGDgfXn/Ul1d3fujo6PbcMaqAbAkobP6GePz8vK+xxC8GxAQ8EAMv1FQUPANnpXPX4FWMzMzG8bGxrb29PS83tjY+G52dvbpiIiImxINT4AEBQXdra6u/pBI2pPomvgtybiLRMTrGN/X1/dqenr6OYwXr3sKLW5VVVUd43vT09ObSGKl8iiLZ37P593d3W8AVOh2R8AD4l55efmncsYOQwFwKIfl5OSckuXW3Nx8CM7yHBIS8hdehx4tLS0H8TKGazlUorIRsOL5jyQat4gEUamoqPiEfQwDgEEkKNzFW7m5uW719fXvwXMSEn7zOQbZGn6+L9x/ARCRkZF/kD+SJz/L/kds2ctqlcHrAIAuUVFRv1MS8RiHkoDQQk+zm5qaeqaoqOgETiGilGBKrNbKZBVAV1fXnri4uF9IVPiqlMT8/Pzvent7X4Nmekoxvx8aGtolFesi++IsoqrVMVY3p5NSEtX1nGiQdG1tbW8BQiv3/+8caXCfkQfkFtWNZNcNgBCTVCSquikpFKL+SzU6L+XxsB4qsXBUaWnpcbq1ROCwIRFQKkZGRsYPGL1MZ/WkQVHf9QIgioCAsuK0bVoTWVMfoMZLxblIlVB0DZ6nnNKJhcM79ebCqkoJokAjE7678go/V8NgtQQ3pAqpo7Da2h4KIT2IJo5CWmih5RObpIgq+qiwsPBrEjctLe1HSikUhar8TT5YE3k2qU/oI6XzTYtscNEDQOnClE26MEVBVST+5bmmpuYDpIshADiQzktJZWNbNcty+9XW1h6lSbLoxEvnCIYjawJP84E0LNFCJ/EMuqijo2Of3kSG852dnXvZS2jkTjSUCPAq3f5bZLshACSUz6HbLT3AS/TLV8y8eqsO1ESew31Frig9h9xADRsCAG+TVExbHIBmEUodJRn1zNIi5jaTyFCIuYB9aY6ckZqaeoHoGFaF4D1NTcZCD7owDQ0ZYa+cplQSVWYC9mMERROhhZT9BcBewwAQBZKP0ApfPZC/hF4Gmrd5346BBuNv4m3VVLcbacK8LEl8nNHU0D5gkb87AUHIGSkxYoWR0llZqpFy45KR8j91yy0FWkjJC+kRruSdtY5sr/xdx2GEmijgQctQfx3DGDFJzCVDveuSof4hv4OOlqF+h7qqaZUTuq5VMJK5QBLvBsYQDdW1ytUVrlU8lNsIPmNEtYV+Rl9srac7NzQ0HCEa5IOlIXkuc7HlhdfxPvKcZOWGTu+Vo2FXi+obupWuFoU+7kSMHGAWXsuXuy4M5sy66stdR7ted3bY63XzPzQmABOACcAE4DDrMQ+PWcLdovDOAAAAAElFTkSuQmCC);}
</style>
<script src="https://wiki.biligame.com/ys/MediaWiki:Knockout.js?action=raw&ctype=text/javascript"></script>
<style>
.simple-folder{cursor:pointer} .simple-folder[data-expand=false] + *{ height: 0; overflow: hidden; transition-property: height; transition-duration: 1s;}
.orderItem.collapsed > .items-wrap{display:none!important} .mapSearch{display:none!important}
</style>
<script name="map.api.js">
var BwikiMapApi = function () {
var origin = 'https://tools-wiki.biligame.com'
var param = {
game: null,
site: null,
dataPrefix: 'Data:Map',
i18n: 'zh'
}
var sign = function (data) {
if (typeof data !== "object") throw Error("Sign Failed!")
var sign = md5(data.game + (data.markTypes || "") + (data.i18n || "") + data.ts + "9b83b0c44c89e26fc52aa50a202c2fd1");
return Object.assign({}, data, {sign: sign})
}
this.set = function (data) {
Object.assign(param, data)
}
this.getOrderData = function (i18n, callback) {
if (!param.game) throw Error("Required parameter missing: game")
if (typeof i18n === 'function') {
callback = i18n
i18n = null
}
$.ajax({
method: "post",
url: origin + '/wiki/getOrderData',
data: sign({
game: param.game,
i18n: i18n || param.i18n,
ts: (new Date).getTime()
}),
success: function (data) {
if (typeof callback === "function") callback(data.data)
}
})
}
this.getMapData = function (markTypes, callback) {
if (!param.game) throw Error("Please set the query parameters first: game")
if (!markTypes) throw Error("Required parameter missing: markTypes")
$.ajax({
method: "post",
url: origin + '/wiki/getMapData',
data: sign({
game: param.game,
markTypes: markTypes,
ts: (new Date).getTime()
}),
success: function (data) {
if (typeof callback === "function") callback(data.data)
}
})
}
this.getPointData = function (list, callback) {
if(typeof list === "function"){
callback = list;
list = ["point.json"]
}
$.each(list, function(i, page){
$.ajax({
url: `/${param.site}/${param.dataPrefix}/${page}`,
success: function (data) {
data = $(data).find("#mapPointData").text().replace(/:Data:[\s\S]{0,30}\/json/g, ":[]");
data = (new Function('return ' + (data || "{}")))();
if (typeof callback === "function") callback(data)
console.log(data)
}
})
})
}
}
</script>
<script name="map.game.switcher.template" id="switcher-template" type="text/html">
<span data-bind="text: label"
style="display:inline-block;font-size: 13px;height: 1em; line-height: 1em;"></span>
<br>
<label data-bind="attr: { style: 'display: inline-block;font-size: 20px;height: 1em;width: 2em;border-radius: 1em;cursor: pointer;vertical-align: bottom;background: ' + ($root[selected]() ?color:'#aaa')}">
<div class="animate-fast"
data-bind="attr: { style: 'height: 1em;width: 1em;border-radius: 1em;background: #FFF;' + ($root[selected]() ?'transform: translate3d(100%, 0, 0)':'') } "></div>
</label>
</script>
<script name="map.game.toolbar.template" id="map-menu-template" type="text/html">
<style data-bind="if: showMenu()">
.leaflet-left {
left: 400px;
}
</style>
<div id="map-menu" data-bind="css: {'toggle-active': showMenu()}">
<div class="mapShrink" data-bind="click: function(){ showMenu(!showMenu()) }">
<div class="shrink-inner">
<i class="map-icon menu-arrow" data-bind="style: { margin: '1em 0',transform : showMenu()? 'scaleX(-1)' : 'scaleX(1)'}"></i>
</div>
</div>
<div class="mapShrink map-area-tab" style="height:auto;top: calc(10vh + 80px);" data-bind="foreach: areaData, visible: areaData().length != 0">
<div data-bind="class: 'shrink-inner ' + ($root.selectedArea() === inside? 'item-active':'') ">
<i data-bind="class: 'map-icon ' + icon , click: function(){$root.changeArea($index())}"></i>
</div>
</div>
<div class="mapMenu">
<div class="wiki-logo">
<img src="https://patchwiki.biligame.com/resources/assets/images/logo/logo_ys.png?t=2021052411&v=41" alt="">
</div>
<div class="menu-search-box">
<input data-bind="value: keyword, valueUpdate: ['afterkeydown', 'input'], click: openToolbox" style="text-align: left"/>
<i class="map-icon search" style="width: 2em; height: 2em; position: absolute; right: 24px; top: 20px;"></i>
</div>
<div class="menu-btn-group">
<div title="此功能暂未完成">
<i class="map-icon lang"></i>
<span>语言</span>
<i class="map-icon lang-arrow" style="position: relative; left: 0.5em;"></i>
</div>
<div data-bind="click: purge">
<i class="map-icon refresh"></i>
<span>刷新</span>
</div>
<div data-bind="click: fullScreenSwitcher">
<i data-bind="class: 'map-icon ' + (isFullScreen()? 'windowed' : 'fullscreen')"></i>
<span data-bind="text: isFullScreen()?'退出全屏':'网页全屏'"></span>
</div>
<div data-bind="click: removeAllMarkers">
<i class="map-icon hidden"></i>
<span>全隐藏</span>
</div>
</div>
<div data-bind="class: 'menu-tab-nav tab-index-' + menuTabIndex() + ' tab-' + menuTabList().length, foreach: menuTabList">
<div data-bind="class: cls, text: label, click: function(){$root.menuTab(id);if(id==='markerPanel') $root.updateCollections();}"></div>
</div>
</div>
<div id="menuList" class="markerList" data-bind="visible: menuTab() == 'listPanel', foreach: categoryObject">
<div data-bind="class: 'orderItem' + ($data.visible?'':' hide') + (!$data.collapsed?' collapsed':'')">
<div class="order-h5" data-bind="click: $root.collapse"><span data-bind="text: name"></span><small data-bind="text: '('+$data.count+')'" style="color:#aaa"></small>
显示全部
<i data-bind="class: 'map-icon list-arrow' + (!collapsed? '' : ' v-flip')" style="float: right; margin: 4px 10px 0 0;"></i>
</div>
<div class="items-wrap" data-bind="foreach: data ">
<div data-bind="class:'select-item ' + (selected?'item-active':'') + (($root.toolbox() || pointsNum) && !hide?'':' hide'), click: $root.setMarkers" class="select-item" style="cursor:pointer">
<span class="catTit">
<img class="list-img" data-bind="attr: {src: icon}" alt="icon">
<span data-bind="text: markTypeName"></span>
</span>
<span class="catNum" data-bind="text: pointsNum"></span>
</div>
</div>
</div>
</div>
<div class="markerList" data-bind="attr: {id:isPhone()?'':'infoPanel'},visible: !isPhone() && (menuTab() == 'infoPanel')">
点击点位可以查看该点位的详细信息或进行讨论
</div>
<div class="markerList" id="markerPanel" data-bind="visible: menuTab() == 'markerPanel'" style="padding:10px;">
<button class="btn btn-primary" style="background: rgb(95,108,121);width:calc(50% - 3px)" data-bind="click: saveUserData">保存数据至wiki</button>
<button class="btn btn-primary" style="background: rgb(95,108,121);width:calc(50% - 3px)" data-bind="click: loadUserData">从wiki同步数据</button>
<div class="drop-down-wrap panel panel-default" style="margin:10px 2px 10px 0;width:auto;padding: 0;font-size:12px;">
<div class="wrap-title panel-heading" style="height:auto"><div class="title" style="line-height:inherit;color:#aaa; font-size:12px;">之前地图的标记数据没有正常显示怎么办?</div><div class="glyphicon icon-arrow-close"></div></div>
<div class="wrap-content panel-body" style="display: none;">
目前新版地图与旧版地图的数据是分离的,若原地图还能正常区分已标记点位,请点击下方按钮尝试进行修复。<br>
<div style="text-align:center;"><button class="btn btn-primary btn-xs" style="margin: 4px;" data-bind="click: refreshUserData">修复标记数据</button></div>
若修复后还未解决问题,请 联系技术支持 或 加入Q群:759910798 进行反馈
</div>
</div>
<div data-bind="class: 'orderItem'">
<div class="order-h5" data-bind="click: $root.collapse"><span data-bind="text: '统计' + ($root.selectedArea() !== ''? '(' + $root.selectedArea() + '地区)':'')"></span></div>
<div class="items-wrap" data-bind="foreach: collections ">
<div data-bind="class:'select-item ' + (pointsNum?'':' hide'), click: $root.setMarkers" style="width: 100%;padding-left: 44px;font-size: 13px;cursor:pointer; position:relative">
<img class="list-img" data-bind="attr: {src: icon}" alt="icon" style="height: 34px;width: 24px;position: absolute;left: 10px;">
<span class="catTit" style="display: flex;justify-content: space-between;flex-wrap: wrap;width: 100%;">
<span data-bind="text: markTypeName"></span>
<span class="catNum" data-bind="text: count + ' / ' + pointsNum"></span>
</span>
<div class="progress" style="width: 100%;margin: 4px 0 0 0;height: 10px;">
<div class="progress-bar" role="progressbar" aria-valuemin="0"
data-bind="style: { width: count / pointsNum * 100 + '%', background: 'rgb(95,108,121)' } " >
<span></span>
</div>
</div>
</div>
</div>
</div>
<div class="drop-down-wrap panel panel-default" style="margin:10px 2px 10px 0;width:auto;padding: 0;font-size:12px;">
<div class="wrap-title panel-heading" style="height:auto"><div class="title" style="line-height:inherit;color:#aaa; font-size:12px;">点位数据有误,如何编辑点位?</div><div class="glyphicon icon-arrow-close"></div></div>
<div class="wrap-content panel-body" style="display: none;">
新版地图的地图点位由玩家进行维护,欢迎加入Q群:759910798 讨论并获取打点教程
</div>
</div>
<div class="drop-down-wrap panel panel-default" style="margin:10px 2px 10px 0;width:auto;padding: 0;font-size:12px;">
<div class="wrap-title panel-heading" style="height:auto"><div class="title" style="line-height:inherit;color:#aaa; font-size:12px;">是否可以补充自定义点位?</div><div class="glyphicon icon-arrow-close"></div></div>
<div class="wrap-content panel-body" style="display: none;">
目前该功能已纳入开发考虑,但因人手不足,欢迎前端开发加入一起完善,可加入Q群:759910798 进行讨论
</div>
</div>
</div>
<div id="searchPanel" data-bind="visible: menuTab() == 'searchPanel'">
搜索结果
</div>
<div id="toolPanel" class="toolPanel" data-bind="visible: menuTab() == 'toolPanel'">
<div data-bind="if: hasGeomanToolbar() && selectedType()">
<style>.leaflet-grab, .leaflet-interactive { cursor: default;}</style>
当前标记:
<img data-bind="attr: {src: selectedTypeData().iconUrl}" alt="icon" style="height:18px">
<span data-bind="text: selectedTypeData().typeName"></span>
<input id="saveSummary" placeholder="修改摘要" style="width:150px"/>
<div style="background: rgba(0,0,0,0.85);color: white;border-radius: 6px;padding: 4px;display: inline-block;font-size: 12px; cursor: pointer"
data-bind="click: savePoints">保存
</div>
<div class="simple-folder" data-expand="true">操作历史</div>
<div data-bind="foreach: markerOperationList" style="max-height: 50%;overflow: auto;">
<div data-bind="text: $data"></div>
</div>
<div class="simple-folder" data-expand="true">点位</div>
<div id="mapDataGrid" data-bind="if: hasGeomanToolbar() && selectedType()" style="max-height:50%;overflow: auto;">
<table style="width: 100%; word-break: break-all;font-size: 8px">
<thead>
<tr>
<th data-bind="text: 'No.'"></th>
<th data-bind="text: 'id'"></th>
<th data-bind="text: 'uid'"></th>
<th data-bind="text: 'lat, lng'"></th>
</tr>
</thead>
<tbody data-bind="foreach: markersData()[selectedType()]">
<tr data-bind="style: $root.stateColor($data.state)">
<td data-bind="text: $index() + 1"></td>
<td></td>
<td data-bind="html: $data.uid || ''"></td>
<td data-bind="html: point.lat + ', ' + point.lng"></td>
</tr>
</tbody>
</table>
</div>
</div>
<div data-bind="if: hasGeomanToolbar() && !selectedType()">
<span data-bind="text: selectedTypeData().typeName"></span>
<input id="saveName" placeholder="路径名" style="width:100px"/>
<input id="saveSummary" placeholder="修改摘要" style="width:150px"/>
<div style="background: rgba(0,0,0,0.85);color: white;border-radius: 6px;padding: 4px;display: inline-block;font-size: 12px; cursor: pointer"
data-bind="click: saveGeoJSON">保存
</div>
<div data-bind="text: editingGeoJSON" style="max-height:50%;overflow: auto;"></div>
</div>
<div class="simple-folder" data-expand="true">区域</div>
<div style="max-height:50%;overflow: auto;">
<table style="width: 100%; word-break: break-all;font-size: 8px">
<thead>
<tr>
<th data-bind="text: '区域名称'"></th>
<th data-bind="text: '操作'"></th>
</tr>
</thead>
<tbody data-bind="foreach: areaData()">
<tr>
<td data-bind="text: name"></td>
<td ><div style="background: rgba(0,0,0,0.85);color: white;border-radius: 6px;padding: 4px;display: inline-block;font-size: 12px; cursor: pointer" data-bind="click: function(){$root.loadGeoJSON($index())}">载入</div></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div id="mapSetting" style="position: absolute; right: 10px ; bottom: 100px ;z-index: 1000;" data-bind="visible:toolbox">
<div class="map-setting-btn" data-bind="click:$root.positionPopupSwitcher, css: {'toggle-active': hasPositionPopup()}">坐标</div>
<div class="map-setting-btn" data-bind="click:$root.getOldMapData, visible: hasGeomanToolbar()">GET</div>
<div class="map-setting-btn" data-bind="click:$root.geomanToolbarSwitcher, css: {'toggle-active': hasGeomanToolbar()}">打点</div>
<div class="map-setting-btn" data-bind="click:function(){$root.toolbox(false)}">关闭</div>
</div>
</script>
<div id="map-div" name="map.body.html">
<div id="map-wrap" class="swipe-container" style="position:relative; overflow:hidden; height: calc(100vh - 50px);">
<div id="map3" style="height: 100%"></div><div class="swipe-panel"></div>
<div class="swipe-panel" style="position:absolute; width:100%; height:100%; transition: top 0.5s; background: white;z-index: 99999;border-radius:20px" data-bind= "css: 'swipe-panel ' + ($root.selectedPoint() !== null? 'toggle-active':''),visible: isPhone()" ><div id="marker-info-panel"></div><div data-bind="attr: {id: isPhone() ? 'infoPanel':''}"></div></div>
<div data-bind="template: { name: 'map-menu-template' }"></div>
</div>
</div>
<script name="map.common.js">
var util = {
autoSet: function (self, defaultData, data, mode) {
/* ko初始化使用 */
data = Object.assign({}, defaultData, data);
for (var i in data) self[i] = mode ? ko.observable(data[i]) : data[i]
return self;
},
loading: function () {
$("body").append("<div class='loading-mask' style='position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.1);z-index:99999999'></div>")
},
loadend: function () {
$(".loading-mask").remove();
},
getUrlValue: function (part, key) {
var query = window.location[part].substring(1);
var vars = query.split("&");
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split("=");
if (pair[0] === key) return pair[1] || '';
}
return '';
},
getUID: function () {
// 需查重
return Number(Math.random().toString().substr(3, 3) + Date.now()).toString(36)
},
coordFormatter: function(latlng) {
return {lat: latlng.lat.toFixed(6), lng: latlng.lng.toFixed(6)}
}
}
</script>
<script name="jquery.swipe">
var swipe = function () {
var self = $(this), $children = $(this).children('.swipe-panel'), cNum = $children.length;
var $target, index = 0, startY = 0, diffY = 0;
self.on('touchstart', '.swipe-panel', function (event) {
if (event.targetTouches.length > 1) return true;
$target = $children.eq(index);
startY = event.targetTouches[0].pageY;
});
self.on('touchmove', '.swipe-panel', function (event) {
// if ($children.index(event.target) !== 1) return false;
if (event.targetTouches.length > 1) return true;
diffY = startY - event.targetTouches[0].pageY;
var top = 10;
if ( diffY > 0) {
top = (80 - (diffY / 6));
if (top > 80) top = 80;
$target.next('.swipe-panel').css({
transition: "0s",
top: top + "%",
})
return false;
} else if (index !== 0 && diffY < 0) {
top = -(diffY / 6);
if (top < 10) top = 10;
$target.css({
transition: "0s",
top: top + "%",
})
return false;
} else {
return false;
}
});
self.on('touchend', '.swipe-panel', function (event) {
// if ($children.index(event.target) !== 1) return false;
if (event.targetTouches.length >= 1) return false;
var minY = 20;
var isSuccess = Math.abs(diffY) > minY;
if (index < cNum - 1 && diffY > 0) {
isSuccess ? index++ : 0;
$target.next('.swipe-panel').css({
transition: "1s",
top: isSuccess ? "10%" : "80%",
})
return false;
}
if (index !== 0 && diffY < 0) {
isSuccess ? index-- : 0;
$target.css({
transition: "1s",
top: isSuccess ? "80%" : "10%",
})
return false;
}
});
};
</script>
<script name="map.markerController.js">
var MapMarkerController = function () {
}
</script>
<script name="map.editorController.js">
var MapEditorController = function () {
}
</script>
<script name="map.model.js">
var MapModel = function (data) {
var self = util.autoSet(this, this.defaultData = {
mapCenter: [0, 0],
zoom:5,
maxZoom: 8,
minZoom: 4,
toolbox: false,
hasPositionPopup: false,
hasGeomanToolbar: false,
categoryData: {},
categorySelected: {},
categoryObject: [],
areaMarkersData : {},
selectedType: null,
selectedPoint: null,
selectPointObj: null,
selectedTypeData: {},
keyword: "",
menuTab: 'listPanel',
markersData: {},
markerWithInfo: [],
areaData: [],
selectedArea: '',
showMenu: true,
isFullScreen: false,
editingGeoJSON: "",
dataList: ["point.json"],
snappable:false,
markedMarker: {}
}, data, true);
self.markerOperationList = ko.observableArray([]);
self.collections = ko.observableArray([]);
self.updateCollections = function(){
var result = self.categoryData();
self.collections([])
$.each(result, function(key, category){
var count = 0;
$.each(category.data, function(tindex, type) {
var collection = $.extend({count:0},type);
$.each(self.markersData()[type.markType] || [], function(pindex, point) {
if(type.collectible && checkMarked(type.markType, point.id) &&
(self.selectedArea() === "" || point.inside === self.selectedArea()))
{collection.count++;}
})
if(type.collectible) self.collections.push(collection)
})
})
}
var setCategoryObject = function () {
var result = self.categoryData(), markers = {};
$.each(result, function(key, category){
var count = 0, selected = 0;
$.each(category.data, function(tindex, type) {
var collection = $.extend({count:0},type);
type.selected = self.categorySelected()[type.markType];
selected += type.selected?1:0
type.hide = false;
if(type.markTypeName.indexOf(self.keyword()) === -1){ type.hide = true; return true; }
markers[type.markType] = []
if(self.selectedArea() === "") {
markers[type.markType] = self.markersData()[type.markType] || []
} else {
$.each(self.markersData()[type.markType] || [], function(pindex, point) {
if(point.inside === self.selectedArea()) markers[type.markType].push(point)
})
}
type.pointsNum = markers[type.markType].length;
if( markers[type.markType].length > 0) count ++;
})
category.count = self.toolbox() ? category.data.length : count;
category.visible = self.toolbox() || (count > 0);
if(category.collapsed === undefined || typeof category.collapsed === "number") {
category.collapsed = selected
}
})
self.categoryObject([]);
self.categoryObject(result);
self.areaMarkersData([]);
self.areaMarkersData(markers);
}
self.search = ko.computed(function () {
setCategoryObject();
return self.keyword();
}, this);
self.collapse = function (obj) {
var result = self.categoryData();
$.each(result, function(key, category){
if(category.name === obj.name) category.collapsed = !category.collapsed
})
self.categoryObject([]);
self.categoryObject(result);
}
self.menuTabList = ko.computed(function () {
var list = [{id: "listPanel", label: "点位列表", cls:self.menuTab()==="listPanel"?"toggle-active":""}];
if(!self.isPhone()) list.push({id: "infoPanel", label: "点位信息", cls:self.menuTab()==="infoPanel"?"toggle-active":""})
if(!self.toolbox()) list.push({id: "markerPanel", label: "我的标记", cls:self.menuTab()==="markerPanel"?"toggle-active":""})
// if(self.keyword() !== "") list.push({id: "searchPanel", label: "搜索结果", cls:self.menuTab()==="searchPanel"?"toggle-active":""})
if(self.toolbox()) list.push({id: "toolPanel", label: "控制台", cls:self.menuTab()==="toolPanel"?"toggle-active":""})
return list;
}, this);
self.menuTabIndex = ko.computed(function () {
var index = 1;
$.each(self.menuTabList(), function(i, tab) {
if(tab.id === self.menuTab()) { index = i + 1; return false};
});
return index;
}, this);
var layers = {}, icons = {}, markerTypes = [], markerGroups = {}, markedGroups = {}, storageKey = "";
var posPopup = L.popup();
var reformatInfoPgae = function (html) {
var $html = $(html), $div = $("<div>");
$html.find("a").attr("target", "_blank");
$html.appendTo($div);
return '<style>.wiki-header, #content > *, #bodyContent > * , .comments-title, .comment-time {display:none} #wikiToapp{display:none!important} .mw-body{min-height:auto!important}body{background:white!important;}</style>' + $div.html() + '<style>#bodyContent, #mw-content-text, #flowthread{display:block} #flowthread > .comment-replybox {position: fixed;padding:0;bottom:0;background:white;z-index:99;width: calc(100% - 26px);} .comment-body{padding:0!important} .comment-thread .comment-replybox{margin:0}.comment-body textarea{height: 36px!important; line-height: 26px; padding: 6px 10px; outline: none; background: #F0F0F0; border-radius: 51px; margin-bottom: 4px; color: black;}.comment-body textarea::-webkit-scrollbar { display: none; }.comment-toolbar{height: 36px; margin-bottom: 4px; width: 60px; padding: 0; margin-left: 10px;}.comment-submit{height: 36px; line-height: 0; width: 60px; border-radius: 51px; background: rgba(0,0,0,0.85);}.comment-avatar{margin:-1px 4px 0 0}.comment-avatar img,.comment-thread>div:not(:first-child) .comment-avatar img{width:20px;height:20px}.comment-post{padding:8px 0 4px 0}.comment-footer{padding-top:4px}</style>'
}
self.changeArea = function(index) {
var time1 = new Date().getTime(), time2 = 0;
if(self.areaData()[index].inside && !self.areaData()[index].split) {
splitIntoArea(index)
}
self.markerOperationList.push("分区 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
var selectedTemp = mapModel.categorySelected();
self.selectedArea(self.areaData()[index].inside);
self.markerOperationList.push("设置选择地区 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
self.removeAllMarkers();
self.markerOperationList.push("移除全部标记 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
setCategoryObject();
self.markerOperationList.push("重新计算点位列表 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
$.each(selectedTemp, function(type, selected){
if(selected) self.setMarkers({markType: type}, true)
});
self.markerOperationList.push("重新显示已选点位 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
setCategoryObject();
self.markerOperationList.push("重新计算点位列表 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
if(self.areaData()[index].center !== null) map.panTo(self.areaData()[index].center);
else { map.panBy([1,1])}
self.markerOperationList.push("移动中心 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
self.updateCollections();
self.markerOperationList.push("重新计数 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
}
var splitIntoArea = function(index) {
var area = self.areaData()[index];
var t1 = new Date().getTime();
$.each(mapModel.markersData(), function(type, testPoints){
$.each(testPoints, function(index, testPoint){
if(testPoint.inside) { return true; }
var inside = isMarkerInsidePolygon(testPoint, area.geojson.features[0].geometry.coordinates[0]);
if(inside) { testPoint.inside = area.name; return true;}
})
})
area.split = true;
//self.areaData(self.areaData().splice(index, 1, area));
self.areaData().splice(index, 1, area);
var t2 = new Date().getTime();
console.log(area.name + " 分区所花时间 " + (t2 - t1))
}
var isMarkerInsidePolygon = function(marker, poly) {
var polyPoints = poly;
var x = marker.point.lng, y = marker.point.lat;
var inside = false;
for (var i = 0, j = polyPoints.length - 1; i < polyPoints.length; j = i++) {
var xi = polyPoints[i][0], yi = polyPoints[i][1];
var xj = polyPoints[j][0], yj = polyPoints[j][1];
var intersect = ((yi > y) != (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
if (intersect) inside = !inside;
}
return inside;
}
self.loadGeoJSON = function(index) {
var layer = L.geoJSON(self.areaData()[index].geojson,{
style: function (feature) {
return {color: feature.properties.color || "#3388ff"};
}
}).addTo(map);
layer.on('pm:markerdragend', markerEditController);
}
self.generateGeoJson = function(){
var fg = L.featureGroup();
var layers = findLayers(map);
layers.forEach(function(layer){
fg.addLayer(layer);
});
return JSON.stringify(fg.toGeoJSON())
}
function findLayers(map) {
var layers = [];
map.eachLayer(layer => {
if (
layer instanceof L.Polyline ||
layer instanceof L.Marker ||
layer instanceof L.Circle ||
layer instanceof L.CircleMarker
) {
layers.push(layer);
}
});
// filter out layers that don't have the leaflet-geoman instance
layers = layers.filter(layer => !!layer.pm);
// filter out everything that's leaflet-geoman specific temporary stuff
layers = layers.filter(layer => !layer._pmTempLayer);
return layers;
}
var getPurgeTitles = function(){
var titles = [mw.config.get("wgPageName")];
$.each(self.dataList(), function(i, page) {
titles.push(self.dataPrefix() + "/" + page)
})
return titles.join("|")
}
self.purge = function(){
new mw.Api().post({
"action": "purge",
"format": "json",
"titles": getPurgeTitles()
}).then(function(){
window.location.reload();
})
}
self.getOldMapData = function () {
var type = self.selectedType()
if (!type) return false
mapApi.getMapData(self.selectedType(), function (data) {
alert("请到控制台(F12)查看 " + self.selectedTypeData().typeName + " 数据!");
$.each(data, function (i, p) { p.state = "fromDB" })
updateObject(self.markersData, type, {[type]: data})
console.log(data)
})
}
var clickCounter = 0, clickTimer = null;
self.openToolbox = function () {
if(clickTimer){clearTimeout(clickTimer)}
clickTimer=setTimeout(function(){ clickCounter=0 },1000);
if(++clickCounter>=3){ mapModel.toolbox(true) }
}
self.fullScreenSwitcher = function () {
var $map = $("#map-wrap").toggleClass("fs");
$($map.parent()[0].tagName === "BODY" ? "#map-div" : "body").prepend($map);
self.isFullScreen(!self.isFullScreen())
map.invalidateSize(false)
}
self.positionPopupSwitcher = function (disabled) {
self.hasPositionPopup(disabled = !self.hasPositionPopup())
map[disabled ? 'on' : 'off']('click', function (e) {
posPopup.setLatLng(e.latlng).setContent(e.latlng.toString()).openOn(map);
});
if (!disabled) posPopup.remove()
}
self.geomanToolbarSwitcher = function (disabled) {
self.hasGeomanToolbar(disabled = !self.hasGeomanToolbar())
map.pm[disabled ? 'addControls' : 'removeControls']({position: 'bottomleft', snappingOption: self.snappable()});
map.pm.setLang('zh');
disabled ? self.removeAllMarkers() : ''
self.setMarkers = disabled ? setMarkersEditable : setMarkersCanvas
}
self.createPointPage = function () {
var id = self.selectedPoint()
var pointType = self.selectPointObj().icon.options.type
var Text = "欢迎在下方留言~"
var ChestText
switch(pointType){
case 60:ChestText = "华丽的宝箱";break;
case 61:ChestText = "精致的宝箱";break;
case 62:ChestText = "普通的宝箱";break;
case 63:ChestText = "珍贵的宝箱";break;
}
if(ChestText != undefined)
Text = "[[:模板:宝箱\n]]"
new mw.Api().create(self.dataPrefix() + '/point/' + id, {"bot": 1, "minor": 1, tags: 'apiedit|autoedit|aboutmap'}, Text ).then(function () {
new mw.Api().ajax({action: "purge", titles: "Widget:Map3"}, {method: "post"})
self.markerWithInfo().push(id);
showMarkInfo(id)
}).catch(function (e) {
if (e === 'nocreate-missing') {
new mw.Api().ajax({action: "purge", titles: "Widget:Map3"}, {method: "post"})
self.markerWithInfo().push(id);
showMarkInfo(id)
}
});
}
var showMarkInfo = function (id) {
self.selectedPoint(id)
if (self.markerWithInfo().indexOf(id) === -1) {
$("#infoPanel").html("此标记暂时还无内容和讨论 点击创建");
} else {
var $iframe = $('<iframe src="about:blank" width="100%" height="100%" frameborder="0">');
var $btn = self.hasGeomanToolbar() ? $("").css({
display: "inline-block",
cursor: "pointer",
position: "absolute",
right: "10px",
background: "#ffffff88"
}).html("编辑") : "";
$("#infoPanel").html($btn).append($iframe);
$.get(`/${self.site()}/${self.dataPrefix()}/point/` + id, function (html) {
$iframe[0].contentWindow.document.write(reformatInfoPgae(html));
})
}
if(!self.isPhone()) self.menuTab('infoPanel')
}
self.editPointPage = function () {
var id = self.selectedPoint();
window.open(`/${self.site()}/${self.dataPrefix()}/point/${id}?action=edit`);
return ;
var $iframe = $('<iframe src="about:blank" width="100%" height="100%" frameborder="0">');
$("#infoPanel").html($iframe);
$.get(`/${self.site()}/${self.dataPrefix()}/point/${id}?action=edit`, function (html) {
$iframe[0].contentWindow.document.write(reformatInfoPgae(html));
})
}
self.saveGeoJSON = function () {
util.loading();
var saveName = $("#saveName").val()
var saveSummary = $("#saveSummary").val()
if (saveName === "") {
util.loadend();
alert("请填写保存路径名!")
return false;
}
if (saveSummary === "") {
util.loadend();
alert("请填写保存摘要!")
return false;
}
new mw.Api().edit(
self.dataPrefix() + '/' + saveName,
function () {
return {
text: self.editingGeoJSON(),
summary: saveSummary,
minor: true,
tags: 'apiedit|aboutmap'
};
}
).then(function () {
new mw.Api().ajax({action: "purge", titles: self.dataPrefix() + '/' + saveName}, {method: "post"})
.then(function () {
new mw.Api().ajax({action: "purge", titles: self.dataPrefix() + '/area.json'}, {method: "post"})
new mw.Api().ajax({action: "purge", titles: self.dataPrefix() + '/route.json'}, {method: "post"})
});
self.markerOperationList.push(`保存 ${saveName} 数据成功!`);
alert('Saved!');
util.loadend();
}).catch(function (e) {
if (e === 'nocreate-missing') {
new mw.Api().create(self.dataPrefix() + '/' + saveName, {
summary: '加油!打路人',
contentmodel: "text",
tags: 'apiedit|aboutmap'
}, "").then( self.saveGeoJSON )
}
});
}
self.savePoints = function () {
util.loading();
var saveSummary = $("#saveSummary").val()
if (saveSummary === "") {
util.loadend();
alert("请填写点位保存摘要!")
return false;
}
var type = self.selectedType();
var points = self.markersData()[type]
var submitData = [], submitText = [];
new mw.Api().edit(
self.dataPrefix() + '/type/' + type + '/json',
function (revision) {
submitData = JSON.parse(revision.content || "[]")
$.each(points, function (i, p) {
if (!p.state) return true;
if (p.state === "create") {
delete p.state
submitData.push(p);
} else {
var point = getObjectWithAttr(submitData, 'id', p.id)
if (point.index === false || p.state === "fromDB") {
delete p.state
submitData.push(p);
} else if (p.state === "remove") {
submitData.splice(point.index, 1)
} else if (p.state === "edit") {
delete p.state
submitData.splice(point.index, 1, p)
}
}
})
$.each(submitData, function (i, p) {
submitText.push(JSON.stringify(p))
})
return {
text: "[" + submitText.join(",\n") + "]",
summary: saveSummary,
minor: true,
tags: 'apiedit|aboutmap'
};
}
).then(function () {
new mw.Api().ajax({action: "purge", titles: self.dataPrefix() + '/type/' + type + '/json|' + self.dataPrefix() + '/type/' + type }, {method: "post"})
.then(function () {
new mw.Api().ajax({action: "purge", titles: getPurgeTitles()}, {method: "post"})
});
self.markerOperationList.push(`保存 ${type} ${self.selectedTypeData().typeName} 数据成功!`);
$.get(self.site() + "/" + self.dataPrefix() + '/type' + type + '/json')
alert('Saved!');
$.each(submitData, function (i, p) {
if (p.state) delete p.state
})
updateObject(self.markersData, type, {[type]: submitData})
util.loadend()
}).catch(function (e) {
if (e === 'nocreate-missing') {
new mw.Api().create(self.dataPrefix() + '/type/' + type, {summary: '加油!打点人', tags: 'apiedit|autoedit|aboutmap'}, "[[:模板:PointGrid]]").then(function () {
setTimeout(function () {
util.loadend();
new mw.Api().create(self.dataPrefix() + '/type/' + type + '/json', {
summary: '加油!打点人',
contentmodel: "text",
tags: 'apiedit|autoedit|aboutmap'
}, "").then(self.savePoints)
}, 1000)
})
}
});
}
self.getMarkerList = function () {
mapApi.getOrderData(self.setMarkerLayer)
}
self.setMarkerLayer = function (data) {
self.categoryData(data)
layers['marked'] = L.canvasIconLayer({}).addTo(map);
layers['marked']._canvas.setAttribute("name", 'marked')
layers['marked']._canvas.style.opacity = 0.5
layers['marker'] = L.canvasIconLayer({}).addTo(map);
$.each(data, function (i, order) {
$.each(order.data, function (j, category) {
markerTypes.push(category.markType);
icons[category.markType] = L.icon({
iconUrl: category.icon,
iconAnchor: category.iconAnchor || [14.5, 46],
popupAnchor: category.popupAnchor || [0, -40],
iconSize: category.iconSize || [29, 46],
typeName: category.markTypeName,
type: category.markType
});
})
})
// getMarkers(markerTypes.join(","))
var dataCount = 0;
if(self.dataList().length === 0 ) return dataLoaded();
mapApi.getPointData(self.dataList() , function (data) {
self.markersData($.extend({}, self.markersData(), data))
setCategoryObject();
dataCount++;
if(dataCount > self.dataList().length - 1) dataLoaded();
})
}
self.saveUserData = function() {
new mw.Api().postWithToken( 'csrf', {
action: 'edit',
title: "User:" + UserStatus.userInfo.mid + "/"+ storageKey +".json",
text: JSON.stringify(self.markedMarker()),
tags: 'apiedit|aboutmap',
minor: 1
}).then(function (data) {
if(data && data.edit && data.edit.result === "Success"){
alert("数据成功保存")
} else {
alert("数据保存失败,请刷新后尝试")
}
}).catch(function (e) {
console.log(e)
});
}
self.loadUserData = function() {
$.get("/ys/" + "User:" + UserStatus.userInfo.mid + "/"+ storageKey +".json?action=raw&ctype=text/json")
.then(function(data){
self.markedMarker(JSON.parse(data));
localStorage.setItem(storageKey, JSON.stringify(self.markedMarker()))
alert("云端数据成功同步");
setCategoryObject();
self.updateCollections();
}).catch(function(e){
if(UserStatus.userInfo.mid=== null )alert("云端数据获取失败,请检查登录状态!")
else alert("未获取到云端数据。")
})
}
self.refreshUserData = function(){
localStorage.removeItem(storageKey);
dataLoaded();
setCategoryObject();
self.updateCollections();
alert("标记数据恢复完毕,若未恢复正常请联系技术支持");
}
var dataLoaded = function(){
try{
// 处理点位缓存,兼容旧版 wikiYsOpacData
storageKey = "wiki" + self.game().toUpperCase() + self.dataPrefix().replace("Data:", "") + "Data",
oldStorageKey = "wikiYsOpacData",
self.storageKey = storageKey
markedMarker = localStorage.getItem(storageKey);
if(markedMarker !== null) {
markedMarker = JSON.parse(markedMarker);
} else if(self.game() === "ys" && self.dataPrefix() === "Data:Map" && localStorage.getItem(oldStorageKey) !== null) {
markedMarker = JSON.parse(localStorage.getItem(oldStorageKey));
} else {
markedMarker = []
}
if($.type(markedMarker) === "array" || !markedMarker.version) {
var temp = {version:"3.0", data:{}, self: {}}
$.each(markedMarker, function(i, id){
var point = getPointById(id);
if(!point) return true;
var obj = temp.data;
if(!obj[point.markType]) obj[point.markType] = {};
obj[point.markType][id] = 0;
})
markedMarker = temp;
}
self.markedMarker(markedMarker)
}catch(e){
console.log(e)
}
$.each(self.categoryData(), function(j, category){
$.each(category.data, function(i, type){
if(type.defaultShow === 1) self.setMarkers({markType: type.markType})
})
})
}
var getPointById = function(id){
var data = self.markersData();
for(var i in data){
for(var j in data[i]){
if(data[i][j].id === id) return data[i][j];
}
}
}
var onMarkerPopupOpen = function () {
// return false;
var marker = this, marked = this.options.marked, icon = this.options.icon.options
self.selectPointObj(this.options);
showMarkInfo(this.options.id)
console.log(window.temp = this)
var popupContent = $("<div style='margin-bottom: 10px;min-width: 150px;'>").html("<b>" + (this.options.title && this.options.title !== "" ? this.options.title : icon.typeName) + "</b><br>" + (this.options.title !== this.options.id ? "id: " + this.options.id :"" ) + "<br>").prepend($("").text(!marked ? "标记" : "取消").click(function () {
markMarker(this, marker);
}))
var $target = !self.isPhone() ? $(marker._popup._contentNode) : $("#marker-info-panel")
$target.html(popupContent);
this._popup.update()
}
var onMarkerPopupClose = function () {
$("#infoPanel").html("");
self.menuTab('listPanel')
self.selectedPoint(null)
if(!self.isPhone()) $("#infoPanel").parents(".swipe-panel").css('top', '100%')
}
var markMarker = function (btn, marker) {
console.log(marker)
var marked = marker.options.marked ^= 1,
id = marker.options.id;
if(marked) { // 正在标记
$(btn).text("取消");
marker["removeFrom"](layers['marker']);
marker["addTo"](layers['marked']);
} else { // 正在取消标记
$(btn).text("标记");
marker["addTo"](layers['marker']);
marker["removeFrom"](layers['marked']);
}
checkMarked(marker.options.icon.options.type, id, marked);
self.updateCollections();
}
var checkMarked = function(type, id, marked) {
var markedMarker = self.markedMarker(), obj = markedMarker.data;
if(!obj[type]) {
obj[type] = {};
self.markedMarker(markedMarker);
};
if(marked !== undefined) {
marked ? obj[type][id] = (new Date).getTime(): delete obj[type][id];
self.markedMarker(markedMarker)
localStorage.setItem(storageKey, JSON.stringify(self.markedMarker()))
};
return obj[type][id] !== undefined;
}
self.removeAllMarkers = function () {
if (layers['edit']) layers['edit'].clearLayers();
$.each(self.categorySelected(), function (type, bool) {
if (!bool) return true;
self.categorySelected(Object.assign({}, self.categorySelected(), {[type]: false}))
})
layers['marker'].removeFrom(map);
layers['marked'].removeFrom(map);
layers['marked'] = L.canvasIconLayer({}).addTo(map);
layers['marked']._canvas.setAttribute("name", 'marked')
layers['marked']._canvas.style.opacity = 0.5
layers['marker'] = L.canvasIconLayer({}).addTo(map);
}
self.gotoMarker = function () {
var thisMarker = this
$.each(markerGroups[this.markType], function (i, marker) {
if (marker.options.id === thisMarker.id) {
console.log(marker)
console.log(thisMarker.point)
//map.setView(marker._latlng, 7)
marker.openPopup()
map.panTo(marker._latlng);
// map.panBy(new L.Point(-200, 0));
return false;
}
})
}
var setMarkersCanvas = function (type, mode) { // mode: true no setCategoryObject
if (typeof type === "object") type = type.markType
var isSelected = self.categorySelected()[type]
if (!isSelected) {
markerGroups[type] = [];
markedGroups[type] = [];
var time1 = new Date().getTime(), time2 = 0;
console.log("开始 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
$.each(self.areaMarkersData()[type], function (i, p) {
if (p.state === "remove") return true;
var marked = checkMarked(type, p.id) ? 1 : 0;
var marker = L.marker([p.point.lat, p.point.lng], {icon: icons[p.markType], id: p.id, marked: marked, title: p.title})
marker.bindPopup().on("popupopen", onMarkerPopupOpen).on("popupclose", onMarkerPopupClose)
if (!marked) {
markerGroups[type].push(marker);
} else {
// marker["addTo"](layers['marked']);
markedGroups[type].push(marker);
}
})
console.log("array " + ((time2 = new Date().getTime()) - time1))
time1 = time2
if(markerGroups[type].length > 0 ) {
layers['marker'].addMarkers(markerGroups[type])
}
if(markedGroups[type].length > 0 ) {
layers['marked'].addMarkers(markedGroups[type])
}
console.log("显示 " + ((time2 = new Date().getTime()) - time1))
time1 = time2
} else {
$.each(markedGroups[type], function(i, marker) {
marker["removeFrom"](layers['marked']);
})
$.each(markerGroups[type], function(i, marker) {
marker["removeFrom"](layers['marker']);
})
}
self.categorySelected(Object.assign({}, self.categorySelected(), {[type]: !isSelected}))
if(!mode) setCategoryObject()
if(typeof self.afterSetMarkers === "function") self.afterSetMarkers();
}
self.stateColor = function (state) {
if (!state) return {};
if (state === "create") return {"background": "#a9e58c"}
if (state === "edit") return {"background": "#fff6aa"}
if (state === "remove") return {"background": "#ffb6b6"}
}
var updateObject = function (object, key, data) {
object(Object.assign({}, object(), {[key]: null}))
object(Object.assign({}, object(), data))
}
var getObjectWithAttr = function (object, attr, val) {
var target = {}
$.each(object, function (i, row) {
if (row[attr] !== val) return true
target = {index: i, row: row}
return false
})
return target;
}
var markerEditController = function (e) {
if(self.selectedType() === null) {
self.editingGeoJSON(self.generateGeoJson());
return false;
}
self.menuTab('toolPanel');
var action = e.type.replace("pm:", ""), marker = "";
if (action === "create") {
marker = e.marker;
} else if (action === "edit") {
marker = e.sourceTarget.dragging._marker;
} else if (action === "remove") {
marker = e.layer || e.sourceTarget;
}
var id = marker.options.id,
icon = marker.options.icon.options,
type = marker.options.icon.options.type,
data = self.markersData()[type],
rowIndex = action === "create" ? -1 : data.findIndex(function (value){ return value['id'] === id }),
thisMarker = {
point: util.coordFormatter(marker._latlng),
state: action,
uid: mw.config.values.wgUserName,
time: new Date().getTime()
};
self.markerOperationList.push(`${action} ${type} ${icon.typeName} ${id}`)
if (action === "create") {
data.push(Object.assign({ "id": id, "title": "", "markType": type }, thisMarker))
} else if (action === "edit") {
if (data[rowIndex].state === "create" || data[rowIndex].state === "fromDB")
thisMarker.state = data[rowIndex].state
Object.assign(data[rowIndex], thisMarker)
} else if (action === "remove") {
if (data[rowIndex].state === "create") data.splice(rowIndex)
else Object.assign(data[rowIndex], thisMarker)
}
updateObject(self.markersData, type, {[type]: data})
}
var refreshCursorMarker = function (type) {
if (!type) {
map.pm.Draw.Marker.options.markerStyle.id = util.getUID();
} else {
map.pm.Draw.Marker.options = {markerStyle: {icon: icons[type], id: util.getUID()}};
}
if (map.pm.Draw.Marker._enabled) {
map.pm.disableDraw('Marker', {});
map.pm.enableDraw('Marker', {});
}
}
var addGeoJson = function (type){
try{
$.get(`/ys/Data:Map/route/${type.markTypeName}.json?action=raw`).then(function(data){
var layer = L.geoJSON(JSON.parse(data),{
style: function (feature) {
return {color: feature.properties.color || "#3388ff"};
}
}).addTo(map);
layer.on('pm:markerdragend', markerEditController);
})
} catch(e){console.log(e)}
}
var setMarkersEditable = function (type, mode) { // mode: true no setCategoryObject
if (type.geojson) addGeoJson(type);
if (typeof type === "object") type = type.markType
if (!self.markersData()[type]) {
updateObject(self.markersData, type, {[type]: []})
}
var isSelected = self.categorySelected()[type]
self.selectedType(!isSelected ? type : null)
self.selectedTypeData(icons[type].options)
if (layers['edit']) {
layers['edit'].clearLayers()
self.categorySelected({[type]: !isSelected})
}
if (!isSelected) {
refreshCursorMarker(type);
markerGroups[type] = [];
$.each(self.markersData()[type], function (i, p) {
if (p.state === "remove") return true;
markerGroups[type].push(L.marker([p.point.lat, p.point.lng], {
icon: icons[p.markType],
id: p.id,
title: p.title
}).bindPopup().on("popupopen", onMarkerPopupOpen))
})
layers['edit'] = L.layerGroup(markerGroups[type]);
map.addLayer(layers['edit']);
/* 补充编辑层的编辑和移除处理 */
layers['edit'].on('pm:edit', markerEditController);
layers['edit'].on('pm:remove', markerEditController);
} else {
layers['edit'].clearLayers()
map.pm.disableDraw('Marker', {});
}
self.categorySelected(Object.assign({}, self.categorySelected(), {[type]: !isSelected}))
if(!mode) setCategoryObject()
}
self.setMarkers = setMarkersCanvas
/* 地图初始化相关 */
self.map = {
baiduCRS: new L.Proj.CRS('EPSG:900913', '+proj=merc +a=6378206 +b=6356584.314245179 +lat_ts=0.0 +lon_0=0.0 +x_0=0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs', {
resolutions: function () {
var level = 19, res = [];
for (var i = 0; i < level; i++) {
res[i] = Math.pow(2, (18 - i))
}
return res;
}(),
origin: [0, 0]
}),
TileLayerCustom: L.TileLayer.extend({ getTileUrl: mapData.getTileUrl }),
init: function () {
map = L.map(self.mapid(), {
crs: this.baiduCRS,
center: self.mapCenter(),
zoom: self.zoom(),
maxZoom: self.maxZoom(),
minZoom: self.minZoom(),
maxBounds: [[86, -140],[-86, 140]],
zoomControl: false
});
new this.TileLayerCustom().addTo(map);
L.control.zoom({zoomInTitle: '放大', zoomOutTitle: '缩小', position: 'bottomright'}).addTo(map);
map.on('pm:create', function (e) {
var layer = e.layer;
markerEditController(e)
refreshCursorMarker()
layer.on('pm:edit', markerEditController);
layer.on('pm:remove', markerEditController);
});
map.on('pm:edit', markerEditController);
map.on('pm:remove', markerEditController);
/*map.on('zoomstart', function(event){
console.log(event.target);
console.log(event.target._animateToZoom);
//setMarkers(202)
})
map.on('zoom', function(event){
//setMarkers(202)
console.log(event.target);
console.log(event.target._animateToZoom);
})
map.on('zoomend', function(event){
console.log(event.target);
console.log(event.target._animateToZoom);
})*/
$("#map-div").on("click", ".simple-folder", function(){
$(this).attr("data-expand", $(this).attr("data-expand") !== "true")
})
}
}
};
</script>
<style>
#map-wrap .map-setting-btn {
zoom: 0.8;
font-size: 8px;
width: 32px;
height: 32px;
}
</style>
<style>
.leaflet-container { background: rgb(23,75,86)!important; }
.leaflet-control-attribution {display:none}
.leaflet-left {
transition: all 0.5s;
}
.leaflet-popup-content-wrapper {border-radius:0}
.leaflet-bar a, .leaflet-bar a:hover {
background: rgba(0, 0, 0, 0.8);
color: #CED3DE;
border: 0;
}
.leaflet-bar a:hover {
background: rgba(33, 33, 33, 0.8);
}
.leaflet-pm-toolbar .control-icon {
filter: invert() brightness(1.25);
}
#map-wrap {
border: 1px solid rgba(0, 0, 0, 0.1)
}
</style>
<script name="map.main.js">
var map; // 地图对象
var mapApi = new BwikiMapApi(); // 地图api
var mapModel, self;
var mapData = {
getStorageKey : function(){
return "wiki" + mapModel.game().toUpperCase() + mapModel.dataPrefix().replace("Data:", "")
},
getIconUrl : function (icon) {
return `https://prod-patch-wiki.biligame.com/res/ys/map/icons/${icon}?v=${mapData.default.srcVersion}`
},
getCenter: function () {
// #接参数可以走缓存,而?会慢一些
var center = (util.getUrlValue('hash', 'center').replace(/ /g, '') || '').split(',')
return center.length === 2 ? center : [0, 0]
},
getCategoryData: function () {
var selectedType = localStorage.getItem(mapData.getStorageKey() + "SelectedType");
if(selectedType !== null) selectedType = selectedType.split(",")
var categoryDataJson = $("#mapData #categoryData").text().trim();
if (categoryDataJson !== "") {
categoryDataJson = JSON.parse(categoryDataJson)
var categoryTemp = {}, categoryList = [], categoryData = []
$.each(categoryDataJson, function (i, v) {
v.icon = v.icon.indexOf("http") === 0 ? v.icon : mapData.getIconUrl(v.icon);
if (!categoryTemp[v.type]) {
categoryList.push(v.type)
categoryTemp[v.type] = {name: v.type, data: []}
}
if(selectedType !== null) {
v.defaultShow = selectedType.indexOf(v.markType + "") !== -1?1:0
}
categoryTemp[v.type].data.push(v)
})
$.each(categoryList, function (i, v) {
categoryData[i] = categoryTemp[v]
})
return categoryData
}
return []
},
setCategoryData: function () {
var data = mapData.getCategoryData();
data.length > 0 ? mapModel.setMarkerLayer(data) : mapModel.getMarkerList();
},
setMarkerWithInfo: function () {
var data = $("#mapData #markerWithInfo").text().trim().replace(RegExp(`${mapModel.dataPrefix()}\\/point\\/`,"g"), "").split(", ");
mapModel.markerWithInfo(data);
},
getTileUrl: function(coords) {
coords = function (coords) {
var y = -coords.y + -1, r = Math.ceil((1 << coords.z - 1)/2);
return ( -r / 2 <= coords.x && coords.x < r && -r <= y && y <= r / 2 - 1 &&
{x: coords.x, y: -coords.y + -1, z: coords.z})
}(coords);
return coords ? `https://wiki-dev-patch-oss.oss-cn-hangzhou.aliyuncs.com/res/ys/map2.6-u-1/tiles/${coords.z}/tile-${coords.x}_${coords.y}.png?v=${mapModel.srcVersion()}` :
`https://prod-patch-wiki.biligame.com/res/ys/map/tiles/default.png?v=${mapModel.srcVersion()}`;
},
setGeoData: function () {
mapModel.areaData(JSON.parse($("#mapData #mapAreaData").text().trim()));
// mapModel.routeData(JSON.parse($("#mapData #mapAreaData").text().trim()));
},
afterSetMarkers: function(){
var selectedType = [];
$.each(mapModel.categorySelected(), function(type, selected){
if(selected) selectedType.push(type)
})
localStorage.setItem(mapData.getStorageKey() + "SelectedType", selectedType.join(","))
}
}
var $ready = function () {
$.fn.swipe = swipe;
$("#map-wrap").swipe();
mapApi.set({game: 'ys', site: mw.config.get("wgGameName"), dataPrefix: 'Data:Map'})
ko.applyBindings(mapModel = new MapModel(mapData.default = {
game: 'ys',
site: mw.config.get("wgGameName"),
mapid: 'map3',
dataPrefix: 'Data:Map',
mapCenter: [-25.456657, -33.90622],
srcVersion: '3.0.13',
zoom: 6,
minZoom: 4,
maxZoom: 8,
isPhone: window.innerWidth < 540,
toolbox: mw.config.get("wgUserGroups").indexOf("sysop") !== -1,
dataList: ["point.json", "point2.json"]
}));
self = mapModel;
mapModel.map.init();
mapData.setCategoryData();
mapData.setMarkerWithInfo();
mapData.setGeoData();
mapModel.afterSetMarkers = mapData.afterSetMarkers
window.onresize=function(){
if(window.innerWidth < 540 && !mapModel.isPhone()) return mapModel.isPhone(true)
if(window.innerWidth >= 540 && mapModel.isPhone()) return mapModel.isPhone(false)
}
};
</script>
<script>(function () {var t = function () {window.jQuery && window.mw ? mw.loader.load('ext.gadget.Map3') : window.setTimeout(t, 100); }; t(); })();</script>
<script>!function(n){"use strict";function t(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function r(n,t){return n<<t|n>>>32-t}function e(n,e,o,u,c,f){return t(r(t(t(e,n),t(u,f)),c),o)}function o(n,t,r,o,u,c,f){return e(t&r|~t&o,n,t,u,c,f)}function u(n,t,r,o,u,c,f){return e(t&o|r&~o,n,t,u,c,f)}function c(n,t,r,o,u,c,f){return e(t^r^o,n,t,u,c,f)}function f(n,t,r,o,u,c,f){return e(r^(t|~o),n,t,u,c,f)}function i(n,r){n[r>>5]|=128<<r%32,n[14+(r+64>>>9<<4)]=r;var e,i,a,d,h,l=1732584193,g=-271733879,v=-1732584194,m=271733878;for(e=0;e<n.length;e+=16)i=l,a=g,d=v,h=m,g=f(g=f(g=f(g=f(g=c(g=c(g=c(g=c(g=u(g=u(g=u(g=u(g=o(g=o(g=o(g=o(g,v=o(v,m=o(m,l=o(l,g,v,m,n[e],7,-680876936),g,v,n[e+1],12,-389564586),l,g,n[e+2],17,606105819),m,l,n[e+3],22,-1044525330),v=o(v,m=o(m,l=o(l,g,v,m,n[e+4],7,-176418897),g,v,n[e+5],12,1200080426),l,g,n[e+6],17,-1473231341),m,l,n[e+7],22,-45705983),v=o(v,m=o(m,l=o(l,g,v,m,n[e+8],7,1770035416),g,v,n[e+9],12,-1958414417),l,g,n[e+10],17,-42063),m,l,n[e+11],22,-1990404162),v=o(v,m=o(m,l=o(l,g,v,m,n[e+12],7,1804603682),g,v,n[e+13],12,-40341101),l,g,n[e+14],17,-1502002290),m,l,n[e+15],22,1236535329),v=u(v,m=u(m,l=u(l,g,v,m,n[e+1],5,-165796510),g,v,n[e+6],9,-1069501632),l,g,n[e+11],14,643717713),m,l,n[e],20,-373897302),v=u(v,m=u(m,l=u(l,g,v,m,n[e+5],5,-701558691),g,v,n[e+10],9,38016083),l,g,n[e+15],14,-660478335),m,l,n[e+4],20,-405537848),v=u(v,m=u(m,l=u(l,g,v,m,n[e+9],5,568446438),g,v,n[e+14],9,-1019803690),l,g,n[e+3],14,-187363961),m,l,n[e+8],20,1163531501),v=u(v,m=u(m,l=u(l,g,v,m,n[e+13],5,-1444681467),g,v,n[e+2],9,-51403784),l,g,n[e+7],14,1735328473),m,l,n[e+12],20,-1926607734),v=c(v,m=c(m,l=c(l,g,v,m,n[e+5],4,-378558),g,v,n[e+8],11,-2022574463),l,g,n[e+11],16,1839030562),m,l,n[e+14],23,-35309556),v=c(v,m=c(m,l=c(l,g,v,m,n[e+1],4,-1530992060),g,v,n[e+4],11,1272893353),l,g,n[e+7],16,-155497632),m,l,n[e+10],23,-1094730640),v=c(v,m=c(m,l=c(l,g,v,m,n[e+13],4,681279174),g,v,n[e],11,-358537222),l,g,n[e+3],16,-722521979),m,l,n[e+6],23,76029189),v=c(v,m=c(m,l=c(l,g,v,m,n[e+9],4,-640364487),g,v,n[e+12],11,-421815835),l,g,n[e+15],16,530742520),m,l,n[e+2],23,-995338651),v=f(v,m=f(m,l=f(l,g,v,m,n[e],6,-198630844),g,v,n[e+7],10,1126891415),l,g,n[e+14],15,-1416354905),m,l,n[e+5],21,-57434055),v=f(v,m=f(m,l=f(l,g,v,m,n[e+12],6,1700485571),g,v,n[e+3],10,-1894986606),l,g,n[e+10],15,-1051523),m,l,n[e+1],21,-2054922799),v=f(v,m=f(m,l=f(l,g,v,m,n[e+8],6,1873313359),g,v,n[e+15],10,-30611744),l,g,n[e+6],15,-1560198380),m,l,n[e+13],21,1309151649),v=f(v,m=f(m,l=f(l,g,v,m,n[e+4],6,-145523070),g,v,n[e+11],10,-1120210379),l,g,n[e+2],15,718787259),m,l,n[e+9],21,-343485551),l=t(l,i),g=t(g,a),v=t(v,d),m=t(m,h);return[l,g,v,m]}function a(n){var t,r="",e=32*n.length;for(t=0;t<e;t+=8)r+=String.fromCharCode(n[t>>5]>>>t%32&255);return r}function d(n){var t,r=[];for(r[(n.length>>2)-1]=void 0,t=0;t<r.length;t+=1)r[t]=0;var e=8*n.length;for(t=0;t<e;t+=8)r[t>>5]|=(255&n.charCodeAt(t/8))<<t%32;return r}function h(n){return a(i(d(n),8*n.length))}function l(n,t){var r,e,o=d(n),u=[],c=[];for(u[15]=c[15]=void 0,o.length>16&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(d(t)),512+8*t.length),a(i(c.concat(e),640))}function g(n){var t,r,e="";for(r=0;r<n.length;r+=1)t=n.charCodeAt(r),e+="0123456789abcdef".charAt(t>>>4&15)+"0123456789abcdef".charAt(15&t);return e}function v(n){return unescape(encodeURIComponent(n))}function m(n){return h(v(n))}function p(n){return g(m(n))}function s(n,t){return l(v(n),v(t))}function C(n,t){return g(s(n,t))}function A(n,t,r){return t?r?s(t,n):C(t,n):r?m(n):p(n)}"function"==typeof define&&define.amd?define(function(){return A}):"object"==typeof module&&module.exports?module.exports=A:n.md5=A}(this);
//# sourceMappingURL=md5.min.js.map</script>
Map3.0Gadget.xml
包含如下页面:
- MediaWiki:Gadget-leaflet.css
- MediaWiki:Gadget-leaflet.pm.css
- MediaWiki:Gadget-proj4.js
- MediaWiki:Gadget-proj4leaflet.min.js
- MediaWiki:Gadget-Md5.min.js
- MediaWiki:Gadget-Map3.js
- MediaWiki:Gadget-leaflet.js
- MediaWiki:Gadget-leaflet.canvas-markers.js
- MediaWiki:Gadget-leaflet.pm.min.js
- MediaWiki:Gadget-Map3
然后添加下内容至MediaWiki:Gadgets-definition页面:
* Map3[ResourceLoader|rights=edit]|leaflet.css|leaflet.js|leaflet.canvas-markers.js|leaflet.pm.css|leaflet.pm.min.js|proj4.js|proj4leaflet.min.js|Md5.min.js|Map3.js
您必须在目标Wiki上拥有管理员和界面管理员权限才能执行以上两步操作。
第二步:替换底图
为地图添加底图:在widget:Map3/main中寻找方法getTileUrl,将return coords后的链接修改成地图瓦片的保存路径
getTileUrl: function(coords) {
coords = function (coords) {
var y = -coords.y + -1, r = Math.ceil((1 << coords.z - 4)/4 * 10);
return ( -r <= coords.x && coords.x <= r && -r <= y && y <= r &&
{x: coords.x, y: -coords.y + -1, z: coords.z})
}(coords);
return coords ? `https://prod-patch-wiki.biligame.com/res/ys/map2/tiles/${coords.z}/tile-${coords.x}_${coords.y}.png?v=${mapModel.srcVersion()}` :
`https://prod-patch-wiki.biligame.com/res/ys/map/tiles/default.png?v=${mapModel.srcVersion()}`;
},
setGeoData: function () {
mapModel.areaData(JSON.parse($("#mapData #mapAreaData").text().trim()));
// mapModel.routeData(JSON.parse($("#mapData #mapAreaData").text().trim()));
},
例如:
原神的瓦片地址为:https://prod-patch-wiki.biligame.com/res/ys/map2/
只修改路径其他的不要改
如何获得瓦片地图
- 使用瓦片地图制作工具即可,稍后提供一个工具地址。
瓦片地图如何存放
第三步:创建点位
创建地图的对应点位信息。
第四步:输出地图
以原神地图为例
<!--地图必须结构勿动-->
<div id="mapData" style="display:none">
<div id="categoryData">{{:Data:Map/type/json}}</div>
<div id="markerWithInfo">{{#ask:[[~Data:Map/point/*]][[!~*/json]]|link=none|limit=1000|searchlabel=}}, {{#ask:[[~Data:Map/point/*]][[!~*/json]]|link=none|limit=1000|offset=1000|searchlabel=}}</div>
<!--以下部分为地图分区功能,如果不需要分区可以删掉-->
<div id="mapAreaData">
[
{"name":"提瓦特", "icon":"world", "inside":"", "geojson": null, "center": null},
{"name":"蒙德", "icon":"mengde", "inside":"蒙德", "geojson": {{:Data:Map/蒙德.json}}, "center": [19.88871, 4.312327]},
{"name":"璃月", "icon":"liyue", "inside":"璃月", "geojson": {{:Data:Map/璃月.json}}, "center": [-23.182214, -20.965561]},
{"name":"雪山", "icon":"xueshan", "inside":"雪山", "geojson": {{:Data:Map/雪山.json}}, "center": [2.301491, 0.448894]},
{"name":"稻妻", "icon":"daoqi", "inside":"稻妻", "geojson": {{:Data:Map/稻妻.json}}, "center": [-51.085105, 38.289228]}
]
</div><!--分区结束-->
</div>
<div>
{{#widget:Map3/css}}
{{#widget:Map3/icon}}
{{#widget:Map3/mapc}}
{{#widget:Map3/main}}
{{#widget:Md5}}
<div>
<!--地图end-->
替换地图菜单上的logo
widget:Map3/mapc
页面中如下代码替换图片链接即可。
<div class="mapMenu">
<div class="wiki-logo">
<img src="https://patchwiki.biligame.com/resources/assets/images/logo/logo_ys.png?t=2021052411&v=41" alt="">
</div>
如何打点
- 在第三步要定义好所有需要打的点
- 打点教程:Map教程
分区
- 划分区域(如果需要分区功能):教程暂缺
作者
标签
leaflet JAVASCRIPT SMW JQUERY HTML
依赖页面
框架(Widget)
框架(Gadget)
- MediaWiki:Gadget-leaflet.css
- MediaWiki:Gadget-leaflet.pm.css
- MediaWiki:Gadget-proj4.js
- MediaWiki:Gadget-proj4leaflet.min.js
- MediaWiki:Gadget-Md5.min.js
- MediaWiki:Gadget-Map3.js
- MediaWiki:Gadget-leaflet.js
- MediaWiki:Gadget-leaflet.canvas-markers.js
- MediaWiki:Gadget-leaflet.pm.min.js
- MediaWiki:Gadget-Map3
内容
- 详见:Map维护
已使用该功能的页面
更新日志
- 从3.0版本进行的重构
- 重构底层代码
- 重构打点功能
- 新增点位分区
- 新增点位标记状态储存功能