|
|
|
|
|
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1.0"><title>云南4天自驾行程规划 - 交互式地图</title><style>/* required styles */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-pane,
|
|
|
|
|
|
.leaflet-tile,
|
|
|
|
|
|
.leaflet-marker-icon,
|
|
|
|
|
|
.leaflet-marker-shadow,
|
|
|
|
|
|
.leaflet-tile-container,
|
|
|
|
|
|
.leaflet-pane > svg,
|
|
|
|
|
|
.leaflet-pane > canvas,
|
|
|
|
|
|
.leaflet-zoom-box,
|
|
|
|
|
|
.leaflet-image-layer,
|
|
|
|
|
|
.leaflet-layer {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-container {
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tile,
|
|
|
|
|
|
.leaflet-marker-icon,
|
|
|
|
|
|
.leaflet-marker-shadow {
|
|
|
|
|
|
-webkit-user-select: none;
|
|
|
|
|
|
-moz-user-select: none;
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
-webkit-user-drag: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* Prevents IE11 from highlighting tiles in blue */
|
|
|
|
|
|
.leaflet-tile::selection {
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
|
|
|
|
|
|
.leaflet-safari .leaflet-tile {
|
|
|
|
|
|
image-rendering: -webkit-optimize-contrast;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* hack that prevents hw layers "stretching" when loading new tiles */
|
|
|
|
|
|
.leaflet-safari .leaflet-tile-container {
|
|
|
|
|
|
width: 1600px;
|
|
|
|
|
|
height: 1600px;
|
|
|
|
|
|
-webkit-transform-origin: 0 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-marker-icon,
|
|
|
|
|
|
.leaflet-marker-shadow {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
|
|
|
|
|
|
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
|
|
|
|
|
|
.leaflet-container .leaflet-overlay-pane svg {
|
|
|
|
|
|
max-width: none !important;
|
|
|
|
|
|
max-height: none !important;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-container .leaflet-marker-pane img,
|
|
|
|
|
|
.leaflet-container .leaflet-shadow-pane img,
|
|
|
|
|
|
.leaflet-container .leaflet-tile-pane img,
|
|
|
|
|
|
.leaflet-container img.leaflet-image-layer,
|
|
|
|
|
|
.leaflet-container .leaflet-tile {
|
|
|
|
|
|
max-width: none !important;
|
|
|
|
|
|
max-height: none !important;
|
|
|
|
|
|
width: auto;
|
|
|
|
|
|
padding: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-container img.leaflet-tile {
|
|
|
|
|
|
/* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */
|
|
|
|
|
|
mix-blend-mode: plus-lighter;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-container.leaflet-touch-zoom {
|
|
|
|
|
|
-ms-touch-action: pan-x pan-y;
|
|
|
|
|
|
touch-action: pan-x pan-y;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-container.leaflet-touch-drag {
|
|
|
|
|
|
-ms-touch-action: pinch-zoom;
|
|
|
|
|
|
/* Fallback for FF which doesn't support pinch-zoom */
|
|
|
|
|
|
touch-action: none;
|
|
|
|
|
|
touch-action: pinch-zoom;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
|
|
|
|
|
|
-ms-touch-action: none;
|
|
|
|
|
|
touch-action: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-container {
|
|
|
|
|
|
-webkit-tap-highlight-color: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-container a {
|
|
|
|
|
|
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tile {
|
|
|
|
|
|
filter: inherit;
|
|
|
|
|
|
visibility: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tile-loaded {
|
|
|
|
|
|
visibility: inherit;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-zoom-box {
|
|
|
|
|
|
width: 0;
|
|
|
|
|
|
height: 0;
|
|
|
|
|
|
-moz-box-sizing: border-box;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
z-index: 800;
|
|
|
|
|
|
}
|
|
|
|
|
|
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
|
|
|
|
|
|
.leaflet-overlay-pane svg {
|
|
|
|
|
|
-moz-user-select: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-pane { z-index: 400; }
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-tile-pane { z-index: 200; }
|
|
|
|
|
|
.leaflet-overlay-pane { z-index: 400; }
|
|
|
|
|
|
.leaflet-shadow-pane { z-index: 500; }
|
|
|
|
|
|
.leaflet-marker-pane { z-index: 600; }
|
|
|
|
|
|
.leaflet-tooltip-pane { z-index: 650; }
|
|
|
|
|
|
.leaflet-popup-pane { z-index: 700; }
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-map-pane canvas { z-index: 100; }
|
|
|
|
|
|
.leaflet-map-pane svg { z-index: 200; }
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-vml-shape {
|
|
|
|
|
|
width: 1px;
|
|
|
|
|
|
height: 1px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.lvml {
|
|
|
|
|
|
behavior: url(#default#VML);
|
|
|
|
|
|
display: inline-block;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* control positioning */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-control {
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
z-index: 800;
|
|
|
|
|
|
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
|
|
|
|
|
pointer-events: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-top,
|
|
|
|
|
|
.leaflet-bottom {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
z-index: 1000;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-top {
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-right {
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-bottom {
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-left {
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control {
|
|
|
|
|
|
float: left;
|
|
|
|
|
|
clear: both;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-right .leaflet-control {
|
|
|
|
|
|
float: right;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-top .leaflet-control {
|
|
|
|
|
|
margin-top: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-bottom .leaflet-control {
|
|
|
|
|
|
margin-bottom: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-left .leaflet-control {
|
|
|
|
|
|
margin-left: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-right .leaflet-control {
|
|
|
|
|
|
margin-right: 10px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* zoom and fade animations */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-fade-anim .leaflet-popup {
|
|
|
|
|
|
opacity: 0;
|
|
|
|
|
|
-webkit-transition: opacity 0.2s linear;
|
|
|
|
|
|
-moz-transition: opacity 0.2s linear;
|
|
|
|
|
|
transition: opacity 0.2s linear;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
|
|
|
|
|
|
opacity: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-zoom-animated {
|
|
|
|
|
|
-webkit-transform-origin: 0 0;
|
|
|
|
|
|
-ms-transform-origin: 0 0;
|
|
|
|
|
|
transform-origin: 0 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
svg.leaflet-zoom-animated {
|
|
|
|
|
|
will-change: transform;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-zoom-anim .leaflet-zoom-animated {
|
|
|
|
|
|
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
|
|
|
|
|
|
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
|
|
|
|
|
|
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-zoom-anim .leaflet-tile,
|
|
|
|
|
|
.leaflet-pan-anim .leaflet-tile {
|
|
|
|
|
|
-webkit-transition: none;
|
|
|
|
|
|
-moz-transition: none;
|
|
|
|
|
|
transition: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-zoom-anim .leaflet-zoom-hide {
|
|
|
|
|
|
visibility: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* cursors */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-interactive {
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-grab {
|
|
|
|
|
|
cursor: -webkit-grab;
|
|
|
|
|
|
cursor: -moz-grab;
|
|
|
|
|
|
cursor: grab;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-crosshair,
|
|
|
|
|
|
.leaflet-crosshair .leaflet-interactive {
|
|
|
|
|
|
cursor: crosshair;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-popup-pane,
|
|
|
|
|
|
.leaflet-control {
|
|
|
|
|
|
cursor: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-dragging .leaflet-grab,
|
|
|
|
|
|
.leaflet-dragging .leaflet-grab .leaflet-interactive,
|
|
|
|
|
|
.leaflet-dragging .leaflet-marker-draggable {
|
|
|
|
|
|
cursor: move;
|
|
|
|
|
|
cursor: -webkit-grabbing;
|
|
|
|
|
|
cursor: -moz-grabbing;
|
|
|
|
|
|
cursor: grabbing;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* marker & overlays interactivity */
|
|
|
|
|
|
.leaflet-marker-icon,
|
|
|
|
|
|
.leaflet-marker-shadow,
|
|
|
|
|
|
.leaflet-image-layer,
|
|
|
|
|
|
.leaflet-pane > svg path,
|
|
|
|
|
|
.leaflet-tile-container {
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-marker-icon.leaflet-interactive,
|
|
|
|
|
|
.leaflet-image-layer.leaflet-interactive,
|
|
|
|
|
|
.leaflet-pane > svg path.leaflet-interactive,
|
|
|
|
|
|
svg.leaflet-image-layer.leaflet-interactive path {
|
|
|
|
|
|
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
|
|
|
|
|
|
pointer-events: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* visual tweaks */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-container {
|
|
|
|
|
|
background: #ddd;
|
|
|
|
|
|
outline-offset: 1px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-container a {
|
|
|
|
|
|
color: #0078A8;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-zoom-box {
|
|
|
|
|
|
border: 2px dotted #38f;
|
|
|
|
|
|
background: rgba(255,255,255,0.5);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* general typography */
|
|
|
|
|
|
.leaflet-container {
|
|
|
|
|
|
font-family: "Helvetica Neue", Arial, Helvetica, sans-serif;
|
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
|
font-size: 0.75rem;
|
|
|
|
|
|
line-height: 1.5;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* general toolbar styles */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-bar {
|
|
|
|
|
|
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
|
|
|
|
|
|
border-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-bar a {
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border-bottom: 1px solid #ccc;
|
|
|
|
|
|
width: 26px;
|
|
|
|
|
|
height: 26px;
|
|
|
|
|
|
line-height: 26px;
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
color: black;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-bar a,
|
|
|
|
|
|
.leaflet-control-layers-toggle {
|
|
|
|
|
|
background-position: 50% 50%;
|
|
|
|
|
|
background-repeat: no-repeat;
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-bar a:hover,
|
|
|
|
|
|
.leaflet-bar a:focus {
|
|
|
|
|
|
background-color: #f4f4f4;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-bar a:first-child {
|
|
|
|
|
|
border-top-left-radius: 4px;
|
|
|
|
|
|
border-top-right-radius: 4px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-bar a:last-child {
|
|
|
|
|
|
border-bottom-left-radius: 4px;
|
|
|
|
|
|
border-bottom-right-radius: 4px;
|
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-bar a.leaflet-disabled {
|
|
|
|
|
|
cursor: default;
|
|
|
|
|
|
background-color: #f4f4f4;
|
|
|
|
|
|
color: #bbb;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-touch .leaflet-bar a {
|
|
|
|
|
|
width: 30px;
|
|
|
|
|
|
height: 30px;
|
|
|
|
|
|
line-height: 30px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-touch .leaflet-bar a:first-child {
|
|
|
|
|
|
border-top-left-radius: 2px;
|
|
|
|
|
|
border-top-right-radius: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-touch .leaflet-bar a:last-child {
|
|
|
|
|
|
border-bottom-left-radius: 2px;
|
|
|
|
|
|
border-bottom-right-radius: 2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* zoom control */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-control-zoom-in,
|
|
|
|
|
|
.leaflet-control-zoom-out {
|
|
|
|
|
|
font: bold 18px 'Lucida Console', Monaco, monospace;
|
|
|
|
|
|
text-indent: 1px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
|
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* layers control */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-control-layers {
|
|
|
|
|
|
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border-radius: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-layers-toggle {
|
|
|
|
|
|
background-image: url(images/layers.png);
|
|
|
|
|
|
width: 36px;
|
|
|
|
|
|
height: 36px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-retina .leaflet-control-layers-toggle {
|
|
|
|
|
|
background-image: url(images/layers-2x.png);
|
|
|
|
|
|
background-size: 26px 26px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-touch .leaflet-control-layers-toggle {
|
|
|
|
|
|
width: 44px;
|
|
|
|
|
|
height: 44px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-layers .leaflet-control-layers-list,
|
|
|
|
|
|
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
|
|
|
|
|
|
display: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-layers-expanded .leaflet-control-layers-list {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-layers-expanded {
|
|
|
|
|
|
padding: 6px 10px 6px 6px;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-layers-scrollbar {
|
|
|
|
|
|
overflow-y: scroll;
|
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
|
padding-right: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-layers-selector {
|
|
|
|
|
|
margin-top: 2px;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
top: 1px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-layers label {
|
|
|
|
|
|
display: block;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-size: 1.08333em;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-layers-separator {
|
|
|
|
|
|
height: 0;
|
|
|
|
|
|
border-top: 1px solid #ddd;
|
|
|
|
|
|
margin: 5px -10px 5px -6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Default icon URLs */
|
|
|
|
|
|
.leaflet-default-icon-path { /* used only in path-guessing heuristic, see L.Icon.Default */
|
|
|
|
|
|
background-image: url(images/marker-icon.png);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* attribution and scale controls */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-container .leaflet-control-attribution {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.8);
|
|
|
|
|
|
margin: 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-attribution,
|
|
|
|
|
|
.leaflet-control-scale-line {
|
|
|
|
|
|
padding: 0 5px;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
line-height: 1.4;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-attribution a {
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-attribution a:hover,
|
|
|
|
|
|
.leaflet-control-attribution a:focus {
|
|
|
|
|
|
text-decoration: underline;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-attribution-flag {
|
|
|
|
|
|
display: inline !important;
|
|
|
|
|
|
vertical-align: baseline !important;
|
|
|
|
|
|
width: 1em;
|
|
|
|
|
|
height: 0.6669em;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-left .leaflet-control-scale {
|
|
|
|
|
|
margin-left: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-bottom .leaflet-control-scale {
|
|
|
|
|
|
margin-bottom: 5px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-scale-line {
|
|
|
|
|
|
border: 2px solid #777;
|
|
|
|
|
|
border-top: none;
|
|
|
|
|
|
line-height: 1.1;
|
|
|
|
|
|
padding: 2px 5px 1px;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
-moz-box-sizing: border-box;
|
|
|
|
|
|
box-sizing: border-box;
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.8);
|
|
|
|
|
|
text-shadow: 1px 1px #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-scale-line:not(:first-child) {
|
|
|
|
|
|
border-top: 2px solid #777;
|
|
|
|
|
|
border-bottom: none;
|
|
|
|
|
|
margin-top: -2px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
|
|
|
|
|
|
border-bottom: 2px solid #777;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-touch .leaflet-control-attribution,
|
|
|
|
|
|
.leaflet-touch .leaflet-control-layers,
|
|
|
|
|
|
.leaflet-touch .leaflet-bar {
|
|
|
|
|
|
box-shadow: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-touch .leaflet-control-layers,
|
|
|
|
|
|
.leaflet-touch .leaflet-bar {
|
|
|
|
|
|
border: 2px solid rgba(0,0,0,0.2);
|
|
|
|
|
|
background-clip: padding-box;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* popup */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-popup {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
margin-bottom: 20px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-popup-content-wrapper {
|
|
|
|
|
|
padding: 1px;
|
|
|
|
|
|
text-align: left;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-popup-content {
|
|
|
|
|
|
margin: 13px 24px 13px 20px;
|
|
|
|
|
|
line-height: 1.3;
|
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
|
font-size: 1.08333em;
|
|
|
|
|
|
min-height: 1px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-popup-content p {
|
|
|
|
|
|
margin: 17px 0;
|
|
|
|
|
|
margin: 1.3em 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-popup-tip-container {
|
|
|
|
|
|
width: 40px;
|
|
|
|
|
|
height: 20px;
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
margin-top: -1px;
|
|
|
|
|
|
margin-left: -20px;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-popup-tip {
|
|
|
|
|
|
width: 17px;
|
|
|
|
|
|
height: 17px;
|
|
|
|
|
|
padding: 1px;
|
|
|
|
|
|
|
|
|
|
|
|
margin: -10px auto 0;
|
|
|
|
|
|
pointer-events: auto;
|
|
|
|
|
|
|
|
|
|
|
|
-webkit-transform: rotate(45deg);
|
|
|
|
|
|
-moz-transform: rotate(45deg);
|
|
|
|
|
|
-ms-transform: rotate(45deg);
|
|
|
|
|
|
transform: rotate(45deg);
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-popup-content-wrapper,
|
|
|
|
|
|
.leaflet-popup-tip {
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
color: #333;
|
|
|
|
|
|
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-container a.leaflet-popup-close-button {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
border: none;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
width: 24px;
|
|
|
|
|
|
height: 24px;
|
|
|
|
|
|
font: 16px/24px Tahoma, Verdana, sans-serif;
|
|
|
|
|
|
color: #757575;
|
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-container a.leaflet-popup-close-button:hover,
|
|
|
|
|
|
.leaflet-container a.leaflet-popup-close-button:focus {
|
|
|
|
|
|
color: #585858;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-popup-scrolled {
|
|
|
|
|
|
overflow: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-oldie .leaflet-popup-content-wrapper {
|
|
|
|
|
|
-ms-zoom: 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-oldie .leaflet-popup-tip {
|
|
|
|
|
|
width: 24px;
|
|
|
|
|
|
margin: 0 auto;
|
|
|
|
|
|
|
|
|
|
|
|
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
|
|
|
|
|
|
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-oldie .leaflet-control-zoom,
|
|
|
|
|
|
.leaflet-oldie .leaflet-control-layers,
|
|
|
|
|
|
.leaflet-oldie .leaflet-popup-content-wrapper,
|
|
|
|
|
|
.leaflet-oldie .leaflet-popup-tip {
|
|
|
|
|
|
border: 1px solid #999;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* div icon */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-div-icon {
|
|
|
|
|
|
background: #fff;
|
|
|
|
|
|
border: 1px solid #666;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Tooltip */
|
|
|
|
|
|
/* Base styles for the element that has a tooltip */
|
|
|
|
|
|
.leaflet-tooltip {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
padding: 6px;
|
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
border: 1px solid #fff;
|
|
|
|
|
|
border-radius: 3px;
|
|
|
|
|
|
color: #222;
|
|
|
|
|
|
white-space: nowrap;
|
|
|
|
|
|
-webkit-user-select: none;
|
|
|
|
|
|
-moz-user-select: none;
|
|
|
|
|
|
-ms-user-select: none;
|
|
|
|
|
|
user-select: none;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip.leaflet-interactive {
|
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
|
pointer-events: auto;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-top:before,
|
|
|
|
|
|
.leaflet-tooltip-bottom:before,
|
|
|
|
|
|
.leaflet-tooltip-left:before,
|
|
|
|
|
|
.leaflet-tooltip-right:before {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
border: 6px solid transparent;
|
|
|
|
|
|
background: transparent;
|
|
|
|
|
|
content: "";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Directions */
|
|
|
|
|
|
|
|
|
|
|
|
.leaflet-tooltip-bottom {
|
|
|
|
|
|
margin-top: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-top {
|
|
|
|
|
|
margin-top: -6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-bottom:before,
|
|
|
|
|
|
.leaflet-tooltip-top:before {
|
|
|
|
|
|
left: 50%;
|
|
|
|
|
|
margin-left: -6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-top:before {
|
|
|
|
|
|
bottom: 0;
|
|
|
|
|
|
margin-bottom: -12px;
|
|
|
|
|
|
border-top-color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-bottom:before {
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
margin-top: -12px;
|
|
|
|
|
|
margin-left: -6px;
|
|
|
|
|
|
border-bottom-color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-left {
|
|
|
|
|
|
margin-left: -6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-right {
|
|
|
|
|
|
margin-left: 6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-left:before,
|
|
|
|
|
|
.leaflet-tooltip-right:before {
|
|
|
|
|
|
top: 50%;
|
|
|
|
|
|
margin-top: -6px;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-left:before {
|
|
|
|
|
|
right: 0;
|
|
|
|
|
|
margin-right: -12px;
|
|
|
|
|
|
border-left-color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
.leaflet-tooltip-right:before {
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
margin-left: -12px;
|
|
|
|
|
|
border-right-color: #fff;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* Printing */
|
|
|
|
|
|
|
|
|
|
|
|
@media print {
|
|
|
|
|
|
/* Prevent printers from removing background-images of controls. */
|
|
|
|
|
|
.leaflet-control {
|
|
|
|
|
|
-webkit-print-color-adjust: exact;
|
|
|
|
|
|
print-color-adjust: exact;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style><style>:root{--primary:#2d6a4f;--primary-light:#40916c;--primary-dark:#1b4332;--accent:#f4a261;--bg:#f8f9fa;--card-bg:#fff;--text:#2b2d42;--text-light:#6c757d;--shadow:0 2px 8px rgba(0,0,0,.08);--radius:12px;--radius-sm:8px}
|
|
|
|
|
|
*{margin:0;padding:0;box-sizing:border-box}
|
|
|
|
|
|
body{font-family:-apple-system,BlinkMacSystemFont,"Segoe UI","PingFang SC","Hiragino Sans GB","Microsoft YaHei",sans-serif;background:var(--bg);color:var(--text);height:100vh;overflow:hidden;display:flex;flex-direction:column}
|
|
|
|
|
|
.header{background:linear-gradient(135deg,var(--primary-dark),var(--primary));color:#fff;padding:12px 24px;display:flex;align-items:center;justify-content:space-between;box-shadow:0 2px 10px rgba(0,0,0,.15);flex-shrink:0}
|
|
|
|
|
|
.header h1{font-size:18px;font-weight:700;letter-spacing:1px}
|
|
|
|
|
|
.header .subtitle{font-size:12px;opacity:.85;margin-top:2px}
|
|
|
|
|
|
.header-badge{background:var(--accent);color:var(--primary-dark);padding:6px 14px;border-radius:20px;font-size:12px;font-weight:700}
|
|
|
|
|
|
.main-layout{flex:1;display:flex;overflow:hidden}
|
|
|
|
|
|
.left-panel{width:280px;background:var(--card-bg);box-shadow:2px 0 10px rgba(0,0,0,.05);display:flex;flex-direction:column;flex-shrink:0;z-index:10}
|
|
|
|
|
|
.sidebar-header{background:linear-gradient(135deg,var(--primary),var(--primary-light));color:#fff;padding:16px;font-size:14px;font-weight:700}
|
|
|
|
|
|
.sidebar-header small{opacity:.85;font-weight:400;display:block;margin-top:4px;font-size:11px}
|
|
|
|
|
|
.timeline{flex:1;overflow-y:auto;padding:12px 16px}
|
|
|
|
|
|
.timeline-item{display:flex;gap:12px;padding:12px 0;cursor:pointer;transition:all .2s}
|
|
|
|
|
|
.timeline-item:hover{transform:translateX(4px)}
|
|
|
|
|
|
.timeline-item.active .tl-dot{transform:scale(1.3);box-shadow:0 0 0 4px rgba(45,106,79,.2)}
|
|
|
|
|
|
.timeline-item.completed .tl-dot{background:var(--primary);border-color:var(--primary)}
|
|
|
|
|
|
.timeline-item.completed .tl-dot::after{content:"\2713";color:#fff;font-size:10px;display:flex;align-items:center;justify-content:center}
|
|
|
|
|
|
.tl-line{display:flex;flex-direction:column;align-items:center;width:20px;flex-shrink:0}
|
|
|
|
|
|
.tl-dot{width:12px;height:12px;border-radius:50%;border:3px solid var(--primary);background:#fff;position:relative;z-index:1;transition:all .3s}
|
|
|
|
|
|
.tl-connector{flex:1;width:2px;background:linear-gradient(to bottom,var(--primary),#ccc);margin:4px 0}
|
|
|
|
|
|
.tl-connector.passed{background:var(--primary)}
|
|
|
|
|
|
.tl-content{flex:1;min-width:0}
|
|
|
|
|
|
.tl-day{font-size:10px;font-weight:700;color:var(--primary);text-transform:uppercase;letter-spacing:1px;margin-bottom:2px}
|
|
|
|
|
|
.tl-title{font-size:13px;font-weight:600;line-height:1.3}
|
|
|
|
|
|
.tl-meta{font-size:10px;color:var(--text-light);margin-top:4px;display:flex;gap:8px}
|
|
|
|
|
|
.nav-controls{padding:12px 16px;border-top:1px solid #eee;display:flex;gap:8px;flex-shrink:0}
|
|
|
|
|
|
.nav-btn{flex:1;padding:10px 12px;border:none;border-radius:var(--radius-sm);font-size:13px;font-weight:600;cursor:pointer;transition:all .2s;display:flex;align-items:center;justify-content:center;gap:6px}
|
|
|
|
|
|
.nav-btn.prev{background:#f0f0f0;color:var(--text)}.nav-btn.prev:hover{background:#e0e0e0}
|
|
|
|
|
|
.nav-btn.next{background:linear-gradient(135deg,var(--primary),var(--primary-light));color:#fff}.nav-btn.next:hover{opacity:.9}
|
|
|
|
|
|
.nav-btn:disabled{opacity:.4;cursor:not-allowed;transform:none!important}
|
|
|
|
|
|
.middle-panel{flex:1;overflow-y:auto;padding:24px;background:var(--bg)}
|
|
|
|
|
|
.detail-hero{height:200px;background-size:cover;background-position:center;border-radius:var(--radius);position:relative;display:flex;align-items:flex-end;margin-bottom:20px;box-shadow:var(--shadow)}
|
|
|
|
|
|
.detail-hero::after{content:"";position:absolute;bottom:0;left:0;right:0;height:60%;background:linear-gradient(transparent,rgba(0,0,0,.75))}
|
|
|
|
|
|
.detail-hero-content{position:relative;z-index:1;padding:20px;color:#fff;width:100%}
|
|
|
|
|
|
.detail-day-badge{display:inline-block;background:var(--accent);color:var(--primary-dark);padding:4px 12px;border-radius:20px;font-size:12px;font-weight:700;margin-bottom:6px}
|
|
|
|
|
|
.detail-hero-content h2{font-size:22px;font-weight:800;margin-bottom:4px}
|
|
|
|
|
|
.detail-hero-content .route-info{font-size:13px;opacity:.9}
|
|
|
|
|
|
.detail-stats{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;margin-bottom:20px}
|
|
|
|
|
|
.stat-card{background:var(--card-bg);border-radius:var(--radius-sm);padding:14px;text-align:center;box-shadow:var(--shadow)}
|
|
|
|
|
|
.stat-card .stat-icon{font-size:20px;margin-bottom:4px}
|
|
|
|
|
|
.stat-card .stat-value{font-size:16px;font-weight:700;color:var(--primary)}
|
|
|
|
|
|
.stat-card .stat-label{font-size:11px;color:var(--text-light);margin-top:2px}
|
|
|
|
|
|
.detail-section{background:var(--card-bg);border-radius:var(--radius);padding:16px;margin-bottom:16px;box-shadow:var(--shadow)}
|
|
|
|
|
|
.detail-section h3{font-size:15px;font-weight:700;margin-bottom:10px;display:flex;align-items:center;gap:8px;color:var(--primary-dark)}
|
|
|
|
|
|
.detail-section h3::before{content:"";width:3px;height:16px;background:var(--accent);border-radius:2px}
|
|
|
|
|
|
.timeline-detail{display:flex;flex-direction:column;gap:8px}
|
|
|
|
|
|
.timeline-detail-item{display:flex;gap:10px;padding:8px;background:#f8f9fa;border-radius:var(--radius-sm);font-size:13px}
|
|
|
|
|
|
.timeline-detail-item .tdi-time{font-weight:700;color:var(--primary);white-space:nowrap;min-width:45px;font-size:12px}
|
|
|
|
|
|
.food-tags{display:flex;flex-wrap:wrap;gap:8px}
|
|
|
|
|
|
.food-tag{background:linear-gradient(135deg,#fff3e0,#ffe0b2);color:#e65100;padding:6px 14px;border-radius:20px;font-size:12px;font-weight:600}
|
|
|
|
|
|
.gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
|
|
|
|
|
|
.gallery-item{height:120px;border-radius:var(--radius-sm);overflow:hidden;background:linear-gradient(135deg,#e8f5e9,#c8e6c9);transition:transform .2s;cursor:pointer}
|
|
|
|
|
|
.gallery-item:hover{transform:scale(1.03)}
|
|
|
|
|
|
.gallery-item img{width:100%;height:100%;object-fit:cover}
|
|
|
|
|
|
.hotel-card{background:linear-gradient(135deg,#e8f5e9,#c8e6c9);border-radius:var(--radius-sm);padding:12px;display:flex;align-items:center;gap:12px}
|
|
|
|
|
|
.hotel-card .hotel-text{font-size:13px;line-height:1.5}
|
|
|
|
|
|
.hotel-card .hotel-text strong{color:var(--primary-dark)}
|
|
|
|
|
|
.tips-box{background:linear-gradient(135deg,#fff3cd,#ffeaa7);border-left:4px solid var(--accent);border-radius:0 var(--radius-sm) var(--radius-sm) 0;padding:12px;font-size:12px;line-height:1.6;color:#856404}
|
|
|
|
|
|
.right-panel{width:50%;position:relative;flex-shrink:0;border-left:2px solid #eee}
|
|
|
|
|
|
#map{width:100%;height:100%;z-index:1}
|
|
|
|
|
|
.marker-pin{width:36px;height:36px;border-radius:50% 50% 50% 0;transform:rotate(-45deg);display:flex;align-items:center;justify-content:center;box-shadow:0 3px 8px rgba(0,0,0,.25);cursor:pointer;transition:transform .2s}
|
|
|
|
|
|
.marker-pin:hover{transform:rotate(-45deg) scale(1.15)}
|
|
|
|
|
|
.marker-pin span{transform:rotate(45deg);color:#fff;font-weight:800;font-size:13px}
|
|
|
|
|
|
.marker-pin.d0{background:#6c757d}.marker-pin.d1{background:#2196F3}.marker-pin.d2{background:#4CAF50}.marker-pin.d3{background:#FF9800}.marker-pin.d4{background:#E91E63}
|
|
|
|
|
|
.marker-label{background:#fff;padding:2px 8px;border-radius:4px;font-size:11px;font-weight:700;box-shadow:0 1px 4px rgba(0,0,0,.15);white-space:nowrap;margin-top:6px}
|
|
|
|
|
|
.car-marker{z-index:1000!important}
|
|
|
|
|
|
.car-marker .car-inner{font-size:28px;filter:drop-shadow(0 2px 4px rgba(0,0,0,.3));animation:carBounce 1.5s ease infinite}
|
|
|
|
|
|
@keyframes carBounce{0%,100%{transform:translateY(0)}50%{transform:translateY(-3px)}}
|
|
|
|
|
|
.loading-overlay{position:fixed;top:0;left:0;right:0;bottom:0;z-index:9999;background:#1b4332;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#fff;transition:opacity .5s}
|
|
|
|
|
|
.loading-overlay.hidden{opacity:0;pointer-events:none}
|
|
|
|
|
|
.loading-spinner{width:40px;height:40px;border:3px solid rgba(255,255,255,.2);border-top-color:var(--accent);border-radius:50%;animation:spin 1s linear infinite;margin-bottom:16px}
|
|
|
|
|
|
@keyframes spin{to{transform:rotate(360deg)}}
|
|
|
|
|
|
@media(max-width:1024px){.right-panel{width:40%}.middle-panel{padding:16px}}
|
|
|
|
|
|
@media(max-width:768px){.main-layout{flex-direction:column-reverse}.right-panel{width:100%;height:35vh;border-left:none;border-top:2px solid #eee}.left-panel{width:100%;height:25vh;flex-direction:row}.sidebar-header{display:none}.timeline{flex-direction:row;overflow-x:auto;overflow-y:hidden;padding:8px}.timeline-item{flex-direction:column;align-items:center;gap:4px;padding:8px 16px}.tl-line{width:100%;height:2px;flex-direction:row}.tl-connector{height:2px;width:20px;margin:0 4px}.tl-connector.passed{background:var(--primary)}.tl-content{text-align:center}.middle-panel{height:40vh}}
|
|
|
|
|
|
</style><script>/* @preserve
|
|
|
|
|
|
* Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
|
|
|
|
|
|
* (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
|
|
|
|
|
|
*/
|
|
|
|
|
|
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).leaflet={})}(this,function(t){"use strict";function l(t){for(var e,i,n=1,o=arguments.length;n<o;n++)for(e in i=arguments[n])t[e]=i[e];return t}var R=Object.create||function(t){return N.prototype=t,new N};function N(){}function a(t,e){var i,n=Array.prototype.slice;return t.bind?t.bind.apply(t,n.call(arguments,1)):(i=n.call(arguments,2),function(){return t.apply(e,i.length?i.concat(n.call(arguments)):arguments)})}var D=0;function h(t){return"_leaflet_id"in t||(t._leaflet_id=++D),t._leaflet_id}function j(t,e,i){var n,o,s=function(){n=!1,o&&(r.apply(i,o),o=!1)},r=function(){n?o=arguments:(t.apply(i,arguments),setTimeout(s,e),n=!0)};return r}function H(t,e,i){var n=e[1],e=e[0],o=n-e;return t===n&&i?t:((t-e)%o+o)%o+e}function u(){return!1}function i(t,e){return!1===e?t:(e=Math.pow(10,void 0===e?6:e),Math.round(t*e)/e)}function W(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}function F(t){return W(t).split(/\s+/)}function c(t,e){for(var i in Object.prototype.hasOwnProperty.call(t,"options")||(t.options=t.options?R(t.options):{}),e)t.options[i]=e[i];return t.options}function U(t,e,i){var n,o=[];for(n in t)o.push(encodeURIComponent(i?n.toUpperCase():n)+"="+encodeURIComponent(t[n]));return(e&&-1!==e.indexOf("?")?"&":"?")+o.join("&")}var V=/\{ *([\w_ -]+) *\}/g;function q(t,i){return t.replace(V,function(t,e){e=i[e];if(void 0===e)throw new Error("No value provided for variable "+t);return e="function"==typeof e?e(i):e})}var d=Array.isArray||function(t){return"[object Array]"===Object.prototype.toString.call(t)};function G(t,e){for(var i=0;i<t.length;i++)if(t[i]===e)return i;return-1}var K="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";function Y(t){return window["webkit"+t]||window["moz"+t]||window["ms"+t]}var X=0;function J(t){var e=+new Date,i=Math.max(0,16-(e-X));return X=e+i,window.setTimeout(t,i)}var $=window.requestAnimationFrame||Y("RequestAnimationFrame")||J,Q=window.cancelAnimationFrame||Y("CancelAnimationFrame")||Y("CancelRequestAnimationFrame")||function(t){window.clearTimeout(t)};function x(t,e,i){if(!i||$!==J)return $.call(window,a(t,e));t.call(e)}function r(t){t&&Q.call(window,t)}var tt={__proto__:null,extend:l,create:R,bind:a,get lastId(){return D},stamp:h,throttle:j,wrapNum:H,falseFn:u,formatNum:i,trim:W,splitWords:F,setOptions:c,getParamString:U,template:q,isArray:d,indexOf:G,emptyImageUrl:K,requestFn:$,cancelFn:Q,requestAnimFrame:x,cancelAnimFrame:r};function et(){}et.extend=function(t){function e(){c(this),this.initialize&&this.initialize.apply(this,arguments),this.callInitHooks()}var i,n=e.__super__=this.prototype,o=R(n);for(i in(o.constructor=e).prototype=o,this)Object.prototype.hasOwnProperty.call(this,i)&&"prototype"!==i&&"__super__"!==i&&(e[i]=this[i]);if(t.statics&&l(e,t.statics),t.includes){var s=t.includes;if("undefined"!=typeof L&&L&&L.Mixin){s=d(s)?s:[s];for(var r=0;r<s.length;r++)s[r]===L.Mixin.Events&&console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.",(new Error).stack)}l.apply(null,[o].concat(t.includes))}return l(o,t),delete o.statics,delete o.includes,o.options&&(o.options=n.options?R(n.options):{},l(o.options,t.options)),o._initHooks=[],o.callInitHooks=function(){if(!this._initHooksCalled){n.callInitHooks&&n.callInitHooks.call(this),this._initHooksCalled=!0;for(var t=0,e=o._initHooks.length;t<e;t++)o._initHooks[t].call(this)}},e},et.include=function(t){var e=this.prototype.options;return l(this.prototype,t),t.options&&(this.prototype.options=e,this.mergeOptions(t.options)),this},et.mergeOptions=function(t){return l(this.prototype.options,t),this},et.addInitHook=function(t){var e=Array.prototype.slice.call(arguments,1),i="function"==typeof t?t:function(){this[t].apply(this,e)};return this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(i),this};var e={on:function
|
|
|
|
|
|
//# sourceMappingURL=leaflet.js.map</script><style>.loading-overlay{position:fixed;top:0;left:0;right:0;bottom:0;z-index:9999;background:#1b4332;display:flex;flex-direction:column;align-items:center;justify-content:center;color:#fff;transition:opacity .5s}.loading-overlay.hidden{opacity:0;pointer-events:none}.loading-spinner{width:40px;height:40px;border:3px solid rgba(255,255,255,.2);border-top-color:#f4a261;border-radius:50%;animation:spin 1s linear infinite;margin-bottom:16px}@keyframes spin{to{transform:rotate(360deg)}}.loading-error{display:none;background:rgba(231,111,81,.9);padding:20px 30px;border-radius:12px;max-width:500px;text-align:center;margin-top:20px}#map{background:linear-gradient(135deg,#e8f5e9 0%,#c8e6c9 100%)}</style></head><body><div class="loading-overlay" id="loadingOverlay"><div class="loading-spinner"></div><div class="loading-text" style="font-size:18px;margin-bottom:8px">正在加载地图...</div><div class="loading-sub" style="font-size:13px;opacity:.7">请稍候</div><div class="loading-error" id="loadError"><strong>⚠️ 地图加载失败</strong><br>请检查网络或稍后重试。</div></div><div class="header"><div><h1>🚗 云南4天自驾行程规划</h1><div class="subtitle">北京出发 · 9月 · 昆明落地自驾</div></div><div class="header-badge">总里程 ~1450km</div></div><div class="main-layout"><div class="left-panel"><div class="sidebar-header">📋 行程时间线<small>点击节点切换,或用按钮逐步前进</small></div><div class="timeline" id="timeline"></div><div class="nav-controls"><button class="nav-btn prev" id="btnPrev">← 上一站</button><button class="nav-btn next" id="btnNext">下一站 →</button></div></div><div class="middle-panel" id="middlePanel"></div><div class="right-panel"><div id="map"></div></div></div><script>var LOCATIONS=[{"id": 0, "name": "昆明(起点)", "lat": 25.04, "lng": 102.71, "day": "出发日", "badge": "START", "km": "0km", "driveTime": "—", "desc": "北京飞抵昆明,取车出发", "icon": "🏙️", "images": ["https://pics.unsplash.com/photo-1590736704720-f4e64e79e5e6?w=400&h=300&fit=crop", "https://pics.unsplash.com/photo-1598257006447-86c2f5e9b349?w=400&h=300&fit=crop", "https://pics.unsplash.com/photo-1603921313555-42b4598d3b77?w=400&h=300&fit=crop"], "heroImage": "https://pics.unsplash.com/photo-1590736704720-f4e64e79e5e6?w=800&h=400&fit=crop", "schedule": [{"time": "上午", "content": "北京飞昆明(约3.5小时),抵达长水机场"}, {"time": "中午", "content": "机场取车(推荐SUV),检查车况"}, {"time": "下午", "content": "昆明市区:翠湖公园、斗南花市"}, {"time": "晚上", "content": "南强街夜市吃野生菌火锅"}], "foods": ["野生菌火锅", "过桥米线", "官渡粑粑", "鲜花饼"], "hotel": "昆明市区酒店(翠湖或南屏街附近)", "tips": "取车拍照记录车况,下载离线地图。"}, {"id": 1, "name": "普者黑", "lat": 24.12, "lng": 104.12, "day": "第一天", "badge": "DAY 1", "km": "280km", "driveTime": "约3.5h", "desc": "喀斯特山水田园,三生三世取景地", "icon": "🏞️", "images": ["https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=400&h=300&fit=crop", "https://images.unsplash.com/photo-1470071459604-3b5ec3a7fe05?w=400&h=300&fit=crop", "https://images.unsplash.com/photo-1441974231531-c6227db76b6e?w=400&h=300&fit=crop"], "heroImage": "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=800&h=400&fit=crop", "schedule": [{"time": "08:00", "content": "昆明出发,沿广昆高速向东南"}, {"time": "11:30", "content": "抵达普者黑,入住仙人洞村民宿"}, {"time": "13:00", "content": "午餐:荷花宴、荷叶鸡"}, {"time": "14:30", "content": "青龙山观景台,俯瞰喀斯特峰林"}, {"time": "16:00", "content": "天鹅湖湿地、三生三世取景地拍照"}, {"time": "18:00", "content": "仙人洞村漫步看日落"}, {"time": "19:30", "content": "晚餐后休息"}], "foods": ["荷花宴", "荷叶鸡", "野生鱼", "酸汤鱼", "花糯米饭"], "hotel": "普者黑<EFBFBD>
|
|
|
|
|
|
var currentStep=0,map,carMarker,routeLine,markers=[],routeLineLayer,isMapInit=false;
|
|
|
|
|
|
var isAnimating = false;
|
|
|
|
|
|
var animationFrameId = null;
|
|
|
|
|
|
|
|
|
|
|
|
function initMap(){
|
|
|
|
|
|
if(isMapInit) return;
|
|
|
|
|
|
try {
|
|
|
|
|
|
map=L.map("map",{center:[23.8,101.5],zoom:8,zoomControl:true,attributionControl:false});
|
|
|
|
|
|
|
|
|
|
|
|
// Tiles
|
|
|
|
|
|
var gaodeUrl = 'https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}';
|
|
|
|
|
|
var osmUrl = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png';
|
|
|
|
|
|
|
|
|
|
|
|
routeLineLayer = L.tileLayer(gaodeUrl, {subdomains:['1','2','3','4'], maxZoom:18}).addTo(map);
|
|
|
|
|
|
var tileFailed = false;
|
|
|
|
|
|
routeLineLayer.on('tileerror', function() {
|
|
|
|
|
|
if (!tileFailed) {
|
|
|
|
|
|
tileFailed = true;
|
|
|
|
|
|
map.removeLayer(routeLineLayer);
|
|
|
|
|
|
L.tileLayer(osmUrl, {subdomains:['a','b','c'], maxZoom:18}).addTo(map);
|
|
|
|
|
|
setTimeout(function(){ map.invalidateSize(); }, 300);
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
L.control.zoom({position:"topright"}).addTo(map);
|
|
|
|
|
|
LOCATIONS.forEach(function(loc,i){
|
|
|
|
|
|
var pinIcon=L.divIcon({className:"",html:'<div class="marker-pin d'+loc.id+'"><span>'+loc.id+'</span></div><div class="marker-label">'+loc.icon+' '+loc.name+'</div>',iconSize:[60,56],iconAnchor:[30,50]});
|
|
|
|
|
|
var m=L.marker([loc.lat,loc.lng],{icon:pinIcon}).addTo(map);
|
|
|
|
|
|
(function(idx){m.on("click",function(){driveCarTo(idx);});})(i);
|
|
|
|
|
|
markers.push(m);
|
|
|
|
|
|
});
|
|
|
|
|
|
var carIcon=L.divIcon({className:"car-marker",html:'<div class="car-inner">🚗</div>',iconSize:[36,36],iconAnchor:[18,18]});
|
|
|
|
|
|
carMarker=L.marker([LOCATIONS[0].lat,LOCATIONS[0].lng],{icon:carIcon,zIndexOffset:1000}).addTo(map);
|
|
|
|
|
|
drawRoute();
|
|
|
|
|
|
isMapInit = true;
|
|
|
|
|
|
setTimeout(function(){ map.invalidateSize(); }, 100);
|
|
|
|
|
|
updateButtons();
|
|
|
|
|
|
} catch(e) {
|
|
|
|
|
|
console.error("Map init failed:", e);
|
|
|
|
|
|
isMapInit = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function drawRoute(){
|
|
|
|
|
|
if(routeLine)map.removeLayer(routeLine);
|
|
|
|
|
|
var coords=LOCATIONS.map(function(l){return[l.lat,l.lng];});
|
|
|
|
|
|
routeLine=L.polyline(coords,{color:"#2d6a4f",weight:4,opacity:0.7,dashArray:"10,8"}).addTo(map);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateButtons(){
|
|
|
|
|
|
document.getElementById("btnPrev").disabled=(currentStep===0 || isAnimating);
|
|
|
|
|
|
document.getElementById("btnNext").disabled=(currentStep>=LOCATIONS.length-1 || isAnimating);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Animation logic: FIXED 1.5s TOTAL
|
|
|
|
|
|
function driveCarTo(targetIdx) {
|
|
|
|
|
|
if (isAnimating) return;
|
|
|
|
|
|
if (targetIdx === currentStep) return;
|
|
|
|
|
|
if (animationFrameId) cancelAnimationFrame(animationFrameId);
|
|
|
|
|
|
|
|
|
|
|
|
isAnimating = true;
|
|
|
|
|
|
updateButtons();
|
|
|
|
|
|
|
|
|
|
|
|
var direction = targetIdx > currentStep ? 1 : -1;
|
|
|
|
|
|
var totalSegments = Math.abs(targetIdx - currentStep);
|
|
|
|
|
|
|
|
|
|
|
|
// TIME CALCULATION
|
|
|
|
|
|
// If 1 segment: 1.5s.
|
|
|
|
|
|
// If multiple segments: Total 1.5s including 0.1s pause between segments.
|
|
|
|
|
|
var driveTime = 1.5;
|
|
|
|
|
|
if (totalSegments > 1) {
|
|
|
|
|
|
var pauseTime = 0.1;
|
|
|
|
|
|
// (TotalTime - TotalPause) / Segments
|
|
|
|
|
|
driveTime = (1.5 - pauseTime * (totalSegments - 1)) / totalSegments;
|
|
|
|
|
|
driveTime = Math.max(0.2, driveTime); // Minimum 0.2s per segment
|
|
|
|
|
|
}
|
|
|
|
|
|
var durationMs = driveTime * 1000;
|
|
|
|
|
|
|
|
|
|
|
|
function nextSegment() {
|
|
|
|
|
|
var nextIdx = currentStep + direction;
|
|
|
|
|
|
if (nextIdx < 0 || nextIdx >= LOCATIONS.length) {
|
|
|
|
|
|
isAnimating = false;
|
|
|
|
|
|
updateButtons();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
var startLoc = LOCATIONS[currentStep];
|
|
|
|
|
|
var endLoc = LOCATIONS[nextIdx];
|
|
|
|
|
|
|
|
|
|
|
|
// 1. Animate Map
|
|
|
|
|
|
map.flyTo([endLoc.lat, endLoc.lng], 8, {duration: driveTime});
|
|
|
|
|
|
|
|
|
|
|
|
// 2. Animate Car Marker (Linear Interpolation)
|
|
|
|
|
|
var startTime = performance.now();
|
|
|
|
|
|
var startLat = startLoc.lat, startLng = startLoc.lng;
|
|
|
|
|
|
var endLat = endLoc.lat, endLng = endLoc.lng;
|
|
|
|
|
|
|
|
|
|
|
|
function driveFrame(currentTime) {
|
|
|
|
|
|
var elapsed = currentTime - startTime;
|
|
|
|
|
|
var t = Math.min(elapsed / durationMs, 1);
|
|
|
|
|
|
|
|
|
|
|
|
var cLat = startLat + (endLat - startLat) * t;
|
|
|
|
|
|
var cLng = startLng + (endLng - startLng) * t;
|
|
|
|
|
|
|
|
|
|
|
|
carMarker.setLatLng([cLat, cLng]);
|
|
|
|
|
|
|
|
|
|
|
|
if (t < 1) {
|
|
|
|
|
|
animationFrameId = requestAnimationFrame(driveFrame);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// Arrived at waypoint
|
|
|
|
|
|
currentStep = nextIdx;
|
|
|
|
|
|
updateTimeline();
|
|
|
|
|
|
updateMiddlePanel(currentStep);
|
|
|
|
|
|
updateButtons();
|
|
|
|
|
|
|
|
|
|
|
|
// Continue or stop?
|
|
|
|
|
|
if (currentStep !== targetIdx) {
|
|
|
|
|
|
// Pause briefly then continue
|
|
|
|
|
|
setTimeout(nextSegment, 100); // 0.1s pause
|
|
|
|
|
|
} else {
|
|
|
|
|
|
isAnimating = false;
|
|
|
|
|
|
updateButtons();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
animationFrameId = requestAnimationFrame(driveFrame);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nextSegment();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateTimeline(){
|
|
|
|
|
|
var tl=document.getElementById("timeline");
|
|
|
|
|
|
var html="";
|
|
|
|
|
|
LOCATIONS.forEach(function(loc,i){
|
|
|
|
|
|
var cls=i===currentStep?"active":(i<currentStep?"completed":"");
|
|
|
|
|
|
var connCls=i<currentStep?" passed":"";
|
|
|
|
|
|
html+='<div class="timeline-item '+cls+'" data-idx="'+i+'">';
|
|
|
|
|
|
html+='<div class="tl-line"><div class="tl-dot"></div>';
|
|
|
|
|
|
if(i<LOCATIONS.length-1)html+='<div class="tl-connector'+connCls+'"></div>';
|
|
|
|
|
|
html+='</div>';
|
|
|
|
|
|
html+='<div class="tl-content"><div class="tl-day">'+loc.day+'</div>';
|
|
|
|
|
|
html+='<div class="tl-title">'+loc.icon+' '+loc.name+'</div>';
|
|
|
|
|
|
html+='<div class="tl-meta"><span>🚗 '+loc.km+'</span><span>⏱️ '+loc.driveTime+'</span></div>';
|
|
|
|
|
|
html+='</div></div>';
|
|
|
|
|
|
});
|
|
|
|
|
|
tl.innerHTML=html;
|
|
|
|
|
|
tl.querySelectorAll(".timeline-item").forEach(function(el){
|
|
|
|
|
|
el.addEventListener("click",function(){driveCarTo(parseInt(this.getAttribute("data-idx")));});
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function updateMiddlePanel(idx){
|
|
|
|
|
|
var loc=LOCATIONS[idx];
|
|
|
|
|
|
var mp=document.getElementById("middlePanel");
|
|
|
|
|
|
var h="";
|
|
|
|
|
|
h+='<div class="detail-hero" style="background-image:url(\''+loc.heroImage+'\'); background-color:#2d6a4f;">';
|
|
|
|
|
|
h+='<div class="detail-hero-content"><span class="detail-day-badge">'+loc.badge+'</span>';
|
|
|
|
|
|
h+='<h2>'+loc.icon+' '+loc.name+'</h2><div class="route-info">'+loc.desc+'</div></div></div>';
|
|
|
|
|
|
h+='<div class="detail-stats">';
|
|
|
|
|
|
h+='<div class="stat-card"><div class="stat-icon">🚗</div><div class="stat-value">'+loc.km+'</div><div class="stat-label">行驶里程</div></div>';
|
|
|
|
|
|
h+='<div class="stat-card"><div class="stat-icon">⏱️</div><div class="stat-value">'+loc.driveTime+'</div><div class="stat-label">驾驶时间</div></div>';
|
|
|
|
|
|
h+='<div class="stat-card"><div class="stat-icon">📍</div><div class="stat-value">D'+loc.id+'</div><div class="stat-label">第几天</div></div>';
|
|
|
|
|
|
h+='</div>';
|
|
|
|
|
|
h+='<div class="detail-section"><h3>📅 行程安排</h3><div class="timeline-detail">';
|
|
|
|
|
|
loc.schedule.forEach(function(s){
|
|
|
|
|
|
h+='<div class="timeline-detail-item"><span class="tdi-time">'+s.time+'</span><span class="tdi-content">'+s.content+'</span></div>';
|
|
|
|
|
|
});
|
|
|
|
|
|
h+='</div></div>';
|
|
|
|
|
|
h+='<div class="detail-section"><h3>🍽️ 美食推荐</h3><div class="food-tags">';
|
|
|
|
|
|
loc.foods.forEach(function(f){h+='<span class="food-tag">'+f+'</span>';});
|
|
|
|
|
|
h+='</div></div>';
|
|
|
|
|
|
h+='<div class="detail-section"><h3>📸 风景美图</h3><div class="gallery">';
|
|
|
|
|
|
loc.images.forEach(function(img){
|
|
|
|
|
|
h+='<div class="gallery-item"><img src="'+img+'" alt="风景" loading="lazy" onerror="this.style.display=\'none\';this.parentElement.style.background=\'linear-gradient(135deg,#a8e6cf,#dcedc1)\';this.parentElement.innerHTML+=\'<span style=\\\'position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);font-size:24px;\\\'>📷</span>\'"></div>';
|
|
|
|
|
|
});
|
|
|
|
|
|
h+='</div></div>';
|
|
|
|
|
|
h+='<div class="detail-section"><h3>🏨 住宿推荐</h3><div class="hotel-card">';
|
|
|
|
|
|
h+='<div class="hotel-icon">🛏️</div><div class="hotel-text"><strong>'+loc.hotel+'</strong></div>';
|
|
|
|
|
|
h+='</div></div>';
|
|
|
|
|
|
h+='<div class="detail-section"><h3>💡 注意事项</h3><div class="tips-box">'+loc.tips+'</div></div>';
|
|
|
|
|
|
mp.innerHTML=h;
|
|
|
|
|
|
mp.scrollTop = 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
document.getElementById("btnPrev").addEventListener("click",function(){driveCarTo(currentStep-1);});
|
|
|
|
|
|
document.getElementById("btnNext").addEventListener("click",function(){driveCarTo(currentStep+1);});
|
|
|
|
|
|
|
|
|
|
|
|
document.addEventListener("keydown",function(e){
|
|
|
|
|
|
if(e.key==="ArrowRight"||e.key==="ArrowDown"){e.preventDefault();driveCarTo(currentStep+1);}
|
|
|
|
|
|
if(e.key==="ArrowLeft"||e.key==="ArrowUp"){e.preventDefault();driveCarTo(currentStep-1);}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
if(document.readyState === 'loading'){
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', function(){
|
|
|
|
|
|
initMap();
|
|
|
|
|
|
updateTimeline();
|
|
|
|
|
|
updateMiddlePanel(0);
|
|
|
|
|
|
hideLoading();
|
|
|
|
|
|
});
|
|
|
|
|
|
} else {
|
|
|
|
|
|
initMap();
|
|
|
|
|
|
updateTimeline();
|
|
|
|
|
|
updateMiddlePanel(0);
|
|
|
|
|
|
hideLoading();
|
|
|
|
|
|
}
|
|
|
|
|
|
</script></body></html>
|