下面提供了一个用于在点击时更改图像的脚本,更改将在画布中受到影响。
该脚本在Firefox和Chrome中正常运行,但在Safari
中无效可能是什么原因?
<script>
$(function() {
var house = document.getElementById("house");
var ctxHouse = house.getContext("2d");
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var canvas2 = document.getElementById("canvas2");
var ctxHand = canvas2.getContext("2d");
var FabricLink;
var imageObj = new Image();
var red = new Image();
red.onload = function() {
canvas.width = red.width;
canvas.height = red.height;
var houseImage = new Image();
houseImage.onload = function() {
house.width = houseImage.width;
house.height = houseImage.height;
ctxHouse.drawImage(houseImage, 0, 0);
}
houseImage.src = "images/img.jpg";
ctx.drawImage(red, 0, 0);
imageObj.onload = function() {
var pattern = ctx.createPattern(imageObj, 'repeat');
ctx.globalCompositeOperation = 'source-in';
ctx.rect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = pattern;
ctx.fill();
};
$(imageObj).attr('src', 'images/' + FabricLink + '.png');
}
red.src = "images/img.png";
var imageObj2 = new Image();
var blue = new Image();
blue.onload = function() {
canvas2.width = blue.width;
canvas2.height = blue.height;
var houseImage = new Image();
houseImage.onload = function() {
house.width = houseImage.width;
house.height = houseImage.height;
ctxHouse.drawImage(houseImage, 0, 0);
}
houseImage.src = "images/img.jpg";
ctxHand.drawImage(blue, 0, 0);
imageObj2.onload = function() {
var pattern = ctx.createPattern(imageObj2, 'repeat');
ctxHand.globalCompositeOperation = 'source-in';
ctxHand.rect(0, 0, canvas2.width, canvas2.height);
ctxHand.fillStyle = pattern;
ctxHand.fill();
};
$(imageObj2).attr('src', 'images/' + FabricLink + '.png');
}
blue.src = "images/img.png";
$('#style li').click(
function() {
//we get our current filename and use it for the src
var linkIndex = $(this).attr("data-filename");
$(red).attr('src', 'images/' + linkIndex + '.png');
}
);
$('#Sleeves li').click(
function() {
$("#canvas2").addClass("show-z");
//we get our current filename and use it for the src
var SleevesLink = $(this).attr("data-filename");
$(blue).attr('src', 'images/' + SleevesLink + '.png');
}
);
$('#Fabric li').click(
function() {
//we get our current filename and use it for the src
FabricLink = $(this).attr("data-filename");
$(imageObj2).attr('src', 'images/' + FabricLink + '.png');
$(imageObj).attr('src', 'images/' + FabricLink + '.png');
}
);
$("#Fabric li:first-child").click();
}); // end $(function(){});
</script>
在调试时,我们可以看到 imageObj.onload 在第一次点击时没有被触发,只有在刷新时才会在Safari中发生变化。
jsfiddle.net/qvfx3kz7(在小提琴图片中没有加载,但是添加了完整的代码)
答案 0 :(得分:1)
我不确定Safari究竟出现了什么问题,但我可以看到,只有在请求时才尝试加载资源,使得所有内容过于复杂,这会导致您设置的回调噩梦。 / p>
相反,请准备好您的资产,以便只加载一次。由于您使用的是模式,我将假设每个模式实际上都是一个小图像
因此,不是加载每个小图案图像,而是加载一个sprite-sheet,其中包含all your patterns
从那里,您将能够同步动态生成CanvasPattern,而无需关心任何加载回调。为此,您必须使用第二个屏幕外的画布,您将使用它作为createPattern()
方法的来源:
// really dummy implementation...
function AssetsLoader() {}
AssetsLoader.prototype = Object.create({
addImage: function(objs, cb) {
if (!objs || typeof objs !== 'object') return;
if (!Array.isArray(objs)) objs = [];
var toLoad = objs.length,
imgs = objs.map(loadImage, this);
function loadImage(obj) {
if (!obj.src) return;
this.toLoad++;
var img = new Image();
img.src = obj.src;
img.onload = onimgload;
img.onerror = onimgerror;
return obj.img = img;
}
function onimgload(evt) {
if (--toLoad <= 0 && typeof cb === 'function') cb(imgs);
}
function onimgerror(evt) {
console.warn('failed to load image at ', evt.target.src);
}
}
});
// Some info about our assets, there are an infinity of ways to deal with it,
// You would have to determine yourself what's best for your own case
var dests = {
sofa: {
name: 'sofa',
src: 'https://i.stack.imgur.com/ryO42.png'
},
shirt: {
name: 'shirt',
src: 'https://i.stack.imgur.com/cPNbe.png'
}
};
var patterns = {
name: 'patterns',
src: 'https://i.stack.imgur.com/TdIAJ.png',
positions: {
orange: {
x: 0,
y: 0,
width: 173,
height: 173,
out_width: 75,
out_height: 75
},
violet: {
x: 173,
y: 0,
width: 173,
height: 173,
out_width: 35,
out_height: 35
},
psyche: {
x: 0,
y: 173,
width: 173,
height: 173,
out_width: 25,
out_height: 25
},
pink: {
x: 173,
y: 173,
width: 173,
height: 173,
out_width: 125,
out_height: 125
}
}
}
var assets = new AssetsLoader();
// first load all our images, and only then, start the whole thing
assets.addImage([dests.shirt, dests.sofa, patterns], init);
function init() {
// populate our selects
for (var key in dests) {
dest_select.appendChild(new Option(key, key));
}
for (var key in patterns.positions) {
pat_select.appendChild(new Option(key, key));
}
dest_select.onchange = pat_select.onchange = draw;
var ctx = canvas.getContext('2d');
var offscreenCtx = document.createElement('canvas').getContext('2d');
draw();
function draw() {
var dest = dests[dest_select.value].img;
ctx.canvas.width = dest.width;
ctx.canvas.height = dest.height;
ctx.globalCompositeOperation = 'source-over';
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(dest, 0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'source-in';
// here we generate the CanvasPattern
ctx.fillStyle = getPattern(pat_select.value);
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'luminosity';
ctx.drawImage(dest, 0, 0, canvas.width, canvas.height);
}
// now that we have our patterns loaded in a single sprite-sheet,
// we can generate the CanvasPatterns synchronously
function getPattern(key) {
var pos = patterns.positions[key]; // get our pattern's position in our dictionary
// resize the offscreen canvas so it matches our pattern
offscreenCtx.canvas.width = pos.out_width;
offscreenCtx.canvas.height = pos.out_height;
offscreenCtx.drawImage(patterns.img, pos.x, pos.y, pos.width, pos.height, 0, 0, pos.out_width, pos.out_height);
return offscreenCtx.createPattern(offscreenCtx.canvas, 'repeat');
}
}
&#13;
<select id="dest_select"></select>
<select id="pat_select"></select>
<br><br><br>
<canvas id="canvas"></canvas>
&#13;