公司网站上要放一个地图展示位置,"联系我们"页面经常用,但地图一加载就是几百KB的JS,首页打开慢了2秒,客户还没看到地址就走了。这个问题其实用展开收起+懒加载两步就能解决——平时只显示一个"查看地图"按钮,客户点了才加载地图,展开过程还有平滑动画。下面把完整的实现方式拆开说,从纯CSS动画到地图API调用,每一步都有代码可以直接用。
地图展开组件的三个核心问题:①展开动画怎么做才丝滑(不用display:none) → max-height + transition;②地图什么时候加载(不让首页变慢) → 点击展开时才new Map(),懒初始化;③手机上看会不会变形 → 宽度100% + touchZoom + CSS媒体查询适配。
一、先搭HTML骨架,一个按钮一个容器
HTML结构只需要两样东西:一个触发按钮,一个装地图的div。地图容器初始是折叠隐藏状态。
<!-- 触发按钮 --><button id="mapToggle" onclick="toggleMap()">查看公司地图位置 ▼</button><!-- 地图容器,初始折叠 --><div id="mapWrapper" class="map-collapsed"><div id="baiduMap" style="width: 100%; height: 400px;"></div></div>
二、核心动画:四行CSS搞定平滑展开
这里有个容易踩的坑:如果直接用 display:none ↔ display:block 切换,浏览器不会做过渡动画,因为display属性不参与transition。正确的做法是用 max-height + overflow:hidden 组合。
/* ===== 核心四行CSS ===== */.map-collapsed {max-height: 0; /* 折叠状态高度为0 */overflow: hidden; /* 隐藏超出部分 */transition: max-height 0.5s ease-in-out; /* 过渡动画 */}.map-expanded {max-height: 600px; /* 展开后最大高度,要大于地图实际高度 */}展开高度怎么设?你的地图如果高400px,就把max-height设成500~600px,留点余量给padding和margin。设太大(比如9999px)会导致动画前段看不到内容、后段突然结束,体验不好。

三、JavaScript:点击展开、加载地图、收起还原
JS部分做三件事:切换CSS类名触发动画、地图只初始化一次、收起时隐藏。
let mapInstance = null; // 地图实例,全局存一份let mapLoaded = false; // 标记地图是否已加载过let isExpanded = false; // 当前展开状态function toggleMap() {const wrapper = document.getElementById('mapWrapper');const btn = document.getElementById('mapToggle');if (!isExpanded) {// 展开wrapper.classList.remove('map-collapsed');wrapper.classList.add('map-expanded');btn.innerHTML = '收起地图 ▲';// 地图只加载一次if (!mapLoaded) {initBaiduMap();mapLoaded = true;}isExpanded = true;} else {// 收起wrapper.classList.remove('map-expanded');wrapper.classList.add('map-collapsed');btn.innerHTML = '查看公司地图位置 ▼';isExpanded = false;}}
为什么用mapLoaded标记?如果不加这个标记,每次展开都重新new一个地图,第二次展开就会报错——div里已经有一个地图实例了,再往里塞一个会冲突。所以地图初始化只做一次,后面展开收起只是CSS显隐。
四、加载百度地图API:动态插入script标签
地图的JS SDK文件有几百KB,不要在页面加载时就引入。点击展开时才动态创建script标签加载,这才是真正的按需加载。
function initBaiduMap() {// 动态加载百度地图JSconst script = document.createElement('script');script.src = 'https://api.map.baidu.com/api?v=3.0&ak=你的AK密钥&callback=onBaiduMapLoaded';document.body.appendChild(script);}// SDK加载完成后回调这个函数function onBaiduMapLoaded() {const map = new BMap.Map('baiduMap');// 设定中心点(换成你的地址坐标)const point = new BMap.Point(116.404, 39.915);map.centerAndZoom(point, 15);// 加个标记const marker = new BMap.Marker(point);map.addOverlay(marker);// 启用滚轮缩放map.enableScrollWheelZoom();mapInstance = map;}
AK密钥怎么获取?去百度地图开放平台(lbsyun.baidu.com)注册账号,创建应用选"浏览器端",就能拿到一个AK。免费额度每天有配额,企业站完全够用。
五、高德地图方案:代码结构几乎一样,换API就行
如果你更习惯用高德地图,代码结构完全相同,只是API调用方式换一下。
// 高德地图的初始化函数function initAmapMap() {const script = document.createElement('script');script.src = 'https://webapi.amap.com/maps?v=2.0&key=你的KEY&callback=onAmapLoaded';document.body.appendChild(script);}function onAmapLoaded() {const map = new AMap.Map('baiduMap', {center: [116.404, 39.915], // 注意:高德是[经度,纬度]zoom: 15,resizeEnable: true // 容器大小变化时自动适应});const marker = new AMap.Marker({ position: [116.404, 39.915] });map.add(marker);}
六、移动端适配:三件事让手机上看也正常
移动端屏幕窄,地图展开后如果高度还是400px会占大半个屏幕。需要做三处调整。
/* 1. 移动端地图高度缩小 */@media (max-width: 768px) {#baiduMap {height: 280px !important;}.map-expanded {max-height: 400px;}}/* 2. 按钮全宽,方便手指点击 */#mapToggle {padding: 14px 24px;font-size: 15px;cursor: pointer;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);color: #fff;border: none;border-radius: 8px;width: 100%;max-width: 400px;display: block;margin: 0 auto;}
3. 初始化时设置手势适配:百度地图初始化时加一行 map.enableScrollWheelZoom() 让PC端滚轮缩放生效,移动端双指缩放默认是开启的。高德地图在构造函数里加 resizeEnable: true 可以让地图在容器大小变化时自动刷新尺寸。

移动端最容易踩的坑:地图展开后只显示左上角一小块,其余部分是灰色。这是因为展开动画结束后地图容器尺寸变了,但地图实例没刷新。解决方案:展开动画的transition结束后,调一下地图的checkResize()方法。
七、加上过渡动画后的resize修复
transition动画0.5秒结束后,地图容器尺寸变了但地图实例不知道,所以需要监听transitionend事件,在动画结束后手动让地图重新计算尺寸。
// 展开后监听动画结束,手动刷新地图尺寸const wrapper = document.getElementById('mapWrapper');wrapper.addEventListener('transitionend', function() {if (isExpanded && mapInstance) {// 百度地图和高德地图都有 checkResize 方法mapInstance.checkResize();}});
八、进阶:地址坐标放HTML的data属性里,不用写死JS
实际建站时地址经常变——公司搬家了、新增分店了——每次改JS太麻烦。把经纬度和地址信息写在HTML的data属性里,JS读取就行。
<!-- HTML中存放地址数据 --><div id="baiduMap"data-lng="116.404"data-lat="39.915"data-zoom="15"data-title="XX科技有限公司"style="width: 100%; height: 400px;"></div>// JS中读取data属性const mapDiv = document.getElementById('baiduMap');const lng = parseFloat(mapDiv.dataset.lng);const lat = parseFloat(mapDiv.dataset.lat);const point = new BMap.Point(lng, lat);
九、常见问题排查
十、多地点切换展开:多个门店怎么搞
如果公司有多个门店,可以做一个标签切换式的展开地图。点"北京店"展开显示北京地图,点"上海店"展开显示上海地图。
// 门店数据配置const stores = [{ name: '北京总部', lng: 116.404, lat: 39.915 },{ name: '上海分公司', lng: 121.473, lat: 31.230 },{ name: 深圳分公司', lng: 114.057, lat: 22.543 }];function switchStore(index) {const store = stores[index];const point = new BMap.Point(store.lng, store.lat);mapInstance.centerAndZoom(point, 15);// 清除旧标记,加新标记...}
多门店的关键点:地图实例只初始化一次,切换门店时只改变centerAndZoom中心点和标记,不重新new地图。这样切换丝滑,也不会有加载延迟。
最后说两句
网站里的地图展开图,技术拆开来看就三件事:CSS的max-height+transition做动画、JS的classList切换做展开收起、地图API的懒加载做性能。代码量加起来不到60行,但每个环节都有几个容易翻车的细节——max-height别设太大、展开后要调checkResize、地图只初始化一次别重复new。这些坑踩一次就知道,但提前知道就能少走弯路。三个地图平台里,百度适合PC企业站、高德移动端体验更好、腾讯地图如果你用的是腾讯生态可以无缝接入,选哪个取决于你的网站主力用户在哪里。代码本身不复杂,照着上面的示例改一下AK和坐标就能上线。

十一、腾讯地图方案
如果网站用的是腾讯系域名或者微信小程序里用,腾讯地图JavaScript API GL也可以。代码结构跟前两个差不多,注意腾讯地图坐标格式是(纬度,经度),和百度高德反过来。
十二、完整HTML页面代码(可直接用)
把所有代码拼在一起,就是一个完整可运行的页面。替换掉AK和坐标就能直接上线。以下是核心代码结构:
<!DOCTYPE html><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><style>.map-collapsed { max-height: 0; overflow: hidden; transition: max-height 0.5s ease-in-out; }.map-expanded { max-height: 600px; }#mapToggle { padding: 14px 24px; font-size: 15px; cursor: pointer; background: linear-gradient(135deg, #667eea, #764ba2); color: #fff; border: none; border-radius: 8px; }@media (max-width: 768px) { #baiduMap { height: 280px !important; } .map-expanded { max-height: 400px; } }</style></head><body><button id="mapToggle" onclick="toggleMap()">查看公司地图位置 ▼</button><div id="mapWrapper" class="map-collapsed"><div id="baiduMap" data-lng="116.404" data-lat="39.915" style="width:100%;height:400px"></div></div><script>let mapInstance = null, mapLoaded = false, isExpanded = false;function toggleMap() {const w = document.getElementById('mapWrapper');const b = document.getElementById('mapToggle');if (!isExpanded) {w.classList.replace('map-collapsed', 'map-expanded');b.innerHTML = '收起地图 ▲';if (!mapLoaded) { initMap(); mapLoaded = true; }isExpanded = true;} else {w.classList.replace('map-expanded', 'map-collapsed');b.innerHTML = '查看公司地图位置 ▼';isExpanded = false;}}function initMap() {const s = document.createElement('script');s.src = 'https://api.map.baidu.com/api?v=3.0&ak=你的AK密钥&callback=onMapLoaded';document.body.appendChild(s);}function onMapLoaded() {const div = document.getElementById('baiduMap');const lng = parseFloat(div.dataset.lng);const lat = parseFloat(div.dataset.lat);const map = new BMap.Map('baiduMap');map.centerAndZoom(new BMap.Point(lng, lat), 15);map.addOverlay(new BMap.Marker(new BMap.Point(lng, lat)));map.enableScrollWheelZoom();mapInstance = map;}document.getElementById('mapWrapper').addEventListener('transitionend', function() {if (isExpanded && mapInstance) mapInstance.checkResize();});</script></body></html>把"你的AK密钥"替换成百度地图开放平台申请的AK,把data-lng和data-lat换成你自己公司地址的经纬度,其他代码一个字都不用改。
十三、不想写代码的替代方案
如果只是想在网站里加个地图,不想写代码,也有几个现成的路子:
Leaflet的额外好处:如果你对地图精度要求不高(比如只是展示大概位置),Leaflet + OpenStreetMap完全免费、不需要申请任何密钥、国内也能正常加载。代码比百度高德更简单,而且移动端适配天然就很好。
最后说两句
网站里的地图展开图,技术拆开来看就三件事:CSS的max-height+transition做动画、JS的classList切换做展开收起、地图API的懒加载做性能。代码量加起来不到60行,但每个环节都有几个容易翻车的细节——max-height别设太大、展开后要调checkResize、地图只初始化一次别重复new。这些坑踩一次就知道,但提前知道就能少走弯路。三个地图平台里,百度适合PC企业站、高德移动端体验更好、腾讯地图如果你用的是腾讯生态可以无缝接入,选哪个取决于你的网站主力用户在哪里。代码本身不复杂,照着上面的示例改一下AK和坐标就能上线。
十四、怎么获取公司地址的经纬度坐标
写代码之前先得知道公司地址的经纬度。三个地图平台都有自己的坐标拾取工具,在网页上点一下就能拿到坐标。注意:不同地图平台使用的坐标系不一样——百度用的是BD09坐标系,高德和腾讯用的是GCJ02(火星坐标系),GPS原始坐标是WGS84。直接用GPS坐标放到百度地图上会偏几百米。
省事的做法:直接用你要用的那个地图平台的坐标拾取工具去取坐标,保证坐标系对得上。不要用手机GPS定位的坐标直接填进去。
