2016-11-09 784 views
1

我正在使用FabricJS作爲項目,我需要能夠設置畫布的背景圖像。畫布可以是任何尺寸,並且可以隨時調整大小。最後,圖像應該始終填充畫布,而不管其大小,但不會以任何方式扭曲。例如,如果我有800x600(WxH)的畫布和1200x700的背景圖像,圖像應該縮小到1029x600,以便覆蓋整個畫布而不會變形。FabricJS設置背景圖像的大小和位置

我已經寫了一個函數,應該計算畫布和圖像的尺寸,並相應地設置圖像的大小和位置,但我很難讓它正常工作。它大部分時間都在使用,但不是「防彈」的。有時圖像會變形,有時候它不會填滿整個畫布。

我想要幫助的是將其重構爲防彈解決方案,無論畫布或圖像的大小如何,它總能滿足我的尺寸標準。我已創建fiddle with the code。小提琴加載一個800x600的畫布,然後設置第一個風景背景圖像,以演示代碼如何確定圖像的大小以覆蓋畫布,然後顯示肖像圖像以顯示圖像是如何扭曲圖像的。

這裏是代碼本身:

var canvas = window._canvas = new fabric.Canvas('c'), 
    canvasOriginalWidth = 800, 
    canvasOriginalHeight = 600, 
    canvasWidth = 800, 
    canvasHeight = 600, 
    canvasScale = .5, 
    photoUrlLandscape = 'https://images8.alphacoders.com/292/292379.jpg', 
    photoUrlPortrait = 'https://presspack.rte.ie/wp-content/blogs.dir/2/files/2015/04/AMC_TWD_Maggie_Portraits_4817_V1.jpg'; 

setCanvasSize({height: canvasHeight, width: canvasWidth}); 
setTimeout(function() { 
    setCanvasBackgroundImageUrl(photoUrlLandscape, 0, 0, 1) 
}, 50) 
setTimeout(function() { 
    setCanvasBackgroundImageUrl(photoUrlPortrait, 0, 0, 1) 
}, 4000) 

function setCanvasSize(canvasSizeObject) { 
    canvas.setWidth(canvasSizeObject.width); 
    canvas.setHeight(canvasSizeObject.height); 
    setZoom(); 
} 
function setZoom() { 
    setCanvasZoom(); 
    canvas.renderAll(); 
} 
function setCanvasZoom() { 
    var width = canvasOriginalWidth; 
    var height = canvasOriginalHeight; 
    var tempWidth = width * canvasScale; 
    var tempHeight = height * canvasScale; 

    canvas.setWidth(tempWidth); 
    canvas.setHeight(tempHeight); 
} 
function setCanvasBackgroundImageUrl(url, top, left, opacity) { 
    if(url && url.length > 0) { 
     fabric.Image.fromURL(url, function(img) { 
      var aspect, scale; 

      if(parseInt(canvasWidth) > parseInt(canvasHeight)) { 
       if(img.width >= img.height) { 
        // Landscape canvas, landscape source photo 
        aspect = img.width/img.height; 

        if(img.width >= parseInt(canvasWidth)) { 
         scale = img.width/parseInt(canvasWidth); 
        } else { 
         scale = parseInt(canvasWidth)/img.width; 
        } 

        img.width = parseInt(canvasWidth) 
        img.height = img.height/scale; 
       } else { 
        // Landscape canvas, portrait source photo 
        aspect = img.height/img.width; 

        if(img.width >= parseInt(canvasWidth)) { 
         scale = img.width/parseInt(canvasWidth); 
        } else { 
         scale = parseInt(canvasWidth)/img.width; 
        } 

        img.width = parseInt(canvasWidth); 
        img.height = img.height * scale; 
       } 
      } else { 
       if(img.width >= img.height) { 
        // Portrait canvas, landscape source photo 
        aspect = img.width/img.height; 

        if(img.height >= parseInt(canvasHeight)) { 
         scale = img.width/parseInt(canvasHeight); 
        } else { 
         scale = parseInt(canvasHeight)/img.height; 
        } 

        img.width = img.width * scale; 
        img.height = parseInt(canvasHeight) 
       } else { 
        // Portrait canvas, portrait source photo 
        aspect = img.height/img.width; 

        if(img.height >= parseInt(canvasHeight)) { 
         scale = img.height/parseInt(canvasHeight); 
        } else { 
         scale = parseInt(canvasHeight)/img.height; 
        } 

        img.width = img.width * scale; 
        img.height = parseInt(canvasHeight); 
       } 
      } 

      canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), { 
       top: parseInt(top) || 0, 
       left: parseInt(left) || 0, 
       originX: 'left', 
       originY: 'top', 
       opacity: opacity ? opacity : 1, 
       scaleX: canvasScale, 
       scaleY: canvasScale 
      }); 

      canvas.renderAll(); 
      setZoom(); 
     }); 
    } else { 
     canvas.backgroundImage = 0; 
     canvas.setBackgroundImage('', canvas.renderAll.bind(canvas)); 

     canvas.renderAll(); 
     setZoom(); 
    } 
}; 
+0

您說要保留圖像的縱橫比,並且希望它填充畫布,但如果圖像的比例與畫布的比例不匹配,則希望的行爲是什麼?你想讓圖像在畫布上裁剪並居中? –

+0

是的,如果有重疊,圖像應該被裁剪並居中(如果可能的話)。我不關心居中,因爲我的應用程序允許用戶移動背景圖像。 – ACIDSTEALTH

回答

2

這裏是一個小提琴要實現這一目標所做的(我認爲):

https://jsfiddle.net/whippet71/7s5obuk2/

用於縮放圖像的代碼是相當直截了當:

function scaleAndPositionImage() { 
     setCanvasZoom(); 

     var canvasAspect = canvasWidth/canvasHeight; 
     var imgAspect = bgImage.width/bgImage.height; 
     var left, top, scaleFactor; 

     if (canvasAspect >= imgAspect) { 
      var scaleFactor = canvasWidth/bgImage.width; 
      left = 0; 
      top = -((bgImage.height * scaleFactor) - canvasHeight)/2; 
     } else { 
      var scaleFactor = canvasHeight/bgImage.height; 
      top = 0; 
      left = -((bgImage.width * scaleFactor) - canvasWidth)/2; 

     } 

     canvas.setBackgroundImage(bgImage, canvas.renderAll.bind(canvas), { 
      top: top, 
      left: left, 
      originX: 'left', 
      originY: 'top', 
      scaleX: scaleFactor, 
      scaleY: scaleFactor 
     }); 
     canvas.renderAll(); 

    } 

基本上你只是想知道是否th圖像的縱橫比大於或小於畫布的縱橫比。一旦你知道你可以計算出比例因子,最後一步就是計算出如何偏移圖像,使其位於畫布中心。

+0

比我想要的更優雅。我試圖單獨解釋每一種可能性。在代碼中看到你的解決方案有助於理解這一點。這很棒!謝謝! – ACIDSTEALTH