公司简介页的交通地图,用CSS向右仅旋转了2.5°。本文先依据各种官方资料,梳理作为其前提的两个问题——道路为何不沿正北方向Web地图为何被固定为“以北为上”——然后解说如何用CSS倾斜不支持旋转的Google地图嵌入。

为便于比较,先展示未经任何处理的原始嵌入。它与公司简介页的地图采用相同的中心、相同的缩放级别,只是没有旋转。中央的红色图钉是敝公司的所在地,其上方是押上站(东京晴空塔),下方是锦系町站。

▲ 未旋转的原始Google地图(以北为上)

道路不沿正北方向

在开头的地图中,纵向连接押上与锦系町的是“Tower View通”,中途东西向横穿它的是“春日通”。从OpenStreetMap取得道路两端的坐标并计算方位角,这两条道路分别倾斜了:

  • Tower View通 — 从北向西约3.5°
  • 春日通 — 偏离东西方向约3.2°

因此,在将押上与锦系町纵向收入的构图中,作为构图轴线的Tower View通相对于画面显得略微倾斜。

倾斜的由来 — 不是磁北,而是江户的运河

方位的基准有两个:指向自转轴方向的“正北”,以及指南针所指的“磁北”。根据国土地理院的磁偏图,东京附近的偏角(正北与磁北之间的偏差)约为西偏7度。本次的约3.5°与该数值不一致,因此街道并非以磁针为基准而设。

原因在于街区的形成过程。街道一般不以天文学方位,而是以地形、水系、既有街道为基准而设。此处——墨田区南部的旧本所地区,是以明历大火(1657年)为契机开辟的新兴地,棋盘格般的街景与纵横流淌的水路,都源自当时的规划性开发(墨田区资料)。Tower View通所沿行的大横川亲水公园,也是这次开发中开凿的运河——横川的旧址。也就是说,道路约3.5°的倾斜,是江户时期所设方格从正北略有偏离这一事实历经370年的遗留。

地图被固定为“以北为上”的机制

Google地图的2D地图,其机制是用墨卡托投影将地球投影到正方形平面上,并按每个缩放级别配送预先分割好的图像(瓦片)来显示(Map and Tile Coordinates)。由于瓦片是以北为上绘制的现成图像,这种方式的地图根本不存在“旋转”这一操作。实际上,查阅Maps Embed API文档,在地图模式下可指定的仅限于中心(center)、缩放(zoom)等,并无朝向参数(heading只能用于指定街景模式下相机的朝向)。

另一方面,Maps JavaScript API的矢量地图在客户端绘制的是图形数据而非瓦片图像,因此支持通过setHeading()进行旋转与倾斜。不过前提是取得API密钥并设置计费。在使用免密钥嵌入的静态网站上,无法旋转地图数据本身。于是,我们决定只用CSS旋转显示

用CSS旋转显示

先从结果说起。下面的地图,是将开头相同的嵌入用CSS旋转了2.5°。纵向贯穿中央的Tower View通,与画面的纵轴几乎平行。

▲ 用CSS旋转2.5°的嵌入。与开头的原始地图相比,道路已与画面的纵横对齐。

实现采用如下结构,仅由外框元素与iframe构成。上面的地图也原样套用了这段CSS(在公司简介页则用Tailwind CSS的类写出同样的内容)。

.map-frame {
  position: relative;
  height: 500px;
  overflow: hidden;      /* 裁掉溢出的四角 */
  border-radius: 12px;
}
.map-frame iframe {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 110%;           /* 预先放大一圈 */
  height: 120%;
  transform: translate(-50%, -50%) rotate(2.5deg);
}

要点有三个。

不旋转外框,只旋转内容 — 保持带圆角与边框的外框不变,只用transformrotate()旋转内侧的iframe。

将iframe放大一圈 — 若直接旋转长方形,四角会出现三角形空隙,露出背景。为使宽w、高h的框在旋转角度θ之后仍能无空隙地覆盖,所需的尺寸可由旋转的坐标变换求得,即宽w·cosθ + h·sinθ、高w·sinθ + h·cosθ。本站的框约为宽740px、高500px,因此在θ = 2.5°(sin θ ≈ 0.044)时,按计算宽增加约22px(+3%)、高增加约32px(+7%)即足够。实现中留有余量,取宽110%、高120%。

用外框的overflow: hidden裁切 — 放大并旋转后溢出的部分,由外框裁掉。框内只留下道路与画面纵横对齐的地图。

另外,CSS的变换不影响文档的布局,只作用于绘制与指针的命中测试(CSS Transforms Module Level 1)。因此旋转后iframe内的拖动与缩放仍照常工作,坐标的变换由浏览器处理。

关于旋转角,若按实测值旋转3.5°,Tower View通会与画面完全平行,但作为包含地图中文字在内的整体倾斜不易被察觉的范围,本站采用了2.5°。

补充 — 关于地图的构图

敝公司(墨田区横川)位于押上站与锦系町站几乎正中间,指路时以这两站为标志。公司简介页的地图之所以采用将两站收入一屏的构图,正是出于此因。为使作为构图轴线的Tower View通(敝公司所面对的是其东侧的一条道路)与画面的纵轴对齐,加入了2.5°的旋转。

总结

  • 道路约3.5°的倾斜与磁偏角(东京约西偏7度)是两回事,它源自明历大火后以运河为骨架划分的本所棋盘格,从正北略有偏离。
  • Web的2D地图机制是配送以墨卡托投影绘制的“以北为上”的瓦片图像,因此栅格方式的嵌入没有旋转操作(矢量地图的setHeading()支持旋转)。
  • 用CSS的transform旋转iframe,依据w·cosθ + h·sinθ放大一圈,再用外框的overflow: hidden裁切,即可只调整外观上的朝向。
  • 采用的旋转角为2.5°(相对于实测的3.5°,优先考虑地图整体倾斜不易被察觉)。

旋转的效果,可通过对比本文开头的原始嵌入与“用CSS旋转显示”一节中旋转后的嵌入来确认。实际运用的例子是公司简介页的地图,它在同样的旋转之上还加入了灰度显示等装饰。

参考资料