skip to Main Content

I’m using the stroke and path in the canvas to make two lines, which i’m wanting to curve like a wave effect. Instead of creating an actual image in Photoshop to achieve this.

Could anybody help with getting the curves like the example picture below?

I also want to achieve the rounded curve to the straight edge at end, is this possible with stroke path?

enter image description here

What I have so far:

(function($){
  var $canvas,
      fnInitWaves,
      fnDrawWave,
      tmrResize;
  
  fnDrawWave = function(canvas){
    var $this = $(canvas), $outer, iWidth, iHeight, iMidWidth, iQuartWidth, iLineWidth, iFillLineWidth, ctx, ctx1;
      
      $outer = $this.parent();
      
      iWidth = $outer.outerWidth();
      iHeight = $outer.outerHeight() - 30;
      iMidWidth = Math.floor(iWidth / 2);
      iQuartWidth = Math.floor(iMidWidth / 2);
      
      iLineWidth = 10;
      iFillLineWidth = 6;

      $this.attr({width: iWidth, height: 100});
      
      ctx = canvas.getContext('2d');
	  ctx1 = canvas.getContext('2d');
	  
      // Wave init
      ctx.lineWidth = iLineWidth;
      ctx.strokeStyle = '#284762';
      ctx.beginPath();
      ctx.moveTo(0, iHeight * 1);
	 
      // Wave peak
      ctx.quadraticCurveTo(iQuartWidth, -(iHeight / 2.5) + iLineWidth, iMidWidth, iHeight / 2.5);
	  
      // Wave valley
      ctx.quadraticCurveTo(iQuartWidth + iMidWidth, (iHeight * 1.5) - iLineWidth, iWidth, iHeight / 4);
	  
      // Wave end
      ctx.lineCap = 'round';
      ctx.stroke();
      ctx.closePath();
	 	  
	  // Wave init
      ctx1.lineWidth = iLineWidth;
      ctx1.strokeStyle = '#efc833';
      ctx1.beginPath();
      ctx1.moveTo(20, iHeight / 1);
	 	
	  ctx1.quadraticCurveTo(iQuartWidth, -(iHeight / 6) + iLineWidth, iMidWidth, iHeight / 2);
	  ctx1.quadraticCurveTo(iQuartWidth + iMidWidth, (iHeight * 1.5) - iLineWidth, iWidth, iHeight / 1.5);
	  
	  ctx1.lineCap = 'round';
      ctx1.stroke();
      ctx1.closePath();
  };
  
  fnInitWaves = function(){    
    $canvas.each(function(i, el){
      fnDrawWave(el);
    });
  };
  
  $(function(){
    $canvas = $('canvas.wave');
    fnInitWaves.apply(undefined);
  });
  
  $(window).on('resize', function(){
    clearTimeout(tmrResize);
    tmrResize = setTimeout(fnInitWaves, 250);
  });
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="wave-outer">
	<canvas class="wave" width="685" height="96"></canvas>  
</div>

2

Answers


  1. Chosen as BEST ANSWER

    So by taking a look at Developer Nodejs answer. I was able to achieve the result I wanted.

    Please take a look at my example:

    function Draw(){
    
    canvas = document.getElementById("canvas")
    ctx = canvas.getContext('2d');
    
    var $this = $(canvas),$outer, iWidth, iHeight, iMidWidth, iQuartWidth, iLineWidth, iFillLineWidth;
    $outer = $this.parent();   
    iWidth = $outer.outerWidth();
    iHeight = $outer.outerHeight() - 30;
    iMidWidth = Math.floor(iWidth / 2);
    iQuartWidth = Math.floor(iMidWidth / 2);  
    iLineWidth = 10;
    iFillLineWidth = 6;
    
    iWidth = $outer.outerWidth();
    iHeight = $outer.outerHeight() - 30;
    $this.attr({width: iWidth, height: 150});
    
    yellowWave(ctx, iWidth, iHeight, iMidWidth, iQuartWidth);
    blueWave(ctx, iWidth, iHeight, iMidWidth, iQuartWidth);
    
    console.log("Curved Lines."); 
      
    }
    
    function blueWave(ctx, width, height,
    iMidWidth, iQuartWidth){
      var cp1 = iQuartWidth;
      var cp2 = -(height / 1);
      var cp3 = iMidWidth;
      var cp4 = height * 2.5;
      var endX = width;
      var endY = height / 4;
      ctx.lineWidth = 50;
      ctx.strokeStyle = '#284762';
      ctx.beginPath();
      ctx.moveTo(-20, height);
      ctx.bezierCurveTo(
        cp1, 
        cp2,
        cp3,
        cp4, 
        endX, 
        endY
      );
    
    
      ctx.lineCap = 'round';
      ctx.stroke();
      ctx.closePath();
    }
    
    function yellowWave(ctx, width, height,
    iMidWidth, iQuartWidth){
      var cp1 = iQuartWidth;
      var cp2 = -(height / 2.5);
      var cp3 = iMidWidth;
      var cp4 = height * 3.5;
      var endX = width + 50;
      var endY = height / 1.7;
      ctx.lineWidth = 40
      ctx.strokeStyle = '#efc833';
      ctx.beginPath();
      ctx.moveTo(-10, height - 10);
      ctx.bezierCurveTo(
        cp1, 
        cp2,
        cp3,
        cp4, 
        endX, 
        endY
      );
    
    
      ctx.lineCap = 'round';
      ctx.stroke();
      ctx.closePath();
    }
    
    Draw();
    .wave {
      background-color: transparent;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <div class="wave-outer">
    	<canvas id="canvas" class="wave" width="685" height="96"></canvas>  
    </div>


  2. Drawing curves on canvas can be done using bezierCurveTo function:

    function draw() {
      var canvas = document.getElementById('canvas');
      if (canvas.getContext) {
        var ctx = canvas.getContext('2d');
        ctx.beginPath();
        ctx.moveTo(25, 100);
        ctx.bezierCurveTo(50, 200, 75, 50, 100, 100);
        ctx.stroke();
      }
    }
    draw()
    

    Updated answer:

    function Draw(){
    
    canvas = document.getElementById("canvas")
    ctx = canvas.getContext('2d');
    
    var $this = $(canvas),$outer, iWidth, iHeight, iMidWidth, iQuartWidth, iLineWidth, iFillLineWidth;
    $outer = $this.parent();   
    iWidth = $outer.outerWidth();
    iHeight = $outer.outerHeight() - 30;
    iMidWidth = Math.floor(iWidth / 2);
    iQuartWidth = Math.floor(iMidWidth / 2);  
    iLineWidth = 10;
    iFillLineWidth = 6;
    
    iWidth = $outer.outerWidth();
    iHeight = $outer.outerHeight() - 30;
    $this.attr({width: iWidth, height: 100});
    
    blueWave(ctx, iWidth, iHeight, iMidWidth, iQuartWidth);
    yellowWave(ctx, iWidth, iHeight, iMidWidth, iQuartWidth);
    
    console.log("Curved Lines."); 
    
    }
    
    function blueWave(ctx, width, height,
    iMidWidth, iQuartWidth){
      var cp1 = iQuartWidth;
      var cp2 = -(height / 2.5);
      var cp3 = iMidWidth;
      var cp4 = height * 2.5;
      var endX = width;
      var endY = height / 4;
      ctx.lineWidth = 16;
      ctx.strokeStyle = '#284762';
      ctx.beginPath();
      ctx.moveTo(0, height);
      ctx.bezierCurveTo(
        cp1, 
        cp2,
        cp3,
        cp4, 
        endX, 
        endY
      );
    
    
      ctx.lineCap = 'round';
      ctx.stroke();
      ctx.closePath();
    }
    
    function yellowWave(ctx, width, height,
    iMidWidth, iQuartWidth){
      var cp1 = iQuartWidth;
      var cp2 = -(height / 2.5);
      var cp3 = iMidWidth;
      var cp4 = height * 2.5;
      var endX = width;
      var endY = height / 3.25;
      ctx.lineWidth = 14;
      ctx.strokeStyle = '#efc833';
      ctx.beginPath();
      ctx.moveTo(6, height + 10);
      ctx.bezierCurveTo(
        cp1, 
        cp2,
        cp3,
        cp4, 
        endX, 
        endY
      );
    
    
      ctx.lineCap = 'round';
      ctx.stroke();
      ctx.closePath();
    }
    
    Draw();
    

    Original answer: http://jsbin.com/dejatihogo/edit?js

    Updated answer: https://jsbin.com/fopesacisa/1/edit?output

    The main issue why your lines look crooked or skwed is because you are using the quadratic curves to tie two curved lines together. Instead, use a bezier function so you can bend the one line at two different control points.

    Also, no need to duplicate getContext(‘2d’). One is enough.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search