2009-11-07 49 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