2009-11-07 48 views
4

我有以下代碼,它試圖將垂直鏡像圖像與透明背景顏色漸變相結合。當組合這兩種效果失敗時,是否需要在畫布上疊加PNG漸變而不是試圖讓畫布執行這兩種操作?使用HTML畫布創建反射圖像?

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" /> 
    <style type="text/css"> 
     body { 
      background-color: #eee; 
      text-align: center; 
      padding-top: 150px; 
     } 
    </style> 
    <script type="text/javascript"> 
     var img = new Image(); 
     img.onload = function() {    
      var ctx = document.getElementById("output").getContext("2d"); 
      // reflect image 
      ctx.translate(0, 75); 
      ctx.scale(1, -1); 
      ctx.drawImage(img, 0, 0, 75, 75); 

      // add gradient 
      var grad = ctx.createLinearGradient(0, 0, 0, 20); 
      grad.addColorStop(0, 'transparent'); 
      grad.addColorStop(1, '#eeeeee'); 

      ctx.fillStyle = grad; 
      ctx.fillRect(0, 0, 75, 20); 
     }; 

     img.src = "test.jpg"; 
    </script> 
</head> 
<body> 
    <div><img src="test.jpg" height="75" width="75" /></div> 
    <canvas id="output" width="75" height="20"></canvas> 
</body> 
</html> 
+0

的鏈接試圖透明之前停止。我可以僅應用漸變,或者僅應用反射圖像,但不能同時應用兩者。 – 2009-11-07 15:08:30

+0

如果您的瀏覽器支持畫布,則可能也會支持一些CSS3 ......您可以使用CSS3創建反射(iTunes樣式) - 無需使用JavaScript。 http://s3.amazonaws.com/nettuts/704_cssReflections/index.html – Greg 2011-06-03 08:03:19

回答

3

不需要2個畫布元素。下面的代碼工作。在Linux上對FireFox 3.0進行測試。

我已經更改了畫布尺寸,以便在測試時可以更好地看到它,我製作了200 x 100像素的畫布。您需要調整回到您的需求(75x20)。出於測試目的,我製作了100x100像素的覆蓋圖,以便我可以看到一半圖像具有漸變效果。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" /> 
<style type="text/css"> 
    body { 
      background-color: #eee; 
      text-align: center; 
      padding-top: 150px; 
    } 
</style> 
<script type="text/javascript"> 
    var img = new Image(); 
    img.onload = function() { 
      var ctx = document.getElementById("output").getContext("2d"); 
      // reflect image 
      ctx.translate(0, 100); 
      ctx.scale(1, -1); 
      ctx.drawImage(img, 0, 0, 200, 100); 

      // add gradient 
      var grad = ctx.createLinearGradient(0, 0, 0, 100); 
      grad.addColorStop(0.3, 'rgb(255,255,255)'); 
      grad.addColorStop(0.7, 'rgba(255,255,255,0)'); 

      ctx.fillStyle = grad; 
      ctx.translate(0,0); 
      ctx.rect(0, 0, 100, 100); 
      ctx.fill(); 
    }; 

    img.src = "img/avatarW3.png"; 
</script> 

<canvas id="output" width="200" height="100" style="border:1px solid black;"></canvas> 

編輯解釋一些這樣:

我認爲你是缺少基本的梯度阿爾法屬性。

grad.addColorStop(0.7, 'rgba(255,255,255,0)'); 

第四個參數是alpha。此外,由於您將畫布翻轉過來,因此漸變現在是上下顛倒的(因此第二個顏色停止處具有透明度,而頂部則是透明的)。

如果你想要做正確的事情,你將需要:

ctx.save(); 
ctx.translate(0, 100); 
ctx.scale(1, -1); 
ctx.drawImage(img, 0, 0, 200, 100); 
ctx.restore(); 

而現在,因爲你需要它,你可以畫出你的透明漸變塊。

此外,對我來說,ctx.fillRect()命令不起作用。我不得不使用ctx.rect()和ctx.fill()。

希望這會有所幫助。

+0

非常感謝。還在Mac上的Safari中測試了這一點,所以我想它也可以在Chrome中使用。 我最終改變了一些漸變參數,使反射看起來更加mac-esque。 grad.addColorStop(0,'rgba(238,238,238,0.8)'); grad.addColorStop(1,'rgb(238,238,238)'); – 2009-11-08 13:59:21

0

使用第二個畫布不提供非常有說服力的漸變疊加。可能需要使用漸變PNG才能獲得體面的結果。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
    <meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" /> 
    <style type="text/css"> 
     body { 
      background-color: #eee; 
      padding-top: 150px; 
     } 

     canvas { 
      float: left; 
     } 

     canvas#grad { 
      margin-left: -75px; 
     } 
    </style> 
    <script type="text/javascript"> 
     var img = new Image(); 
     img.src = "test.jpg"; 

     img.onload = function() { 
      var reflect = document.getElementById("reflect").getContext("2d"); 
      // reflect image 
      reflect.translate(0, 75); 
      reflect.scale(1, -1); 
      reflect.drawImage(img, 0, 0, 75, 75); 

      // add gradient 
      var overlay = document.getElementById("grad").getContext("2d"); 
      var grad = overlay.createLinearGradient(0, 0, 0, 15); 
      grad.addColorStop(0, 'transparent'); 
      grad.addColorStop(1, '#eeeeee'); 

      overlay.fillStyle = grad; 
      overlay.fillRect(0, 0, 75, 15); 
     }; 
    </script> 
</head> 
<body> 
    <div> 
     <div><img src="test.jpg" height="75" width="75" /></div> 
     <canvas id="reflect" width="75" height="15"></canvas> 
     <canvas id="grad" width="75" height="15"></canvas> 
    </div> 
</body> 
</html> 
2
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head> 
<meta http-equiv="content-type" content="application/xhtml+xml; charset=UTF-8" /> 
<style type="text/css"> 
    body { 
      background-color: #FFF; 
      text-align: center; 
      padding-top: 100px; 
    } 
</style> 
<script type="text/javascript"> 
    var img = new Image(); 
    img.onload = function() { 
     var c = document.getElementById("output"); 
     var ctx = c.getContext("2d"); 

     /* Maximum Canvas/Image Size 
      i.e supposing image size 640x480 or greater than 399px 
     */ 
     var max = 400; 

     /* Resizing Image/Drawing */ 
     var r = img.width/img.height; 
     if(r>1) 
      ctx.drawImage(img , 0 , 0 , r*max , max); 
     else 
      ctx.drawImage(img , 0 , 0 , max , max/r); 
     ctx.save(); 

     /* Clearing extra spaces */ 
     ctx.clearRect(0, max, c.width , c.height); 

     /* Creating reflection */ 
     ctx.translate(0, max); 
     ctx.scale(1, -1); 
     if(r>1) 
      ctx.drawImage(img , 0 , -max , r*max , max); 
     else 
      ctx.drawImage(img , 0 , max/2 , max , max/2 , 0 , -max/2 , max , max/2); 
     ctx.restore(); 

     /* Adding gradiant */ 
     ctx.globalCompositeOperation = 'destination-out'; 
     var grad = ctx.createLinearGradient(0, Math.floor(c.height-(max/2)) , 0, c.height); 
     grad.addColorStop(1, 'rgba(255,255,255,1.0)'); 
     grad.addColorStop(0, 'rgba(255,255,255,0.8)'); 
     ctx.fillStyle = grad; 
     ctx.fillRect(0, Math.floor(c.height-(max/2)) , max, (max/2)); 
    }; 

    img.src = "a.jpg"; 
</script> 

</head> 
<body> 
<canvas id="output" width="400" height="600" ></canvas> 
</body> 
</html> 
+0

這種方法給你一個透明的反射(這是一件好事)。 – Philippe 2014-10-08 09:59:02

+0

小提琴:https://jsfiddle.net/gwov2784/1/ – Josiah 2015-07-09 17:28:22

0

創建反射時,不需要重新繪製整個圖像。原始反射僅顯示圖像的底部。 通過這種方式,您可以重新繪製圖像的較小部分,從而提供更好的性能,而且您不需要創建線性漸變來隱藏圖像的下半部分(因爲您從不繪製它)。

您可以使用REFLECTION_HEIGHT和不透明度來獲得所需的結果。

var thumbWidth = 250; 
var REFLECTION_HEIGHT = 50; 
var c = document.getElementById("output"); 
var ctx = c.getContext("2d"); 
var x = 1; 
var y = 1; 

//draw the original image 
ctx.drawImage(img, x, y, thumbWidth, thumbWidth); 
ctx.save(); 
//translate to a point from where we want to redraw the new image 
ctx.translate(0, y + thumbWidth + REFLECTION_HEIGHT + 10); 
ctx.scale(1, -1); 
ctx.globalAlpha = 0.25; 

//redraw only bottom part of the image 
//g.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); 
ctx.drawImage(img, 0, img.height - REFLECTION_HEIGHT, img.width, REFLECTION_HEIGHT, x, y, thumbWidth, REFLECTION_HEIGHT); 

下面是我與「黑」與「白」色測試這個fiddle