Mark Mark - 1 month ago 6
Javascript Question

How to draw canvas trailing line with opacity

I'm attempting to draw the rotating line in this canvas animation with trailing opacity but it's not working. I've seen this effect with rectangles and arcs but never with a line, so I'm not sure what I need to add.

function radians(degrees) {
return degrees * (Math.PI / 180);
}

var timer = 0;

function sonar() {
var canvas = document.getElementById('sonar');
if (canvas) {
var ctx = canvas.getContext('2d');
var cx = innerWidth / 2,
cy = innerHeight / 2;

canvas.width = innerWidth;
canvas.height = innerHeight;

//ctx.clearRect(0, 0, innerWidth, innerHeight);
ctx.fillStyle = 'rgba(255, 255, 255, 0.5)';
ctx.fillRect(0, 0, innerWidth, innerHeight);

var radii = [cy, cy - 30, innerHeight / 3.33, innerHeight / 6.67];

for (var a = 0; a < 4; a++) {
ctx.beginPath();
ctx.arc(cx, cy, radii[a], radians(0), radians(360), false);
ctx.strokeStyle = 'limegreen';
ctx.stroke();
ctx.closePath();
}

// draw grid lines
for (var i = 0; i < 12; i++) {
var x = cx + cy * Math.cos(radians(i * 30));
var y = cy + cy * Math.sin(radians(i * 30));
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(x, y);
ctx.lineCap = 'round';
ctx.strokeStyle = 'rgba(50, 205, 50, 0.45)';
ctx.stroke();
ctx.closePath();
}

if (timer <= 360) {
timer++;
ctx.beginPath();
ctx.fillstyle = 'limegreen';
ctx.moveTo(cx, cy);
ctx.lineTo(cx + cy * Math.cos(radians(timer)), cy + cy * Math.sin(radians(timer)));
ctx.strokeStyle = 'limegreen';
ctx.stroke();
ctx.closePath();
} else {
timer = 0;
}
requestAnimationFrame(sonar);
}
}
sonar();


jsbin example

Answer

Here are two ways to do this: with a gradient and by adding translucent lines.

Sidenote, you should try and only redraw what you need to redraw. I separated the canvases and put one on top of the other so that we don't redraw the grid all the time.

function radians(degrees) {
  return degrees * (Math.PI / 180);
}





var timer = 0;
function trail() {
   var canvas = document.getElementById('trail');
  
   var ctx = canvas.getContext('2d');
   ctx.clearRect(0, 0, innerWidth, innerHeight);
   var cx = innerWidth / 2,
       cy = innerHeight / 2;
  canvas.width = innerWidth;
    canvas.height = innerHeight;
   if (timer <= 360) {
      timer++;
      ctx.beginPath();
      ctx.fillstyle = 'limegreen';
 
      ctx.moveTo(cx, cy);
      ctx.arc(cx,cy,cy,radians(timer-30),radians(timer));
      ctx.lineTo(cx + cy * Math.cos(radians(timer)), cy + cy * Math.sin(radians(timer)));
     var gradient = ctx.createLinearGradient(
cx+cy*Math.cos(radians(timer)),             cy+cy*Math.sin(radians(timer)),  
cx+cy*0.9*Math.cos(radians(timer-30)),             cy+cy*0.9*Math.sin(radians(timer-30)));
      gradient.addColorStop(0,'limegreen');
      gradient.addColorStop(1,'transparent');
      ctx.strokeStyle='transparent';
      
      ctx.fillStyle =  gradient;
      ctx.fill();
      
      
     
     ctx.beginPath();
     var fade = 10;
     for(var i =0;i<fade;i++)
     {
       
       ctx.moveTo(cx, cy);
      ctx.lineTo(cx+cy*Math.cos(radians(180+timer-i*1.3)),cy+cy*Math.sin(radians(180+timer-i*1.3)));
       ctx.strokeStyle ="rgba(50,205,50,0.1)"; 
       ctx.lineWidth=5;
       ctx.closePath();
       ctx.stroke();
     }
     
    } else {
      timer = 0;
    }
    requestAnimationFrame(trail);
 }
function sonar() {
  var canvas = document.getElementById('sonar');
  if (canvas) {
    var ctx = canvas.getContext('2d');
    var cx = innerWidth / 2,
        cy = innerHeight / 2;
 
    canvas.width = innerWidth;
    canvas.height = innerHeight;

    //ctx.clearRect(0, 0, innerWidth, innerHeight);

    var radii = [cy, cy - 30, innerHeight / 3.33, innerHeight / 6.67];

    for (var a = 0; a < 4; a++) {
      ctx.beginPath();
      ctx.arc(cx, cy, radii[a], radians(0), radians(360), false);
      ctx.strokeStyle = 'limegreen';
      ctx.stroke();
      ctx.closePath();
    }

    // draw grid lines
    for (var i = 0; i < 12; i++) {
      var x = cx + cy * Math.cos(radians(i * 30));
      var y = cy + cy * Math.sin(radians(i * 30));
      ctx.beginPath();
      ctx.moveTo(cx, cy);
      ctx.lineTo(x, y);
      ctx.lineCap = 'round';
      ctx.strokeStyle = 'rgba(50, 205, 50, 0.45)';
      ctx.stroke();
      ctx.closePath();
    }

   }
 }
  sonar();
  trail();
canvas{
position: absolute;
  }
<canvas id=sonar></canvas>
<canvas id=trail></canvas>

Comments