根本原因是devicepixelratio变化时未重设canvas的width/height属性,仅修改css尺寸导致绘图坐标系错位;须在dpr变化时同步更新canvas.width/height并调用ctx.scale(dpr,dpr)。
Canvas缩放后地图瓦片错位怎么修
根本原因是devicePixelRatio变化时没重设Canvas的width/height属性,只改了CSS尺寸。浏览器按CSS像素渲染,但Canvas绘图坐标系仍基于物理像素,导致瓦片偏移、模糊或重复。
- 必须在
window.devicePixelRatio变化时(如缩放、切显示器)重新设置canvas.width和canvas.height为cssWidth * window.devicePixelRatio - 重设后立即调用
ctx.scale(devicePixelRatio, devicePixelRatio),让绘图坐标系对齐 - 别用
transform: scale()替代——它只影响显示,不改变Canvas内部坐标系统 - 示例关键段:
function resizeCanvas() { const dpr = window.devicePixelRatio || 1; canvas.width = canvas.clientWidth * dpr; canvas.height = canvas.clientHeight * dpr; ctx.scale(dpr, dpr); }
Leaflet地图在高DPR设备上瓦片模糊
Leaflet默认按CSS像素请求256×256瓦片,但在Retina屏上实际需要512×512才清晰。不配detectRetina: true,它就永远拿不到高清瓦片。
- 初始化时加
detectRetina: true,Leaflet会自动在devicePixelRatio > 1时请求@2x瓦片 - 确保瓦片服务支持
@2x后缀(如https://{a-d}.tile.openstreetmap.org/{z}/{x}/{y}@2x.png),否则404 - 自定义瓦片URL时,用
{r}占位符:url: 'https://.../{z}/{x}/{y}{r}.png',再配detectRetina: true,Leaflet自动补r: '@2x' - 注意:某些地图服务(如Mapbox Static API)需显式传
scale=2参数,detectRetina无效
WebGL地图(Cesium/Deck.gl)分辨率适配失效
WebGL上下文创建后,gl.drawingBufferWidth/Height不会随窗口缩放自动更新,必须手动resize并重置viewport,否则渲染区域被裁剪或拉伸。