admin管理员组文章数量:1289986
I have the following code which tries to bine a vertical mirrored image with a transparent to background color gradient. When bining these two effects it fails, do I need to overlay a PNG gradient over the canvas instead of trying to get the canvas to perform both operations?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
".dtd">
<html xmlns="">
<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>
I have the following code which tries to bine a vertical mirrored image with a transparent to background color gradient. When bining these two effects it fails, do I need to overlay a PNG gradient over the canvas instead of trying to get the canvas to perform both operations?
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3/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>
Share
Improve this question
asked Nov 7, 2009 at 15:07
Greg KGreg K
11.1k11 gold badges46 silver badges62 bronze badges
2
- I tested this with 'black' and 'white' color stops before trying transparent. I can apply just the gradient, or just the reflected image but not both. – Greg K Commented Nov 7, 2009 at 15:08
- If the canvas is supported in your browser, chances are that some CSS3 will be supported too ... you can create reflections (iTunes style) with CSS3 only - no need for JavaScript. s3.amazonaws./nettuts/704_cssReflections/index.html – Greg Commented Jun 3, 2011 at 8:03
4 Answers
Reset to default 3There is no need for 2 canvas elements. The code below works.Tested it on FireFox 3.0 on Linux.
I have changed the canvas sizes so I could see it better while testing, I made the canvas 200 x 100 pixels. You will need to resize back to your needs (75x20). For testing purposes, I've made the overlay 100x100 pixels so I could see half the image with a gradient.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3/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>
Edit to explain some of this:
I think you were basically missing the alpha attribute on the gradient.
grad.addColorStop(0.7, 'rgba(255,255,255,0)');
The fourth parameter is alpha. Also, since you flip the canvas upside down, the gradient is currently drawn upside down (hence the second color stop has the transparency on it, and yet the block is transparent on the top side).
If you wanted to do things correctly, you would need to:
ctx.save();
ctx.translate(0, 100);
ctx.scale(1, -1);
ctx.drawImage(img, 0, 0, 200, 100);
ctx.restore();
And now you can draw your transparent gradient block as you need it.
Also, for me the ctx.fillRect() mand did not work. I had to use ctx.rect() and ctx.fill().
Hope this helps.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3/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>
You don't need to redraw the entire image when creating a reflection. An original reflection simply shows the bottom part of the image. This way you are redrawing a smaller part of the image which provides better performance and also you don't need to create linear gradient to hide the lower part of the image (since you never draw it).
You can play around with REFLECTION_HEIGHT and opacity to get desired results.
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);
Here is a link to the fiddle
Using a second canvas doesn't provide a very convincing gradient overlay. May have to go with a gradient PNG for decent results.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3/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>
本文标签: javascriptCreate reflected image with HTML CanvasStack Overflow
版权声明:本文标题:javascript - Create reflected image with HTML Canvas? - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741448121a2379323.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论