UI很忙?那我自己做雪碧圖

某某講啊發表於2019-07-31

引言

作為一名前端工程師(菜鳥),我們在做專案的時候可能會用到很多小圖片,需要我們將這些小圖片歸納到一張圖片上,也就是製作成雪碧圖。講道理,這個應該交給ui來做才對,可領導說ui很忙,讓我自己想辦法。於是自己就瞎搗鼓了一下,沒想到效果還可以(自我感覺良好0.0),因為是使用的float佈局的,所以圖片新增順序不合適的話,會產生大量留白(珍惜頭髮)。

預覽

githup地址:github.com/moumoujiang…

UI很忙?那我自己做雪碧圖

思路

  1. 圖片上傳預覽 --> 合理的調整小圖片的位置

  2. 將圖片繪製到canvas上 --> 這張圖不就相當與是雪碧圖嗎

  3. 生成對應的樣式 --> 靈機一動,與其一個個去找背景圖位置,不如直接寫出來

    :整體程式碼都比較簡單,唯一取巧的地方就是canvas區與圖片區大小保持一致,使用小圖片的offsetLeft - 圖片區的offsetLeft來記錄圖片的位置(offsetTop同理),此時的位置恰好可作為canvas每次繪製小圖片的位置,也是每張小圖片的背景位置。

圖片上傳預覽

// 上傳預覽圖片
    $(".selectImgInput").change(function(e) {
      for(let i=0;i<e.target.files.length;i++) {
        let file = e.target.files.item(i);
        //允許檔案MIME型別 也可以在input標籤中指定accept屬性
        //console.log(/^image\/.*$/i.test(file.type));
        if(!(/^image\/.*$/i.test(file.type))) {
          continue;      //不是圖片 就跳出這一次迴圈
        }
        //例項化FileReader API
        var freader = new FileReader();
        let img = document.createElement('img');
        freader.readAsDataURL(file);
        freader.onload=function(e) {
          // var img = '<img src="'+e.target.result+'" class="img" alt="'+file.name.split(".")[0]+ '" />';
          img.src = e.target.result
          img.alt = file.name.split(".")[0]
          img.className = 'img'
          $(".imgs").append(img);
        }
        freader.onloadend = function(e) {
          if($('.imgs').eq(0).height() < img.offsetTop + img.height) {
            $('.imgs').eq(0).height(img.offsetTop + img.height)
          }
        }
      }
    })
複製程式碼

將圖片繪製到canvas上

這裡我們使用transparent來清空canvas畫布,這樣可以生成透明的圖片

$(".product").click(function() {
      var drawW = $('.imgs')[0].offsetLeft;;
      var drawH = $('.imgs')[0].offsetTop;
      var canvas = document.getElementById("canvas")
      var ctx = canvas.getContext('2d')
      console.log($('.imgs').eq(0).height())
      var width = canvas.width = 400;
      var height = canvas.height = $('.imgs').eq(0).height() + 10;
      ctx.fillStyle = 'transparent';
      ctx.fillRect(0,0,width,height);
      var len = $('.img').length;
      var sccStyle = `
.sprites{
  display: inline-block;
  backGround: url(./sprites.png);
}
`;
      for(let i=0;i<len;i++) {
        var img = $('.img')[i]
        // console.log(img)
        var x = $('.img')[i].offsetLeft - drawW;
        var y = $('.img')[i].offsetTop - drawH;
        ctx.drawImage(img,0,0, img.width, img.height, x, y, img.width, img.height);
        var className = img.alt

    })
複製程式碼

生成對應的樣式

知道了每張小圖在canvas畫布上的位置,即上文中的x, y;如不加以利用豈不天理難容?於是就有了css樣式的這個部分。

        sccStyle += `
.sp_${className}{
  width: ${img.width}px;
  heihgt: ${img.height}px;
  background-position: ${x}px ${y}px;
}
`
      }
      html = `
<pre>
${sccStyle}
</pre>
`
      $(".css_sprites").html(html)
複製程式碼

下載雪碧圖

在這裡我是使用a標籤進行下載的

// 下載雪碧圖
    $('.download').click(function(e) {
      var canvas = document.getElementById("canvas")
      var MIME_TYPE = "image/png";
      var imgURL = canvas.toDataURL(MIME_TYPE);

      var dlLink = document.createElement('a')
      dlLink.download = 'sprites';
      dlLink.href = imgURL;
      dlLink.dataset.downloadurl = [MIME_TYPE, dlLink.download, dlLink.href].join(':');

      document.body.appendChild(dlLink);
      dlLink.click();
      document.body.removeChild(dlLink);
    })
  })
複製程式碼

最後

這個程式碼都非常簡單,沒有什麼複雜的邏輯,如果大家有什麼更好的方案也可以自己嘗試實現一個,別忘了@我,大家一起學習。寫東西可能不實用,但更多的是相互學習處理業務的方法,對場景的考量。

相關文章