javascript - How can i make my HTML canvas dots move more naturally? -
link code pen here
i opinions on how make canvas dots move in more fluid, liquid way.
i've tried limiting direction number of renders (draw()), has improved little! still lacks fluidity, coming across rigid , 'hard-coded'.
this switch statement way direction set, either passed random integer or previous direction.
switch (direction) { case 1: star.x--; break; case 2: star.x++; break; case 3: star.y--; break; case 4: star.y++; break; case 5: star.y--; star.x--; break; case 6: star.y--; star.x++; break; case 7: star.y++; star.x++; break; case 8: star.y++; star.x--; break; }
thanks!
you can by:
- generating cardinal spline based on random line points
- walk along line , plot star on current position
why cardinal spline? cardinal spline generate smooth line between set of points. if has tension value. exaggerating tension value (i.e. outside normal [0,1] range) produce curly lines instead.
// draw example lines var ctx = c.getcontext("2d"), p = [0,100, 25,40, 50,70, 75,50, 100,80, 125,32, 150,100, 175,60]; ctx.font = "bold 16px sans-serif"; render(0); render(0.5); render(-2); ctx.settransform(1,0,0,1,0, 110); render(-2, 3, "segments: 3"); render(-2, 9, "segments: 9"); render(-2, 25, "segments: 25"); function render(t, seg, txt) { ctx.beginpath(); ctx.moveto(0, 100); ctx.curve(p, t, seg || 20); ctx.stroke(); ctx.filltext(txt ? txt : (!t ? "plain poly-line" : "cardinal, tension: " + t), 0, 20); ctx.translate(200,0); }
we can take advantage of property , plot point along such line produce liquid-ish movement. movement can refined de/increase segment resolution between each line in spline affect smoothness speed.
other advantages don't have calculate in animation (there initial "peak" when setting points (cache) though), update array pointer , render. , distribution points forces along evenly distributed (invisible) paths.
how implement can vary of course - here 1 example of approach:
example implementation
define star object (it should prototyped sake of demo):
function star(ctx, xseg) { var points = [], // holds points cardinal points cpos = 0, opos = -1, // positions in line len, w = ctx.canvas.width, x = -10, y = -10; // iterates , loop point list this.animate = function() { cpos++; if (cpos > len - 2) { cpos = 0; opos = -1; } var pos = cpos * 2; x = points[pos]; y = points[pos + 1]; drawstar(); } // render star function drawstar() { ctx.rect(x, y, 2, 2); } // generate set of random points, converts // points cardinal spline (linked script). function generatepath() { var w = ctx.canvas.width, h = ctx.canvas.height, numofseg = 20, dh = h / numofseg, i= 0, l, x, y; for(; i<= numofseg; i++) { x = xseg + w / 8 * math.random(); y = h - (i * dh + ((dh / 2) * math.random() - (dh / 4))); points.push(x, y); } points = curve(points, -2, 200 * math.random() + 100); l = points.length; // adjust out of edges for(i = 0; < l; += 2) if (points[i] > w) points[i] -= w; len = points.length / 2; cpos = parseint(len * math.random()); } generatepath(); }
full example
function star(ctx, xseg) { var points = [], // holds points cardinal points cpos = 0, opos = -1, // positions in line len, w = ctx.canvas.width, x = -10, y = -10; this.animate = function() { cpos++; if (cpos > len - 2) { cpos = 0; opos = -1; } var pos = cpos * 2; x = points[pos]; y = points[pos + 1]; drawstar(); }; function drawstar() { ctx.moveto(x + 2, y); ctx.arc(x, y, 2, 0, math.pi*2); } function generatepath() { var w = ctx.canvas.width, h = ctx.canvas.height, numofseg = 20, dh = h / numofseg, i= 0, l, x, y; for(; <= numofseg; i++) { x = xseg + w / 8 * math.random(); y = h - (i * dh + ((dh / 2) * math.random() - (dh / 4))); points.push(x, y); } points = getcurvepoints(points, -2, (400 * math.random() + 200)|0); l = points.length; for(i = 0; < l; += 2) if (points[i] > w) points[i] -= w; len = points.length / 2; cpos = (len * math.random())|0; } generatepath(); } // main code var canvas = document.queryselector("canvas"), ctx = canvas.getcontext("2d"), stars = [], numofstars = 100, segs = canvas.width / numofstars, = 0, throttle = 0, delay = 2; // create stars for(; < numofstars; i++) stars.push(new star(ctx, * segs - segs)); ctx.fillstyle = "#fff"; ctx.shadowcolor ="#fff"; ctx.shadowblur = 7; // animate (function animate() { if (!throttle) { ctx.clearrect(0, 0, canvas.width, canvas.height); ctx.beginpath(); for(var = 0; < stars.length; i++) stars[i].animate(); ctx.fill(); } throttle++; if (throttle === delay) throttle = 0; requestanimationframe(animate); })();
see code cardinal spline implementation in this answer.
another approach use particles , variate velocity using example sinus function. work optimally may need velocity grid instead affect particle based on location. grid can have random directions , velocities.
Comments
Post a Comment