Create reflected image with HTML Canvas?

前端 未结 4 906
长发绾君心
长发绾君心 2021-01-01 05:05

I have the following code which tries to combine a vertical mirrored image with a transparent to background color gradient. When combining these two effects it fails, do I n

相关标签:
4条回答
  • 2021-01-01 05:53

    There 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.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>
    

    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() command did not work. I had to use ctx.rect() and ctx.fill().

    Hope this helps.

    0 讨论(0)
  • 2021-01-01 05:56

    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

    0 讨论(0)
  • 2021-01-01 06:00

    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.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>
    
    0 讨论(0)
  • 2021-01-01 06:07
    <!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 讨论(0)
提交回复
热议问题