javascript - Canvas: draw lots of elements with a changing gradient (emulate angular gradient) -


for project http://biduleohm.free.fr/ledohm/ (sorry, user interface in french code in english) need angular gradient doesn't exists in native i've implemented using linear gradient on line , draw lines more , more longer form triangle. result graphically ok speed isn't (1850 ms 125 triangles). it's in tab [répartition], redraws if there keyup event on 1 of inputs, don't afraid of apparent slowness, i've limited maximum 1 redraw every 2000 ms.

before used simple linear gradient on whole triangle (but doesn't match reality) , speed ok, draws thousands of triangles in less second. function used :

drawfrontlightforcolor : function(x, y, w, h, color) {     var x2 = x - w;     var x3 = x + w;     var gradient = distri.frontcanvas.createlineargradient(x2, y, x3, y);     gradient.addcolorstop(0,   'rgba(' + color + ', ' + distri.lightedgealpha + ')');     gradient.addcolorstop(0.5, 'rgba(' + color + ', ' + (color == distri.lightcolors.cw ? distri.lightcenteralphacw : distri.lightcenteralphaother) + ')');     gradient.addcolorstop(1,   'rgba(' + color + ', ' + distri.lightedgealpha + ')');     distri.frontcanvas.fillstyle = gradient;     distri.frontcanvas.beginpath();     distri.frontcanvas.moveto(x, y);     distri.frontcanvas.lineto(x2, (y + h));     distri.frontcanvas.lineto(x3, (y + h));     distri.frontcanvas.lineto(x, y);     distri.frontcanvas.fill();     distri.frontcanvas.closepath(); }, 

then switched function :

drawfrontlightforcolor : function(x, y, w, h, centercolor, edgecolor) {     var ratio = w / h;     var tmpy;     var tmpw;     var x2;     var x3;     var gradient;     distri.frontcanvas.linewidth = 1;     (var tmph = 0; tmph < h; tmph++) {         tmpy = y + tmph;         tmpw = math.round(tmph * ratio);         x2 = x - tmpw;         x3 = x + tmpw;         gradient = distri.frontcanvas.createlineargradient(x2, tmpy, x3, tmpy);         gradient.addcolorstop(0, edgecolor);         gradient.addcolorstop(0.5, centercolor);         gradient.addcolorstop(1, edgecolor);         distri.frontcanvas.beginpath();         distri.frontcanvas.moveto(x2, tmpy);         distri.frontcanvas.lineto(x, tmpy);         distri.frontcanvas.lineto(x3, tmpy);         distri.frontcanvas.strokestyle = gradient;         distri.frontcanvas.stroke();         distri.frontcanvas.closepath();     } }, 

you can find whole source here

i can't put beginpath, stroke, closepath out of loop because of gradient changing every iteration (i've tried used last gradient every line (which, ironically, identical first function...) understandable not want).

i accept advice (including redo whole function , modify caller outsource code) improve speed let's 5x (ideally more).

i think took wrong way start : when doing changes of color, have better operate @ pixel level.
yes webgl pixel shader, you'll have fight boilerplate running ok on platform (or lib you).
, anyway there's solution perfect need, , fast enough (a few ms) : use raw pixel data, update them 1 one relevant function, draw result.

the steps :
- create buffer same size canvas.
- iterate through it's pixel, keeping track of x,y of point.
- normalize coordinates match 'space'.
- compute value normalized (x,y) out of data have.
- write color (in example choose greyscale) out of value.
- draw whole buffer canvas.

i did jsfiddle, , here's result 4 data points :

enter image description here

fiddle here : http://jsfiddle.net/gamealchemist/ksm9c/3/

var canvas = document.getelementbyid("canvas"); var ctx = canvas.getcontext('2d'); var width = canvas.width,     height = canvas.height;  // builds image target canvas function buildimage(targetcanvas, valueforxy, somedata) {     var width = targetcanvas.width;     var height = targetcanvas.height;     var tempimg = ctx.createimagedata(width, height);     var buffer = tempimg.data;     var offset = 0;     var xy = [0, 0];     function normalizexy(xy) {         xy[0] = xy[0] / width ;         xy[1] = xy[1] / height;     }     (var y = 0; y < height; y++)     (var x = 0; x < width; x++, offset += 4) {         xy[0] = x; xy[1]=y;         normalizexy(xy);         var val = math.floor(valueforxy(xy, somedata) * 255);         buffer[offset] = val;         buffer[offset + 1] = val;         buffer[offset + 2] = val;         buffer[offset + 3] = 255;     }     ctx.putimagedata(tempimg, 0, 0); }   // return normalized (0->1) value x,y , //      provided data. //    xy 2 elements array function somevalueforxy(xy, somedata) {     var res = 0;     (var = 0; < somedata.length; i++) {         var thisdata = somedata[i];         var dist = math.pow(sq(thisdata[0] - xy[0]) + sq(thisdata[1] - xy[1]), -0.55);         localres = 0.04 * dist;         res += localres;     }     if (res > 1) res = 1;     return res; }  var somedata = [     [0.6, 0.2],     [0.35, 0.8],     [0.2, 0.5],     [0.6, 0.75] ];  buildimage(canvas, somevalueforxy, somedata);  // ------------------------ function sq(x) {     return x * x } 

Comments

Popular posts from this blog

java - WrongTypeOfReturnValue exception thrown when unit testing using mockito -

php - Magento - Deleted Base url key -

android - How to disable Button if EditText is empty ? -