圖片載入失敗解決方案 以及canvas即時生成提示圖片

Finyu發表於2019-03-12

目前專案碰到一個問題,有時後臺給的圖片路徑會有404,原來的方案是新增一個onerror把地址重指向一個404的本地預設地址。 但是問題是在於如果預設地址也404.就會造成無限載入

由於專案用的是vue開發,在vue中有一個once的修飾符,我們們先來試試這個辦法

圖片載入失敗解決方案 以及canvas即時生成提示圖片

圖片載入失敗解決方案 以及canvas即時生成提示圖片

看樣子是可以的,也沒有迴圈呼叫,但是這樣不行!專案onerror太多了一個個替換位置太麻煩(懶得理直氣壯),我們嘗試給它封裝個方法。

在main註冊全域性方法(原型鏈掛載),然後img呼叫

圖片載入失敗解決方案 以及canvas即時生成提示圖片

然後就發現不行的,在一番debug之後才發現果然js基礎還是不夠,在函式內部去改變原引數的指標這樣是不行的,這個函式只能改變url的指標而不能改變intInf.logo的指標,所以這樣是沒用的,那麼怎麼辦呢?改造一下吧:

圖片載入失敗解決方案 以及canvas即時生成提示圖片

圖片載入失敗解決方案 以及canvas即時生成提示圖片

這樣就ok啦,這個其實也不用函式的,不過這樣看上去會好點的樣子。

但是!我還有一個想法,如果error返回一個即時生成的影象,是不是就不會有迴圈請求圖片的問題了。 try try:

圖片載入失敗解決方案 以及canvas即時生成提示圖片

ok,這就算完成了,頁面也顯示正常

圖片載入失敗解決方案 以及canvas即時生成提示圖片
但是有一些問題,每次error就要重新繪圖煩不煩啊,已經畫過的可以不可以找地方存著等需要的時候直接用呢, 於是我改良了一下:

圖片載入失敗解決方案 以及canvas即時生成提示圖片

但是還有問題,目前是可以繪製圖片了,繪製的圖片畢竟美觀度欠佳,萬一要新增已有圖片的地址呢?但是如果該地址又404怎麼辦?於是我又改良了一下下:

圖片載入失敗解決方案 以及canvas即時生成提示圖片

完事,到此問題算是解決了。

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;
  }
};複製程式碼

相關文章