2017-04-19 102 views
1

我需要建立一种地图在帆布的,其必须能够显著较慢保持多于10.000元件并因此具有安静大尺寸在某些情况下(> 8000px宽度,> 4000像素高度)。我还需要平移和缩放的地图。 经过与现有库(Paper.js)和可能的其他解决方案(Leaflet Map)的一番讨论后,我终于从零开始编写了自己的库,因为主要要求是,应该是真的很快(加载,鼠标悬停, ...)并且我尝试过的这些库中没有一个可以提供全部的各个方面。的Android在调整大小和移动多个画布元素

的结构如下:

  • 我有具有相关联的控制对象,该对象注册事件,并且具有调整方法等
  • 的图谱在复式甚至尺寸的方格划分一个地图对象(1,024像素x x 1024px - 可自定义),因为使用地图时只有一个大小超过8000像素的画布使其变得非常慢
  • 每个图块都与画布相关联
  • 元素(只是圆圈)被添加到一个或多个图块如果它在边缘) - mor特别是瓷砖的画布。
  • 将瓷砖放置其具有地图区域的尺寸(当不缩小)
  • 的div容器被置于视口的div内,以使地图被显示为“微件”
  • 一个div容器内
  • 缩放比例尺瓷砖/帆布和容器。为了提高性能,我牺牲了平滑的缩放功能,并实现了可定制的缩放步骤,但仍然感觉没问题。
  • 平移集的topleft风格的容器。使用
  • 事件是window.resizemousewheelDOMMouseScrolmousedownmouseupmousemovetouchstarttouchendtouchmoveHammertime pinch

此产品总数运行满足于桌面浏览器,和iPhone(与SE测试,6S),但对每一个Android设备我测试了它(三星S4,一加一和另一个1岁的设备,和Android演播室模拟器)它运行速度极其缓慢。图的绘制速度很快,但缩放和平移已接近不可能

这段代码太全面了,不能在这里发布,所以我问你是否有任何已知的Android上的画布问题,这可以解释这个问题,或者我可以解释一些问题,与android产生问题。我在这里确实无能为力,因为它可以在桌面和iPhone上运行。

+0

像你采取错误的做法听起来给我。画布不应大于屏幕的分辨率,那么您应该转换画布(['scale'](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/scale)), ['translate'](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/translate)等),以便它显示你所需要的。同样,确保你没有试图渲染任何实际上不可见的东西。 –

+0

@MikeC当我将地图的新部分平移到视口中时,我将不得不绘制元素?除了我必须画更多的事实之外,绘画元素是否有任何缺点(表现方面),除了画布之外? – Strernd

+0

是的,你将不得不绘制仅部分可见的元素,但它肯定会比试图绘制整个东西然后转移画布更快。唯一的“缺点”是你提到的那个:绘制更多。但是,如果这些元素至少部分可见,则需要绘制它们,因此它不是必需品,因为它是一项要求。 –

回答

1

你遇到的真正问题是你超负荷的GPU。一次又一次地加载这么多的数据然后移动它将会对GPU造成影响,并可能迫使浏览器进入软件渲染模式,这是一个巨大的性能影响。

相反,我会建议改变你的方法。您应该拥有一张最多可以显示用户屏幕大小的画布,而不是使用各种大型画布。然后,利用画布API的方法(例如scaletranslate)呈现您所需的内容。为了获得额外的奖励,请避免尝试渲染屏幕外的东西。

似乎不得不在每次移动时重绘场景会很慢,但事实并非如此。实际情况是,要么指定,要么确定需要绘制什么内容,或者浏览器在移动它时再次尝试绘制全部。以下是如何渲染和移动大图像的简要示例。

var ctx = document.querySelector('canvas').getContext('2d'); 
 
var img = new Image(); 
 
img.src = 'https://placeimg.com/1000/1000/nature'; 
 
img.onload = start; 
 

 

 
function start() { 
 
    var xDirection = -1; 
 
    var yDirection = -1; 
 
    var xPosition = 0; 
 
    var yPosition = 0; 
 
    
 
    var prev = Date.now(); 
 
    (function render() { 
 
    var now = Date.now(); 
 
    var delta = (now - prev)/1000; 
 
    
 
    xPosition += xDirection * delta * 20; 
 
    yPosition += yDirection * delta * 40; 
 
    if (xPosition > 0) { 
 
     xPosition = 0; 
 
     xDirection *= -1; 
 
    } else if (xPosition < -320) { 
 
     xPosition = -320; 
 
     xDirection *= -1; 
 
    } 
 
    if (yPosition > 0) { 
 
     yPosition = 0; 
 
     yDirection *= -1; 
 
    } else if (yPosition < -240) { 
 
     yPosition = -240; 
 
     yDirection *= -1; 
 
    } 
 
    
 
    prev = now; 
 
    ctx.save(); 
 
    ctx.translate(xPosition, yPosition); 
 
    ctx.drawImage(img, 0, 0); 
 
    ctx.restore(); 
 
    requestAnimationFrame(render); 
 
    })(); 
 
}
body { 
 
    background: #111; 
 
} 
 
canvas { 
 
    background: #FFF; 
 
}
<canvas width="320" height="240"></canvas>

+0

我会很高兴,如果你可以看看我的后续问题在这里http://stackoverflow.com/questions/43543679/best-practice-for-zooming-and-panning-html5-canvas-with-10k-objects / – Strernd