- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个模拟平铺图像的 Canvas 元素表。我只需要填充那些当前在视口(viewport)中可见的图 block 。这是我使用的代码
for (var ix = visibleRange.firstX; ix <= visibleRange.lastX; ix++) {
for (var iy = visibleRange.firstY; iy <= visibleRange.lastY; iy++) {
var canvasDispJq = $("canvas#" + frameResId + "-" + ix + "-" + iy + "- disp");
var canvasDisp = canvasDispJq.get(0);
var image = new Image();
var context = canvasDisp.getContext("2d");
image.onload = function() {
context.drawImage(image, 0, 0);
}
image.src = self.baseURL + '/' + canvasDispJq.attr("id");
}
}
};
但问题是只加载范围内的最后一个图 block 。同样的事情,但以这种方式实现的工作正常:
$("table#canvasTable-" + frameResId + " canvas.display").each(function() {
var canvasDispJq = $(this);
if ((canvasDispJq.position().top + self.tileSize + imagePosition.y) > 0 &&
(canvasDispJq.position().left + self.tileSize + imagePosition.x) > 0 &&
(canvasDispJq.position().top + imagePosition.y) < self.containerHeight &&
(canvasDispJq.position().left + imagePosition.x) < self.containerWidth) {
var canvasDisp = canvasDispJq.get(0);
var image = new Image();
var context = canvasRaw.getContext("2d");
image.onload = function() {
context.drawImage(image, 0, 0);
}
image.src = self.baseURL + '/' + canvasDispJq.attr("id");
}
});
可见范围计算方式的差异无关紧要,因为我在 Firebug 中进行了检查,并且两种方法都正确选择了要渲染的图 block ,并且实际图 block 图像是从服务器下载的,但对于第一种方法,只显示最后一个图 block ,而对于第二个所有的瓷砖都被正确渲染。
提前感谢您的任何建议。
最佳答案
造成差异的原因主要在这里:
var image = new Image();
var context = canvasDisp.getContext("2d");
image.onload = function() {
context.drawImage(image, 0, 0);
}
它所做的是创建一个闭包并将其分配给图像的 load
事件。闭包关闭 context
和 image
变量(以及其他几个)。这里的关键是它有一个对这些变量的持久引用,而不是创建函数时它们值的副本。由于上面的代码在一个循环中,所有创建的函数(闭包)都将引用相同的 context
和 image
- 循环创建的最后一个。
它不会发生在 each
版本中,因为在那个版本中,闭包关闭了一个不变的变量,one context
和 image
通过调用传递给 each
的迭代器函数创建。
更多关于闭包的信息:Closures are not complicated
也许 稍微 偏离主题,也许不是:如果您的 var
位于不同的位置,这可能会更清楚。 var
is sometimes misunderstood.特别是,它不与某些其他语言(例如 C、C++、Java 和 C#)中的变量声明相同,部分原因是 JavaScript 没有 block 级范围(只有函数级范围和全局范围)。
这是 JavaScript 解释器如何看待您的第一个版本:
var ix, iy, canvasDispJq, canvasDisp, image, context;
for (ix = visibleRange.firstX; ix <= visibleRange.lastX; ix++) {
for (iy = visibleRange.firstY; iy <= visibleRange.lastY; iy++) {
canvasDispJq = $("canvas#" + frameResId + "-" + ix + "-" + iy + "- disp");
canvasDisp = canvasDispJq.get(0);
image = new Image();
context = canvasDisp.getContext("2d");
image.onload = function() {
context.drawImage(image, 0, 0);
};
image.src = self.baseURL + '/' + canvasDispJq.attr("id");
}
}
}
请注意,所有 var
语句都已移至顶部,因为这就是它们的处理方式。无论 var
出现在函数的哪个位置,它都从函数的最开始生效,并且只发生一次。如果 var
有一个初始值设定项,那么它将成为 var
所在的赋值。所以 var x = 2;
实际上是两个完全独立的东西,由解释器在不同的时间处理:var x
,它在进入函数时发生,然后再发生任何其他事情, 和 x = 2;
,它出现在函数代码的逐步执行中。
(此外,题外话:在 for
循环的结束 之后不需要
;
;但您确实想要一个在分配给 onload
处理程序之后。我也将这两个 mod 都制作成了 aboev。)
按照解释器看到的方式编写代码,现在(无论如何对我而言)更清楚的是,您分配给 onload
的每个闭包都将引用相同的 context
和 image
变量,所以他们都会看到最后一个。
如果你想使用非each
版本,你只需要稍微改变它,这样onload
闭包就会关闭它们自己的context<副本
和 image
。看起来像这样:
var ix, iy, canvasDispJq, canvasDisp, image, context;
for (ix = visibleRange.firstX; ix <= visibleRange.lastX; ix++) {
for (iy = visibleRange.firstY; iy <= visibleRange.lastY; iy++) {
canvasDispJq = $("canvas#" + frameResId + "-" + ix + "-" + iy + "- disp");
canvasDisp = canvasDispJq.get(0);
image = new Image();
context = canvasDisp.getContext("2d");
image.onload = createOnloadHandler(context);
image.src = self.baseURL + '/' + canvasDispJq.attr("id");
}
}
}
function createOnloadHandler(ct, img) {
return function() {
context.drawImage(img, 0, 0);
};
}
现在由 createOnloadHandler
函数创建的闭包关闭 ct
和 img
,而不是 context
和 图像
。每个闭包都有自己的副本(传递到创建该闭包的 createOnloadHandler
调用的副本)。
关于javascript - 将图像加载到多个 Canvas 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5269194/
我可以使用两种方法添加一个 child ,一种是 Canvas.AddVisualChild(Visual); Canvas.AddLogicalChild(Visual); 我在视觉对象的 Draw
在过去的几周里,我一直在尝试各种方法,试图找到将 BDD 用于依赖于 HTML5 Canvas 元素以及用户与之交互的 Web 应用程序的最佳方法。 我一直在使用 Jasmine 和 Cucumber
我正在尝试完成撤消/重做。我正在使用loadFromJSON(...)从我存储在数组中的 Canvas 状态重新构建 Canvas 。基本上,我的想法是破坏现有的 Canvas 并重新构建 Canva
我正在尝试在 Canvas 上设置简单的放大/缩小功能。我正在使用 KineticJS 处理触摸事件并在 Canvas 中绘图,但无法实现缩放。 KinteicJS 有一个类似的例子,但它们总是在中心
我正在使用 processing.js 在 javascript 中开发一个画笔应用程序 它正在使用 Canvas 对象。我想在 Canvas 的背景中保留一个图像。在前景中画一些东西。在保存时,我只
您好,我想为 discord.js Bot 安装 Canvas 。 当我尝试使用以下命令安装 Canvas 时npm install canvas我收到以下错误: pi@server:~/Bots/D
我正在尝试使用 Canvas 和动力学的组合来构建填充图案,但在尝试获得连续线时遇到了问题。 此 jsfiddle显示了到目前为止我所拥有的,但是因为我的重复模式是正方形,角会影响线条,我尝试使用 l
我正在开发一个 webassembly 程序。 我可以使用 emscripten_set_canvas_size 设置 Canvas 大小(我一直读到我需要切换到新的 API,因为这个 API 会贬值
您好,我已经为第一个 Canvas 中的第一个图像创建了一个圆形表单,但我没有成功使用第一个 Canvas 的 dataURL 并将其添加到第二个 Canvas 中。 这是我的 fiddle :htt
问题在于不同浏览器之间的不一致。 使用Dart Chrome,JS Chrome,JS Opera运行 双击可以进入和退出全屏 m_oCanvas.width =(window.screen.widt
我正在使用Flutter框架和Dart开发图像编辑器,因此无法将矩阵滤镜应用于 Canvas 。 我正在尝试使用“Paint”类和“canvas.drawPaint(paint)”函数将矩阵过滤器应用
如果在已经具有非整数比例因子的 Canvas 上绘制图像,我会遇到 Canvas 上下文drawImage()方法的问题。似乎这样的图像以一种奇怪的方式被剪切(有时图像的最右边的部分被剪切,有时是最底
Canvas 的“宽度”属性值有限制吗? 在下面的示例中,我在 ScrolledWindow 中创建一个 Canvas。 # Packages package require BWidget # Ma
我正在尝试制作类似于 this article 底部的效果的文本效果 我建议的方法是: 制作两个 Canvas ,一个是可见的,另一个是不可见的我用它作为缓冲区。 在缓冲区 Canvas 上绘制一些文
例如var new = canvas.toDataURL("image/png"); 我希望这个新变量中存在的 base64 显示到存在的第二个 Canvas 元素中。但是它不使用 drawimage
有人有使用这两个 Node.js 库中的一个或两个的经验吗?很想知道每个人的成功或困难。 最佳答案 LearnBoost是社区中最多产的 Node 模块开发人员之一,因此我选择使用 node-canv
如何知道 Canvas 运行的是“WebGL”还是普通 Canvas ? 通过检查源代码,我发现这两种情况都是 Canvas 。 最佳答案 这真的取决于你想如何去发现。 例如你可以这样调用 `getC
在 Canvas 上绘图非常好。甚至橡皮擦也能正常工作。问题是,当 Canvas 保存为图像时,它绘制的是黑线而不是橡皮擦。 为了更好地理解,我添加了屏幕截图和代码。 1。在删除绘图时 - 一个。源代
我正在尝试为 Canvas 附加鼠标悬停和鼠标移出事件: 默认 Canvas 是函数drawcircle的 Canvas 。 如果用户越过 Canvas ,应将其更改为drawEllipse的 Can
我正在使用 Three.js 构建一个简单的 2D 游戏。我只使用世界的 X 和 Y 位置来移动对象,将它们的 z 位置保留为零。我使用禁用旋转的 TrackballControls,以允许使用右键单
我是一名优秀的程序员,十分优秀!