javascript - Continuous gradient along a HTML5 canvas path -


i trying draw continous gradient along path of points, each point has it's own color, using html5 canvas api.

see http://bl.ocks.org/rveciana/10743959 inspiration, effect achieved d3.

there doesn't seem way add multiple linear gradients single canvas path, resorted this: http://jsfiddle.net/51toapv2/

var canvas = document.getelementbyid('canvas'); var ctx = canvas.getcontext('2d');  var pts = [[100, 100, "red"], [150, 150, "green"], [200, 100, "yellow"]];  ctx.linewidth = 20; ctx.linejoin = "round"; ctx.linecap = "round";  (var = 0; < pts.length - 1; i++) {     var begin = pts[i];     var end = pts[i + 1];      ctx.beginpath();     var grad = ctx.createlineargradient(begin[0], begin[1], end[0], end[1]);     grad.addcolorstop(0, begin[2]);     grad.addcolorstop(1, end[2]);     ctx.strokestyle = grad;     ctx.moveto(begin[0], begin[1]);     ctx.lineto(end[0], end[1]);     ctx.stroke(); } 

as can see produces subpar effect paths aren't merged , "line joins" visible.

is possible achieve effect i'm looking canvas api?

you can simple approach interpolating 2 colors along line. if need smooth/shared gradients 2 lines joins @ steeper angles, need calculate , implement line drawing algorithm (almost) scratch. out of scope so, here simpler approach.

that being said - example in link not line several plots of squares of different colors. issues have "hidden" subtle variations.

example

snapshot

this approach requires 2 main functions:

  1. line interpolate function draws each segment in line previous mouse position current position

  2. color interpolate function takes array of colors , interpolate between 2 current colors depending on length, position , segment size.

tweak parameters such segment size, number of colors in array etc. optimal result.

line interpolate function

function plotline(ctx, x1, y1, x2, y2) {    var diffx = math.abs(x2 - x1),      // line length       diffy = math.abs(y2 - y1),       dist = math.sqrt(diffx * diffx + diffy * diffy),       step = dist / 10,               // define resolution       = 0, t, b, x, y;    while (i <= dist) {                 // render circles along line     t = math.min(1, / dist);      x = x1 + (x2 - x1) * t;     y = y1 + (y2 - y1) * t;      ctx.fillstyle = getcolor();       // current color     ctx.beginpath();     ctx.arc(x, y, 10, 0, math.pi*2);     ctx.fill();     += step;   } 

color interpolate function

  function getcolor() {      var r, g, b, t, c1, c2;      c1 = colors[cindex];                           // current color array     c2 = colors[(cindex + 1) % maxcolors];         // next color     t = math.min(1, total / segment);              // calculate t      if (++total > segment) {                       // rotate segment       total = 0;       if (++cindex >= maxcolors) cindex = 0;       // rotate color array     }      r = c1.r + (c2.r - c1.r) * t;                  // interpolate color     g = c1.g + (c2.g - c1.g) * t;     b = c1.b + (c2.b - c1.b) * t;      return "rgb(" + (r|0) + "," + (g|0) + "," + (b|0) + ")";   } 

demo

putting allow draw gradient lines. if don't want draw them manually call plotline() function whenever needed.

// setup code  var c = document.queryselector("canvas"),      ctx = c.getcontext("2d"),      colors = [        {r: 255, g: 0, b: 0},        {r: 255, g: 255, b: 0},        {r: 0, g: 255, b: 0},        {r: 0, g: 255, b: 255},        {r: 0, g: 0, b: 255},        {r: 255, g: 0, b: 255},        {r: 0, g: 255, b: 255},        {r: 0, g: 255, b: 0},        {r: 255, g: 255, b: 0},      ],      cindex = 0, maxcolors = colors.length,      total = 0, segment = 500,      isdown = false, px, py;    setsize();          c.onmousedown = c.ontouchstart = function(e) {    isdown = true;    var pos = getpos(e);    px = pos.x;    py = pos.y;  };    window.onmousemove = window.ontouchmove = function(e) {if (isdown) plot(e)};  window.onmouseup = window.ontouchend = function(e) {    e.preventdefault();    isdown = false  };    function getpos(e) {    e.preventdefault();    if (e.touches) e = e.touches[0];    var r = c.getboundingclientrect();    return {      x: e.clientx - r.left,      y: e.clienty - r.top    }  }    function plot(e) {    var pos = getpos(e);    plotline(ctx, px, py, pos.x, pos.y);    px = pos.x;    py = pos.y;  }    function plotline(ctx, x1, y1, x2, y2) {      var diffx = math.abs(x2 - x1),        diffy = math.abs(y2 - y1),        dist = math.sqrt(diffx * diffx + diffy * diffy),        step = dist / 50,        = 0,        t, b, x, y;        while (i <= dist) {      t = math.min(1, / dist);        x = x1 + (x2 - x1) * t;      y = y1 + (y2 - y1) * t;        ctx.fillstyle = getcolor();      ctx.beginpath();      ctx.arc(x, y, 10, 0, math.pi*2);      ctx.fill();      += step;    }        function getcolor() {          var r, g, b, t, c1, c2;            c1 = colors[cindex];      c2 = colors[(cindex + 1) % maxcolors];      t = math.min(1, total / segment);            if (++total > segment) {        total = 0;        if (++cindex >= maxcolors) cindex = 0;      }          r = c1.r + (c2.r - c1.r) * t;      g = c1.g + (c2.g - c1.g) * t;      b = c1.b + (c2.b - c1.b) * t;          return "rgb(" + (r|0) + "," + (g|0) + "," + (b|0) + ")";    }  }    window.onresize = setsize;  function setsize() {    c.width = window.innerwidth;    c.height = window.innerheight;  }  document.queryselector("button").onclick = function() {    ctx.clearrect(0, 0, ctx.canvas.width, ctx.canvas.height)  };
html, body {background:#777; margin:0; overflow:hidden}  canvas {position:fixed;left:0;top:0;background: #333}  button {position:fixed;left:10px;top:10px}
<canvas></canvas>  <button>clear</button>

tips:

  • the gradient values can pre-populated / cached beforehand
  • the step position in gradient can bound length spread independent of draw speed
  • you can replace brush other path/figures/shapes, combine image based brushes composited current color

Comments

Popular posts from this blog

javascript - Bootstrap Popover: iOS Safari strange behaviour -

Magento/PHP - Get phones on all members in a customer group -

session - Logging Out Using PHP -