关于creator webgl模式下跨域加载图片的解决办法

最近开发遇到跨域的问题 creator中制作了动画 用canvas模式会错位 所以不得不面对webgl跨域的问题
纠结好久 南大给了建议是服务器转发 最后也是用这个方法实现的
后台将图片从库里取出来,直接以字节流的形式传过来 此时已经是同域名下的文件
接收到字节流之后创建Image对象 src指向字节流地址 然后通过texture2d的initWithElement来初始化Image对象
最后通过texture2d就能创建spriteframe对象 实现动态加载跨域图片的需求

注意
一定要在image对象onload之后再创建 否则会报webgl的一个错误 = = 蛋疼的要死当时 最后看国外帖子才搞定
generateMipmaps这个参数也是翻帖子翻出来的 可能是修改调默认power of 2的参数 当时那个报错好像有这个的可能 不过具体是因为Onload还是generateMipmaps没再排查 反正都加上没问题了:stuck_out_tongue_closed_eyes:

创建base64的spriteframe也是用这个方法 集体参考我另一个帖子http://forum.cocos.com/t/base64/36960/5 其实光看看这个也没差多少啦 嗯 就这样 之前查了好些地方都不好使就在这说一下经验

补充一点
上周遇到用户上传图片跨域加载的问题 上述方法出现将spriteframe赋值后 即使组件已经有了新的spriteframe也不显示的情况 后来纠结很久发现重新创建一个sprite放上去是可以的 如果遇到这个坑的也可以注意下这点 坑了两天一通宵没爬出来…

10赞

感谢楼主的分享!大家遇到跨域图片问题可以参考下!

留个脚印,日后碰到再回首

var Base64 = {
_keyStr: “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=”,

// public method for encoding 
encode: function encode(input) {
    var output = "";
    var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
    var i = 0;
    //input = Base64._utf8_encode(input); //comment out to encode binary file(like image) 

    while (i < input.length) {

        chr1 = input[i++];
        chr2 = input[i++];
        chr3 = input[i++];

        enc1 = chr1 >> 2;
        enc2 = (chr1 & 3) << 4 | chr2 >> 4;
        enc3 = (chr2 & 15) << 2 | chr3 >> 6;
        enc4 = chr3 & 63;

        if (isNaN(chr2)) {
            enc3 = enc4 = 64;
        } else if (isNaN(chr3)) {
            enc4 = 64;
        }
        output = output + Base64._keyStr.charAt(enc1) + Base64._keyStr.charAt(enc2) + Base64._keyStr.charAt(enc3) + Base64._keyStr.charAt(enc4);
    }
    return output;
}

};

function loadRemoteImg(url) {

var img = null;
var xmlhttp = new XMLHttpRequest();
var xhr = xmlhttp;
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4 && xhr.status === 200) {
        //console.log(xhr.responseText);
        //var res = xhr.responseText;
        var blob = new Uint8Array(this.response);
        var img = new Image();
        var base = "data:image/png;base64," + Base64.encode(blob);
        img.src = base;
        var spriteFrame = spImg.getComponent('cc.Sprite').spriteFrame;
        //var texture=spriteFrame.getTexture();
        var texture = new cc.Texture2D();
        texture.generateMipmaps = false;
        texture.initWithElement(img);
        texture.handleLoadedTexture();
        var newframe = new cc.SpriteFrame(texture);
        spImg.getComponent('cc.Sprite').spriteFrame = newframe;
    }
};
xmlhttp.open("get", url);
xhr.responseType = 'arraybuffer';
xhr.send(null);

};
经过测试的跨域加载图片,base64 编码模式动态加载texture,代码片段

2赞

为什么我还是出现 Access-Control-Allow-Origin ?你确定能用?

generateMipmaps 这个参数没有啊

服务器后台做了转发了么··?

mark 一下

mark一下

marked

标记下 留待以后参考

这个是解决了,但是微信的浏览器不行.

服务器要开启跨域设置,只能这样了

留个脚印,以后再回首。。。

太感谢了 原来是要 image.onload,是说怎么图像要第二次刷新才能出来

marked

egret的做法很简单
var img = new Image() //这个是H5对象

img.crossOrigin = “anonymous”;

img.src = url;

img.onload传回的数据创建显示内容

native没有跨域问题,用默认方式

感觉很简单,为什么creator不使用这种方式呢?只是为了让web和native使用同一套代码?

我们加载图片的时候,初次加载也是用一样的方式 crossOrigin = anonymous 去加载
一般加载起来就用了,这个过程跟 egret 没区别。
区别在于,如果正常的加载失败,才会去掉 crossOrigin 属性再加载一次,失败的情况一般是由于服务端不允许加 anonymous
跨域头。

那明白了,原来LZ是没有加crossdomain.xml

顶上去