我正在使用我以前用
制作的图像var patternImageAsDataURL= canvasObject.toDataURL('image/png');
在稍后阶段,我想制作一个画布图案对象。下面的代码不起作用 - 我假设在转到最后一行时根本没有加载图像,在createPattern函数中需要它。
var img = document.createElement('img');
img.src = patternImageAsDataURL;
// canvasctx was created somewhere else in the program
pattern = canvasctx.createPattern(img,'repeat');
我在最后一行收到错误:NS_ERROR_NOT_AVAILABLE:
。 (当在最后两行之间的img
的宽度和高度上使用console.log时,我发现当它不起作用时,尺寸为0
。)
稍后使用相同的dataURL完成相同的操作时,它确实有效。虽然图像(img)应该总是重新创建。 (因为我在Firefox中进行了一些内部优化,所以我可以看到它的原因。但是这里除非有人确实知道了答案,否则这是非正式的。)将它们打印到控制台时的宽度和高度是正确的
虽然我很快会编写一些模式处理服务,但是应该解决这个问题,我的问题一般是关于速度问题和简单性。 (如果我使用带有模式的20到50个对象的代码,我宁愿选择内存或省时功能的精益解决方案。)
我能以某种方式更直接地(并且更快地)使用dataURL createPattern函数? 和: 我可以强制程序在
img.src = patternImageAsDataURL;
命令之后等待,直到加载图像,然后继续处理代码? (就像在XMLrequests的同步模式中一样。)
(在当前的程序流程中,使用图像的onload事件是不可行的。)
这是在Firefox 32,Win 7上运行。
答案 0 :(得分:2)
创建模式的更快,更直接的方式
您可以使用第二个canvas元素作为模式的源。
这使您可以完全跳过从源画布创建ImageURL和Image的临时步骤,这样您的模式创建速度就会更快。
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
// Make a temporary canvas to be the template for a pattern
var pc=document.createElement('canvas');
var px=pc.getContext('2d');
pc.width=4;
pc.height=4;
px.fillStyle='palegreen';
px.fillRect(0,0,2,2);
px.fillRect(2,2,2,2);
// Use the temporary canvas as the image source for "createPattern"
var pattern=ctx.createPattern(pc,'repeat');
ctx.fillStyle=pattern;
ctx.fillRect(50,50,100,75);
ctx.strokeRect(50,50,100,75);
body{ background-color: ivory; }
#canvas{border:1px solid red;}
<h4>Using a temporary canvas as source for a Pattern.</h4>
<canvas id="canvas" width=300 height=300></canvas>
答案 1 :(得分:1)
显而易见的当然是使用画布本身作为模式的图像源。
createPattern()
可以将图片,画布,上下文(虽然并非所有浏览器都允许)或甚至视频source。
CanvasPattern createPattern(CanvasImageSource image,
[TreatNullAs = EmptyString] DOMString重复);
其中CanvasImageSource
定义为:
typedef(HTMLImageElement或
HTMLVideoElement或
HTMLCanvasElement或
CanvasRenderingContext2D或
ImageBitmap)CanvasImageSource;
这也是允许您稍后不使用onload
的唯一方法(前提是生成模式但未从图像/视频源中提取)。
如果不使用回调(或承诺),您无法处理异步行为,并期望程序正常工作。期间。
如果由于某种原因无法使用原始画布作为源,则必须异步处理图像。为它添加一个onload
处理程序并从其中继续:
var img = document.createElement('img');
img.onload = function() {
pattern = canvasctx.createPattern(this, 'repeat');
// continue from here..
};
img.src = patternImageAsDataURL;
请注意,由于在图像处理本身之上的额外编码/解码过程,此过程相对较慢。您可以在this answer。
中找到有关此内容的更多详细信息Blob允许您以二进制形式存储数据。这优于将二进制数据作为编码字符串存储,与data-URI一样。与数据URI相比,嵌入和提取的速度更快。
您可以将URL表单与Blob一起使用,并将其用作图像源。
首先直接从画布创建Blob:
var patternImageAsBlob = canvas.toBlob(...); //IE: msToBlob()
这也是一个异步调用,因此您需要考虑到这一点。
例如:
var patternAsBlob;
canvas.toBlob(function(blob) {
patternAsBlob = blob;
// continue from here
}
然后当您需要它作为图像时,为它生成一个Object-URL:
var img = new Image(),
url = URL.createObjectURL(patternAsBlob);
img.onload = function() {
URL.revokeObjectURL(url); // clean up by removing the url object
pattern = canvasctx.createPattern(this, 'repeat');
// continue from here..
};
img.src = url;
如果要加载和设置多个图像,最好使图像加载器在所有资源中加载到数组中,完成后创建模式。
这将简化异步链调用(可选择使用promises,但在没有polyfill的情况下IE尚不支持)。
在较旧的浏览器中,您可能需要使用toblob的polyfill。可以找到一个 here 。
您可能需要“取消修正”createObjectURL()
,这是一种方式:
var domURL = self.URL || self.webkitURL || self;
var url = domURL.createObjectURL( ... );