Создать отраженное изображение с помощью 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>
592   4  

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

    Ничего не найдено.