2015-10-27 127 views
1

我試圖在畫布中使用cover模擬顯示圖像。我發現了一些很酷的answer關於如何做到這一點。如何在畫布中縮放圖像?

到目前爲止,我的圖像根據屏幕分辨率而變化,但只有在刷新頁面後纔會發生變化。

enter image description here

我怎樣可以得到以下scaling effect無刷新頁面? 嘗試調整窗口的大小。

HTML

<canvas id="canvas"></canvas> 

JS

var ctx = canvas.getContext('2d'), 
    img = new Image; 

canvas.setAttribute('width', window.innerWidth); 
canvas.setAttribute('height', window.innerHeight); 

img.onload = draw; 
img.src = 'https://upload.wikimedia.org/wikipedia/commons/0/0f/2010-02-19_3000x2000_chicago_skyline.jpg'; 

function draw() { 
    drawImageProp(ctx, this, 0, 0, canvas.width, canvas.height); 
} 

/** 
* By Ken Fyrstenberg 
* 
* drawImageProp(context, image [, x, y, width, height [,offsetX, offsetY]]) 
* 
* If image and context are only arguments rectangle will equal canvas 
*/ 
function drawImageProp(ctx, img, x, y, w, h, offsetX, offsetY) { 

    if (arguments.length === 2) { 
     x = y = 0; 
     w = ctx.canvas.width; 
     h = ctx.canvas.height; 
    } 

    /// default offset is center 
    offsetX = offsetX ? offsetX : 0.5; 
    offsetY = offsetY ? offsetY : 0.5; 

    /// keep bounds [0.0, 1.0] 
    if (offsetX < 0) offsetX = 0; 
    if (offsetY < 0) offsetY = 0; 
    if (offsetX > 1) offsetX = 1; 
    if (offsetY > 1) offsetY = 1; 

    var iw = img.width, 
     ih = img.height, 
     r = Math.min(w/iw, h/ih), 
     nw = iw * r, /// new prop. width 
     nh = ih * r, /// new prop. height 
     cx, cy, cw, ch, ar = 1; 

    /// decide which gap to fill  
    if (nw < w) ar = w/nw; 
    if (nh < h) ar = h/nh; 
    nw *= ar; 
    nh *= ar; 

    /// calc source rectangle 
    cw = iw/(nw/w); 
    ch = ih/(nh/h); 

    cx = (iw - cw) * offsetX; 
    cy = (ih - ch) * offsetY; 

    /// make sure source rectangle is valid 
    if (cx < 0) cx = 0; 
    if (cy < 0) cy = 0; 
    if (cw > iw) cw = iw; 
    if (ch > ih) ch = ih; 

    /// fill image in dest. rectangle 
    ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h); 
} 

回答

2

通話添加到drawwindow resize event

window.onresize = draw; 

這應該做的伎倆。

代替:

drawImageProp(ctx, this, 0, 0, canvas.width, canvas.height); 

通行證imgdraw功能:

drawImageProp(ctx, img, 0, 0, canvas.width, canvas.height); 

然後,移動寬度/ heigth設置成draw功能,導致:

function draw() { 
    canvas.setAttribute('width', window.innerWidth); 
    canvas.setAttribute('height', window.innerHeight); 
    drawImageProp(ctx, img, 0, 0, canvas.width, canvas.height); 
} 

您可能還想要重新啓動重新啓動,繪製位:

var timeOut; 
window.onresize = function(){ 
    if(timeOut) 
     clearTimeout(timeOut); 
    timeOut = setTimeout(draw, 10); 
} 

這防止draw函數被調用幾個每秒倍,而被調整大小的窗口。

這裏的a working example,從codepen分叉。

+0

需要注意的是縮放在畫布上不起作用。在畫布上繪製的內容不能像那樣操作。應該在調整大小的畫布上重新繪製圖像。 – rottenoats

+0

@Grimbode:我想我現在已經知道了。 – Cerbrus

+0

是否最好的做法是清理畫布,然後重繪或重繪得夠好,如果之前的繪圖不再可見?這對性能有什麼影響? –

1

那麼這個工程。

http://codepen.io/anon/pen/KdRwVY

var ctx = canvas.getContext('2d'), 
 
    img = new Image; 
 

 
canvas.setAttribute('width', window.innerWidth); 
 
canvas.setAttribute('height', window.innerHeight); 
 

 
img.onload = draw; 
 
img.src = 'https://upload.wikimedia.org/wikipedia/commons/0/0f/2010-02-19_3000x2000_chicago_skyline.jpg'; 
 

 
function draw() { 
 
    drawImageProp(ctx, img, 0, 0, canvas.width, canvas.height); 
 
} 
 
window.onresize = resize; 
 

 
function resize() { 
 
    canvas.setAttribute('width', window.innerWidth); 
 
    canvas.setAttribute('height', window.innerHeight); 
 
    draw() 
 
} 
 

 
/** 
 
* By Ken Fyrstenberg 
 
* 
 
* drawImageProp(context, image [, x, y, width, height [,offsetX, offsetY]]) 
 
* 
 
* If image and context are only arguments rectangle will equal canvas 
 
*/ 
 
function drawImageProp(ctx, img, x, y, w, h, offsetX, offsetY) { 
 

 
    if (arguments.length === 2) { 
 
    x = y = 0; 
 
    w = ctx.canvas.width; 
 
    h = ctx.canvas.height; 
 
    } 
 

 
    /// default offset is center 
 
    offsetX = offsetX ? offsetX : 0.5; 
 
    offsetY = offsetY ? offsetY : 0.5; 
 

 
    /// keep bounds [0.0, 1.0] 
 
    if (offsetX < 0) offsetX = 0; 
 
    if (offsetY < 0) offsetY = 0; 
 
    if (offsetX > 1) offsetX = 1; 
 
    if (offsetY > 1) offsetY = 1; 
 

 
    var iw = img.width, 
 
    ih = img.height, 
 
    r = Math.min(w/iw, h/ih), 
 
    nw = iw * r, /// new prop. width 
 
    nh = ih * r, /// new prop. height 
 
    cx, cy, cw, ch, ar = 1; 
 

 
    /// decide which gap to fill  
 
    if (nw < w) ar = w/nw; 
 
    if (nh < h) ar = h/nh; 
 
    nw *= ar; 
 
    nh *= ar; 
 

 
    /// calc source rectangle 
 
    cw = iw/(nw/w); 
 
    ch = ih/(nh/h); 
 

 
    cx = (iw - cw) * offsetX; 
 
    cy = (ih - ch) * offsetY; 
 

 
    /// make sure source rectangle is valid 
 
    if (cx < 0) cx = 0; 
 
    if (cy < 0) cy = 0; 
 
    if (cw > iw) cw = iw; 
 
    if (ch > ih) ch = ih; 
 

 
    /// fill image in dest. rectangle 
 
    ctx.drawImage(img, cx, cy, cw, ch, x, y, w, h); 
 
}
<canvas id="canvas"></canvas>

+0

您不必再次設置src .. –

+0

我認爲你需要保持onload,因爲你可以調整窗口的大小,而圖片可能還沒有加載。 –

+0

當你縮放窗口時,這將不斷調整大小(並重新繪製)畫布。這是非常低效的。 – Cerbrus