JSFiddle - React, Tailwind, and code Playground

by neosoyn

HTML

<h4>Creating a gradient running across a path</h4>
<canvas id="canvas" width=300 height=300></canvas>

CSS

body {
    background-color: ivory;
}
#canvas {
    border:1px solid red;
}

JavaScript

// canvas related variables
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");

// variables defining a cubic bezier curve
var PI2 = Math.PI * 2;
var s = {
    x: 20,
    y: 30
};
var c1 = {
    x: 200,
    y: 40
};
var c2 = {
    x: 40,
    y: 200
};
var e = {
    x: 270,
    y: 220
};

// an array of points plotted along the bezier curve
var points = [];

// we use PI often so put it in a variable
var PI = Math.PI;

// plot 400 points along the curve
// and also calculate the angle of the curve at that point
for (var t = 0; t <= 100; t += 0.25) {

    var T = t / 100;

    // plot a point on the curve
    var pos = getCubicBezierXYatT(s, c1, c2, e, T);

    // calculate the tangent angle of the curve at that point
    var tx = bezierTangent(s.x, c1.x, c2.x, e.x, T);
    var ty = bezierTangent(s.y, c1.y, c2.y, e.y, T);
    var a = Math.atan2(ty, tx) - PI / 2;

    // save the x/y position of the point and the tangent angle
    // in the points array
    points.push({
        x: pos.x,
        y: pos.y,
        angle: a
    });

}


// Note: increase the lineWidth if 
// the gradient has noticable gaps 
ctx.lineWidth = 2;

// draw a gradient-stroked line tangent to each point on the curve
for (var i = 0; i < points.length; i++) {

    // calc the topside and bottomside points of the tangent line
    var offX1 = points[i].x + 20 * Math.cos(points[i].angle);
    var offY1 = points[i].y + 20 * Math.sin(points[i].angle);
    var offX2 = points[i].x + 20 * Math.cos(points[i].angle - PI);
    var offY2 = points[i].y + 20 * Math.sin(points[i].angle - PI);

    // create a gradient stretching between 
    // the calculated top & bottom points
    var gradient = ctx.createLinearGradient(offX1, offY1, offX2, offY2);
    gradient.addColorStop(0.00, 'red');
    gradient.addColorStop(1 / 6, 'orange');
    gradient.addColorStop(2 / 6, 'yellow');
    gradient.addColorStop(3 / 6, 'green')
    gradient.addColorStop(4 / 6, 'aqua');
   ...