描绘故事:
我有一些视觉内容,分为几组图像(平铺)。
我正在使用一个简单的循环,该循环由requestAnimationFrame
调用以在画布上显示这些图块。
实际上,我正在使用PixiJS来完成这些工作;尽管这可能是与该问题不太相关的实现细节。
因为可能会有很多图块,并且因为我希望用户能够“有点即时”滚动浏览这些图块集,所以我只预加载了某些图块集,然后当用户进一步导航时tileet,将加载另一组磁贴,直到没有更多磁贴可供加载。
当视觉内容完全加载后,requestAnimationFrame
循环功能良好,没有任何断断续续的情况。
但是在延迟加载期间,有时会有些断断续续。
我尝试使用setInterval
从requestAnimationFrame
循环中分离延迟加载(也包括废物管理或垃圾收集)。
但是后来我意识到这是因为JavaScript仅具有一个线程,因此图像的加载阻碍了其余代码。因此setInterval
没有帮助;也不进行第二次requestAnimatonFrame
的延迟加载调用。
然后,我读到有关Web Workers的信息,这确实为并发执行事情提供了可能性。但是,当我读取Web Worker线程中的所有数据时,它们将被复制而不是通过引用传递。因此它将占用两倍的内存。
我也怀疑Web Worker是否适合同时加载图块,因为Mozilla开发人员网络页面大多将其指定为并行(繁重)数字运算解决方案的帮助。
有一个特定的Web Worker类型。位于网页请求和Web服务器之间的Service Worker。在执行画图循环时,服务人员会在所有加载图像时帮助我吗?
如果不是,是否有人知道一种替代方法,既可以延迟加载又可以对已经加载的一组图像进行动画处理?有什么明显的我忽略了吗?
编辑3:请仔细观察;图像加载时出现口吃;有时比其他时候更多;但它仍然在那里;因为按照注释部分的指示我删除了模拟,所以它不那么明显了;但是口吃还在那里更容易查看是否扩展了代码段,然后在打开开发人员控制台后,转到“网络”选项卡并选中“禁用缓存”,然后单击“运行”按钮。
编辑2::忽略编辑1.因为模拟已由现在加载的真实图像代替。第一次加载图像或关闭浏览器缓存时,结结很明显。
编辑1:如要求的示例。通过循环模拟懒惰负载阻塞,直到执行了一定的随机延迟为止。这些颜色应该代表瓷砖图像,但实际上是使用随机颜色从画布上绘制的。
var tileImageURLs = [
"https://async.blogjoch.nl/s/W9BcY7RgfNAES38/preview",
"https://async.blogjoch.nl/s/qoHrK9Nz8i7m8Lb/preview",
"https://async.blogjoch.nl/s/ZoAxpcMGF8MPrZH/preview",
"https://async.blogjoch.nl/s/QgTBjbakkSKywpJ/preview",
"https://async.blogjoch.nl/s/G74zo79txm9KHX9/preview",
"https://async.blogjoch.nl/s/cgTy6YswifocsqB/preview",
];
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var y = 0;
var NORMALSPEED = 5;
var currentSpeed = NORMALSPEED;
var TILEWIDTH = 768;
var TILEHEIGHT = 1024;
var TILECOUNT = 6;
var tileImages = [];
var lastTileLoad = -1;
var tileLoadStart = 0;
var PRELOADEDTILESCOUNT = 2;
// For offscreen generation of tiles.
//var tileCanvas = document.createElement('canvas');
//tileCanvas.width = TILEWIDTH;
//tileCanvas.height = TILEHEIGHT;
//var tileCtx = tileCanvas.getContext('2d');
//var tileColors = ['red', 'green', 'blue', 'orange', 'yellow'];
for (var tileIdx = 0; tileIdx < TILECOUNT; tileIdx++) {
tileImages[tileIdx] = document.createElement('img');
tileImages[tileIdx].width = TILEWIDTH;
tileImages[tileIdx].height = TILEHEIGHT;
}
function loadTileImages(tileStart, tileEnd) {
if (tileImages[tileStart]) {
tileImages[tileStart].onload = function() {
// Image loaded; go to next tile if applicable.
if (tileStart + 1 <= tileEnd) {
loadTileImages(++tileStart, tileEnd);
}
}
tileImages[tileStart].src = tileImageURLs[tileStart];
}
}
function loadTiles() {
var tileLoadCount;
if (lastTileLoad < Math.round(y / (canvas.height * 1))) {
/**
* Load checkpoint which lies past previous load checkpoint found;
* so load some stuff.
*/
tileLoadCount = Math.min(tileLoadStart + PRELOADEDTILESCOUNT - 1, TILECOUNT);
loadTileImages(tileLoadStart, tileLoadCount);
tileLoadStart += PRELOADEDTILESCOUNT;
if (tileLoadStart > TILECOUNT - 1) {
/**
* Stop the loading; Infinity is always bigger than a non-infinite number.
*/
console.log('Loading has finished.');
lastTileLoad = Infinity;
} else {
/**
* Store this 'load checkpoint'.
*/
//this.needToDrawFrame = true;
lastTileLoad = Math.round(y / (canvas.height * 1));
}
}
}
function tick() {
var tileImgY;
if (currentSpeed > 0 && (y >= (TILECOUNT * TILEHEIGHT) - canvas.height)) {
currentSpeed = -NORMALSPEED;
} else if (currentSpeed < 0 && (y <= 0)) {
currentSpeed = NORMALSPEED;
}
y += currentSpeed;
loadTiles();
var tileStart = Math.max(Math.floor(y / TILEHEIGHT) - 1, 0);
var tileCount = Math.min(tileStart + Math.ceil(canvas.height / TILEHEIGHT) + 2, TILECOUNT);
//console.log(y, tileStart, tileCount);
ctx.clearRect(0, 0, canvas.width, canvas.height);
for (var tileIndex = tileStart; tileIndex < tileCount; tileIndex++) {
var tileImg = tileImages[tileIndex];
tileImgY = (tileIndex * TILEHEIGHT) - y;
ctx.drawImage(tileImg, 0, tileImgY, TILEWIDTH, TILEHEIGHT);
}
requestAnimationFrame(tick);
}
requestAnimationFrame(tick);
#canvas {
width: 500px;
height: 500px;
border: solid 1px black;
}
<canvas id="canvas" width="768" height="1024"></canvas>
答案 0 :(得分:0)
我对自己的问题有一个答案;这主要是我的愚蠢。
事实证明,它正在加载阶段对股票行情自动收录器功能(由 log.info("Session id=" + vars.get("sessionId"));
调用)(旨在确保新的图块图像到达时刷新屏幕)。
这些调用引起了额外的运动,并感觉好像有些结巴(比我在示例中能够重现的重)。
但是,当我在Web Worker中使用requestAnimationFrame
加载图像后,部分口吃-微型口吃就消失了。