javascript - 在 Canvas 中为草制作动画的有效方法

标签 javascript html animation canvas

我一直在尝试使用 canvas 元素的 2d 上下文的功能来尝试创建相对逼真的 3d 场景,目前正在尝试根据 fiddle 创建一个平原的 3d“ish”草地:

http://jsfiddle.net/PlacidCow/j6h7sajz/

我的问题是,为草设置动画以吸收风/物理等影响的最有效方法是什么?

目前我刚刚绘制到屏幕上 - 我已经尝试将每个 Blade 的尺寸存储在一个大数组中,然后需要很长时间才能循环以制作动画(因此是滞后且毫无意义的)。有没有一种有效的方法来绘制每个 Blade ?或者人们会建议为每个 block 设置动画(但是如何解决,因为清除补丁会弄乱前面的 Blade )?重复 Blade 以便它们批量动画?

在网上看过(也许我缺乏谷歌搜索技能......)但我要么找不到任何东西,要么是谨慎的 webgl 演示,要么是 C 等的示例,但这使用的着色器不适用于 2d Canvas 。

c = document.getElementsByTagName('canvas')[0];
ctx = c.getContext('2d');

var v = {
    w: c.clientWidth,
    h: c.clientHeight
};
c.width = v.w;
c.height = v.h;

var base = {
    c: [
        [-1, -1, 0],
        [-1, -1, -1],
        [1, -1, -1],
        [1, -1, 0]
    ],
    f: 'brown',
    d: -3
};

draw(base.c, base.f, base.d);

for (var j=1; j<120; j++) {
    for (var k=1; k<200; k++) {
        var z = -1 + 2*j/199;
        var x = -1 + (2*Math.random())/1.01;
        var y = 0.06+Math.random()*0.04;
        var fl = Math.pow(-1, (Math.random()*1000)|0) * Math.random()/20;
        var blade = {
c: [
    [x, -1, z-Math.random()/1000],
    [x+0.002+fl, -1+y, z-Math.random()/1000],
    [x+0.007+fl, -1+y, z-Math.random()/1000],
    [x+0.02, -1, z-Math.random()/1000]
],
f: 'green',
d: 2
        };
        draw(blade.c, blade.f, blade.d);
    }
}

function draw(cds, fill, d) {
    var v = {
        w: c.clientWidth,
        h: c.clientHeight
    };

    ctx.beginPath();

    ctx.moveTo(((cds[0][0] * (1 / (1 - cds[0][2])) + 1) * v.w / 2)|0, ((v.h - (cds[0][1] + 1) * v.h / 2) * (1 / (1 - cds[0][2])))|0);

    for (var i = 1; i < cds.length; i++) {
        ctx.lineTo(((cds[i][0] * (1 / (1 - cds[i][2])) + 1) * v.w / 2)|0, ((v.h - (cds[i][1] + 1) * v.h / 2) * (1 / (1 - cds[i][2])))|0);
}
        ctx.lineTo(((cds[0][0] * (1 / (1 - cds[0][2])) + 1) * v.w / 2)|0, ((v.h - (cds[0][1]+1) * v.h / 2) * (1 / (1 - cds[0][2])))|0);

    if (Math.abs(d) == 1) {
        grd = ctx.createLinearGradient((200-200*d/Math.abs(d))/2, 0, (200+200*d/Math.abs(d))/2,0);
    } else if (Math.abs(d) == 2) {
        grd = ctx.createLinearGradient(0,((v.h - (cds[1][1] + 1) * v.h / 2) * (1 / (1 - cds[1][2])))|0,0,((v.h - (cds[0][1] + 1) * v.h / 2) * (1 / (1 - cds[0][2])))|0+v.h/100);
    } else if (Math.abs(d) == 3) {
        grd = ctx.createLinearGradient(0,(200-200*d/Math.abs(d))/2, 0, (200+200*d/Math.abs(d))/2);
    }
    grd.addColorStop(0, fill);
    grd.addColorStop(1, '#000');

    ctx.fillStyle = grd;
    ctx.fill();
}

最佳答案

我要做的是为每片草叶预先生成所有可能的形状。我不熟悉弯曲草背后的数学,但让我们假设每种形状的草都可以用 2 个变量来描述:bentX 和 bentZ。所以我将绘图过程分解为 2:为草和渲染生成图像帧。

框架生成的伪代码:

var frames = [];
for (var i = min possible of bentX, l = max possible of bentX; i<=l; i += precision for bentX)
    for (var j = ... bentZ .... )
         frames[i][j] = image of grass at (i,j);

然后进行渲染:

for each grassObj:
    bentX, bentZ = mathCalcs(grassObj);
    bentX, bentZ = clampToValidValue(bendX, bentZ); 
    frames[bendX][bentZ].draw();

关于javascript - 在 Canvas 中为草制作动画的有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27030172/

相关文章:

javascript - Canvas 动画(window.requestAnimationFrame)

android - Android 中的默认动画在哪里?

css - 左 Angular 动画不起作用

javascript - 当用户向下滚动时显示内容

javascript - 如何从 php 或 node.js 获取 websocket url 路径

javascript - 如何使 Material ui dropzone 区域不允许重复?

ios - 当部署到 Firebase 托管时,HTML5 视频无法通过 HTTPS 在 iOS 上播放

jquery - 在 div 中显示工具提示

javascript位置搜索url中的多个查询参数

javascript - 带有自定义按钮的 tinymce-4 在 Chrome 和 Firefox 中工作正常但在 Safari 中不起作用 - 为什么?