图片加载失败解决方案 以及canvas即时生成提示图片

1,326 阅读2分钟

目前项目碰到一个问题,有时后台给的图片路径会有404,原来的方案是添加一个onerror把地址重指向一个404的本地默认地址。 但是问题是在于如果默认地址也404.就会造成无限加载

由于项目用的是vue开发,在vue中有一个once的修饰符,咱们先来试试这个办法

看样子是可以的,也没有循环调用,但是这样不行!项目onerror太多了一个个替换位置太麻烦(懒得理直气壮),咱尝试给它封装个方法。

在main注册全局方法(原型链挂载),然后img调用

然后就发现不行的,在一番debug之后才发现果然js基础还是不够,在函数内部去改变原参数的指针这样是不行的,这个函数只能改变url的指针而不能改变intInf.logo的指针,所以这样是没用的,那么怎么办呢?改造一下吧:

这样就ok啦,这个其实也不用函数的,不过这样看上去会好点的样子。

但是!我还有一个想法,如果error返回一个即时生成的图像,是不是就不会有循环请求图片的问题了。 try try:

ok,这就算完成了,页面也显示正常

但是有一些问题,每次error就要重新绘图烦不烦啊,已经画过的可以不可以找地方存着等需要的时候直接用呢, 于是我改良了一下:

但是还有问题,目前是可以绘制图片了,绘制的图片毕竟美观度欠佳,万一要添加已有图片的地址呢?但是如果该地址又404怎么办?于是我又改良了一下下:

完事,到此问题算是解决了。

Vue.prototype.imgError = function (name,url,str) {//name是替换的地址名称,url为默认加载错误图片的地址,str为生成图片的提示语(10字之内)
  if(typeof name !==String){
    for (let key in this){
      if(name===this[key]){
        name=key+'';
        break
      }
    }
  }
  str=str||"图片加载错误"
  window.errorImgUrl= window.errorImgUrl||[];
  window.errorImgUrl.push(event.target.src);//错误的地址不再获取第二次
  url=isErrorImg(url)?false:url
  this[name]=url||generateImg(str);
  //获取默认图片
  function generateImg(str){
    window.imgErrorStr= window.imgErrorStr||[];//所有的提示词数组
    window.imgErrorDataURI= window.imgErrorDataURI||[];//所有已经生成过的图像
    if(window.imgErrorStr.includes(str)){//该提示词的图像是否生成过
        return window.imgErrorDataURI[window.imgErrorStr.indexOf(str)]
    }else{
        return Mapping(str);
    }
  }
  //绘制默认图片
  function Mapping(str){
    var canvas=document.createElement('canvas')
    canvas.width=200;
    canvas.height=200;
    var  context = canvas.getContext('2d');
    context.font="Bold 20px Arial";
    context.fillText(str,(200-str.length*20)/2,90);	
    context.lineWidth =2; //设置线宽
    context.strokeStyle='rgb(100,180,120)';
    context.beginPath(); //路径开始
    context.moveTo(0,0);
    context.lineTo(0,200);
    context.lineTo(200,200);
    context.lineTo(200,0);
    context.lineTo(0,0);
    context.stroke();
    var strDataURI=canvas.toDataURL("image/png"); 
    window.imgErrorStr.push(str);
    window.imgErrorDataURI.push(strDataURI);
    return strDataURI;
  }
  function isErrorImg(url){//该地址是否错误的地址
    for(let i in window.errorImgUrl){
      if(window.errorImgUrl[i].indexOf(url)>=0){
        return true;
      }
    }
    return false;
  }
};