In a 2D canvas, is there a way to give a sprite an outline?

前端 未结 3 569
刺人心
刺人心 2020-12-04 03:40

I\'d like to give a sprite an outline when the character gets healed/damaged/whatever but I can\'t think of a way to code this using the 2d canvas. If it were possible, I\'

相关标签:
3条回答
  • 2020-12-04 04:10

    Maybe it would be worth trying this :

    • build a canvas 1.1 time bigger than the original sprite
    • fill it with the outline color
    • draw the sprite scaled by 1.1 on the canvas using destination-in globalCompositeOperation.

    Then you have a bigger 'shadow' of your sprite in the outline color.

    When you want to draw the outline :

    • draw the 'shadow' (centered)
    • draw your sprite within the shadow.

    Depending on the convexity of your sprite, this will work more or less nicely, but i think it's worth trying since it avoids you doubling the number of input graphic files.

    I just did a short try as proof-of-concept and it quite works :
    http://jsbin.com/dogoroxelupo/1/edit?js,output

    Before : enter image description here

    After : enter image description here

    html

    <html>
    <body>
      <image src='http://www.gifwave.com/media/463554/cartoons-comics-video-games-sprites-scott-pilgrim-paul-robertson_200s.gif' id='spr'></image>
      <canvas id='cv' width = 500 height= 500 ></canvas>
    </body>
    </html>
    

    code

    window.onload=function() {
      var spr = document.getElementById('spr');
      var margin = 4;
      var gh = createGhost(spr, '#F80', margin);
      var cv = document.getElementById('cv');
      var ctx = cv.getContext('2d');
      var outlined = true;
      setInterval(function() {
         ctx.clearRect(0,0,cv.width, cv.height);
         if (outlined)       
           ctx.drawImage(gh, 0, 0)
         ctx.drawImage(spr, 0, 0)
         outlined = !outlined;
      }, 400);
    }
    
    function createGhost (img, color, margin) {
      var cv= document.createElement('canvas');
      cv.width = img.width+2*margin;
      cv.height = img.height + 2*margin;
      var ctx = cv.getContext('2d');
      ctx.fillStyle = color;
      ctx.fillRect(0,0, cv.width, cv.height);
      ctx.save();
      ctx.globalCompositeOperation = 'destination-in';
      var scale = cv.width/spr.width;
      ctx.scale(cv.width/spr.width, cv.height/spr.height); 
      ctx.drawImage(img, -margin, -margin);
      ctx.restore();
      return cv;  
    }
    
    0 讨论(0)
  • 2020-12-04 04:14
    • Just draw your original image in 8 position around the original image
    • Change composite mode to source-in and fill with the outline color
    • Change composite mode back to source-over and draw in the original image at correct location

    This will create a clean sharp outline with equal border thickness on every side. It is not so suited for thick outlines however. Image drawing is fast, especially when image is not scaled so performance is not an issues unless you need to draw a bunch (which in that case you would cache the drawings or use a sprite-sheet anyways).

    Example:

    var ctx = canvas.getContext('2d'),
        img = new Image;
    
    img.onload = draw;
    img.src = "http://i.stack.imgur.com/UFBxY.png";
    
    function draw() {
    
      var dArr = [-1,-1, 0,-1, 1,-1, -1,0, 1,0, -1,1, 0,1, 1,1], // offset array
          s = 2,  // scale
          i = 0,  // iterator
          x = 5,  // final position
          y = 5;
      
      // draw images at offsets from the array scaled by s
      for(; i < dArr.length; i += 2)
        ctx.drawImage(img, x + dArr[i]*s, y + dArr[i+1]*s);
      
      // fill with color
      ctx.globalCompositeOperation = "source-in";
      ctx.fillStyle = "red";
      ctx.fillRect(0,0,canvas.width, canvas.height);
      
      // draw original image in normal mode
      ctx.globalCompositeOperation = "source-over";
      ctx.drawImage(img, x, y);
    }
    <canvas id=canvas width=500 height=500></canvas>

    0 讨论(0)
  • 2020-12-04 04:34

    You could use strokeRect method to outline the sprite after drawing it. It should be asy if you know your sprite's dimensions...

    0 讨论(0)
提交回复
热议问题