【问题标题】:How can I create a graphic canvas with 2D objects animated in 3D space?如何在 3D 空间中创建具有 2D 对象动画的图形画布?
【发布时间】:2013-08-14 10:46:57
【问题描述】:

我遇到this site 并爱上了背景动画,尤其是相互连接的点,在 3D 空间中制作动画。 (有问题的元素是:<canvas id="bg" width="1920" height="995"></canvas>)我是画布动画的新手,从我目前所做的研究来看,我不知道应该从什么路径开始为我的项目实现类似的背景动画。到目前为止,我已经研究了 Paper.js 和普通的 Canvas 及其 JS API。

这是我的规格:

  • 能够制作“画布”(不是字面意义上的 <canvas>,而是图形画布。我不反对任何特定的图形包装器)。
  • 能够使“画布”具有响应性
  • 圆点(2D 圆)在 3D 空间中导航(能够在轴上旋转对象是一个加分项,在 helix 中制作动画是一个加分项。)
  • 这些圆点集的可实例化模块
  • 能够根据特定事件(点击、悬停等)为这些模块设置动画

很高兴拥有:

  • 矢量图形

和我想达到的差不多的可以查看here

我知道我要做的所有事情都需要一个整体(JS 图形库,如 Paper.js、自定义 JS 类等),但我只想知道其他人有什么成功。

谢谢!

【问题讨论】:

  • 大部分是图片。还是你的意思是积分?该效果不需要实际的 3D 画布。
  • 对不起,应该更具体。我的意思是背景点。更新了问题。

标签: javascript html animation canvas 3d


【解决方案1】:

如果您希望在浏览器中获得高质量的 3D 图形而无需任何插件,它可能会很快变得复杂。有一些更高级别的库可以使这更容易。其中最著名的是three.js

【讨论】:

  • 我最近也看过 three.js,但我想做的是在 3D 空间中为 2D 对象设置动画,而不是为 3D 对象设置动画。我会更新问题。
【解决方案2】:

老实说,我只是一时兴起才这么做的。我通常尽量不咬那些说“给我这个代码”的问题,但我想看看它需要多长时间。它绝对可以被清理、命名空间等,它甚至可能根本不是你想要的,但无论如何效果都很酷。

注意鼠标事件不包括在这个例子中。这个问题在细节方面有点模糊,所以我提供的只是一个非常简单的方法来开始使用 3d 和 canvas 2d 元素。

有一些相当不错的代码here,这是来自Foundation HTML5 Animation with JavaScript 的示例代码和书籍练习,其中包含一些使用 Javascript 和画布的 3d 示例的精彩介绍。我建议检查一下!

Live Demo

Full Screen

fiddle

var canvas = document.getElementById("canvas"),
    ctx = canvas.getContext("2d");

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
ctx.lineWidth = 4;

// Color stuff not real important just fluff
var cycle = 0,
    colors = {
        r: 0,
        g: 170,
        b: 0
    };

function colorCycle(inc) {
    cycle += inc;
    if (cycle > 100) {
        cycle = 0;
    }
    colors.r = ~~ (Math.sin(.3 * cycle + 0) * 127 + 128);
    colors.g = ~~ (Math.sin(.3 * cycle + 2) * 127 + 128);
    colors.b = ~~ (Math.sin(.3 * cycle + 4) * 127 + 128);
}

// Sections and points

function Point(x, y, z, size) {
    this.x = x;
    this.y = y;
    this.z = z;
    this.xpos = 0;
    this.ypos = 0;
    this.size = 5;

    rotateY(this,angle+=0.1);
}

function Section(x, y, z, width) {
    this.x = x;
    this.y = y;
    this.z = z;
    this.width = width;
    this.points = [];
    this.points.push(new Point(this.x - this.width / 2, this.y, this.z, 20));
    this.points.push(new Point(this.x + this.width / 2, this.y, this.z, 20));

    this.render = function (angleX, angleY) {
        ctx.beginPath();
        for (var p = 0; p < this.points.length; p++) {
            var point = this.points[p];

            rotateX(point, angleX);
            rotateY(point, angleY);
            doPerspective(point);

            ctx.arc(point.xpos, point.ypos, point.size, 0, Math.PI * 2, true);

            if (p == 0) {
                ctx.moveTo(this.points[0].xpos, this.points[0].ypos);
            } else {
                ctx.lineTo(point.xpos, point.ypos);
            }
        }

        ctx.closePath();
        ctx.stroke();
        ctx.fill();
    }
}

// 3d Functions for rotation and perspective
function rotateX(point, angleX) {
    var cosX = Math.cos(angleX),
        sinX = Math.sin(angleX),
        y1 = point.y * cosX - point.z * sinX,
        z1 = point.z * cosX + point.y * sinX;
    point.y = y1;
    point.z = z1;
}

function rotateY(point, angleY) {
    var cosY = Math.cos(angleY),
        sinY = Math.sin(angleY),
        x1 = point.x * cosY - point.z * sinY,
        z1 = point.z * cosY + point.x * sinY;
    point.x = x1;
    point.z = z1;
}

function doPerspective(point) {
    if (point.z > -fl) {
        var scale = fl / (fl + point.z);
        point.size = scale * 5;
        point.xpos = vpX + point.x * scale;
        point.ypos = vpY + point.y * scale;
    }
}

// Init code
var sections = [],
    numSections = 50,
    fl = 250,
    vpX,
    vpY,
    angle = 0;

vpX = canvas.width / 2;
vpY = canvas.height / 2;

// make some sections
for (var i = 0; i < numSections; i++) {
    sections.push(new Section(0, -250 + (i * 10), 0, 50));
}

function render() {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    colorCycle(0.1);
    ctx.fillStyle = "rgb(" + colors.r + "," + colors.g + "," + colors.b + ")";
    ctx.strokeStyle = "rgb(" + colors.r + "," + colors.g + "," + colors.b + ")";
    for (var i = 0; i < sections.length; i++) {
        sections[i].render(0, 0.03);
    }
    requestAnimationFrame(render);
}
render();

【讨论】:

  • 这是非常棒的东西!如果我的问题听起来有点像“嘿,给我代码”,我深表歉意;那不是我的本意。我只是在寻找“嘿,您可以使用 X + Y 来实现效果”。但我确实知道弄清楚什么是有效的可能会让你陷入一个非常深的洞(有时最终会得到一个实际的解决方案而不是概念证明)。话虽如此,您非常感谢您花时间研究这个问题。我今天将剖析您的代码以了解更多信息并扩展解决方案。再次感谢!
猜你喜欢
  • 1970-01-01
  • 2011-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-05-12
  • 1970-01-01
  • 2012-01-09
  • 2013-04-03
相关资源
最近更新 更多