Создать отраженное изображение с помощью HTML Canvas?
У меня есть следующий код, который пытается объединить вертикальное зеркальное изображение с прозрачным градиентом цвета фона. Если объединить эти два эффекта не удается, нужно ли накладывать градиент 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;
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>
4 ответов:
Нет необходимости в двух элементах холста. Приведенный ниже код работает.Проверял на Firefox 3.0 в Linux.
Я изменил размеры холста, чтобы лучше видеть его во время тестирования, я сделал холст 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)');Если вы хотите делать все правильно, вам нужно:
ctx.save(); ctx.translate(0, 100); ctx.scale(1, -1); ctx.drawImage(img, 0, 0, 200, 100); ctx.restore();А теперь вы можете нарисовать свой прозрачный градиентный блок, как вам это нужно.
Также, для меня ctx.команда fillRect () не сработала. Мне пришлось использовать ctx.rect () и ctx.заполнять().
Надеюсь, это поможет.
<!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>
Вам не нужно перерисовывать все изображение при создании отражения. Оригинальное отражение просто показывает нижнюю часть изображения. Таким образом, вы перерисовываете меньшую часть изображения, что обеспечивает лучшую производительность, а также вам не нужно создавать линейный градиент, чтобы скрыть нижнюю часть изображения (так как вы никогда не рисуете его).
Вы можете поиграть с 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);Вот ссылка на скрипку
Использование второго холста не обеспечивает очень убедительное Наложение градиента. Возможно, придется пойти с градиентом 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>
Comments