【BabylonJS】画线及其自动延长的动画

有这么个需求,需要动态画一根线,并以动画的方式延长。

我们先来拆解下技术要点:

1、首先,我们得把一根线给画出来;

2、然后,得让这根线动态地延长。

先来解决第一个问题,画线。Babylon提供了画线的方法 BABYLON.MeshBuilder.CreateLines。该方法接受3个参数,具体可以参照api文档:https://doc.babylonjs.com/api/classes/babylon.meshbuilder#createlines

这里直接举个例子可以看得明白:

var myPoints = [];

var point1 = new BABYLON.Vector3(0, 1, 0);
myPoints.push(point1);
var point2 = new BABYLON.Vector3(2, 1, 1);
 myPoints.push(point2);

var lines = BABYLON.MeshBuilder.CreateLines("lines", {points: myPoints}, engine.scene);

CreateLines第一个参数,只是一个名字,无关紧要;第二个参数就是多段线之间的点。从CreateLines的s可以看得到,其实它是可以支持画多根线的,只需要把拐点定义好即可。最后一个参数就是scene场景对象。

这样,第一个问题解决。我们来看第二个问题。

大家一般会想到,我用个定时器,定时地改变线段的终点,这样子不也是动画了?其实也是可以的,但这样子一般不是很好,会带来很多额外的运算,而且不一定那么连贯。最佳方式还是使用动画机制,动画机制一般是由引擎内部实现的刷新,一般来说不会那么卡顿。

动画的话,BabylonJs提供了Animation对象。它的构造函数声明见API:

https://doc.babylonjs.com/api/classes/babylon.animation#constructor

我们直接上代码:

        var framePerSecond = 30;
        var totalFrames = 1500;
        var animationLine = new BABYLON.Animation("myAnimation", "scaling", framePerSecond,
                BABYLON.Animation.ANIMATIONTYPE_VECTOR3, 
                BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
        var keys = [];
        keys.push({
            frame: 1,
            value: new BABYLON.Vector3(1, 1, 1)
        });
        keys.push({
            frame: totalFrames,
            value: new BABYLON.Vector3(100, 1, 100)
        });
        animationLine.setKeys(keys);
        var finishEvent = new BABYLON.AnimationEvent(totalFrames, function () {
            console.log("animation finish");
        }, false);
        animationLine.addEvent(finishEvent);

        lines.animations = [];
        lines.animations.push(animationLine);
        scene.beginAnimation(lines, 0, totalFrames, false);

上述代码经过以下几个步骤:

1、定义好动画市场的总帧数totalFrames以及每秒多少帧framePerSecond。这里可以看到整个动画会持续50秒。

2、定义动画对象animationLine。第一个参数依然是一个名字,无关紧要;第二个参数就是动画要改变的属性,这里是scaling缩放;第三个参数是动画的帧率,fps;第四个参数是动画改变属性的数据类型,由于scaling是一个三元组,所以这里填BABYLON.Animation.ANIMATIONTYPE_VECTOR3;最后是动画是否循环。这里是不循环

3、定义关键帧keys。这里是个数组,数组元素是一个定义第i帧的具体的数值的对象,不难理解。但要注意,初始帧的状态一定要加上,不然的话动画一下子就biu到结束状态了。所以这里的数组长度至少为2.

4、设置动画回调,设置在最后一帧回调,就是动画结束的时候回调。

5、设置动画并执行,就是以下几句话,不难理解:

lines.animations = [];

lines.animations.push(animationLine);

scene.beginAnimation(lines, 0, totalFrames, false);

这个过程可能会有个关键点,会有同学问我怎么知道scaling可以做这个缩放动画呢?首先这个肯定是根据具体需求来的。如果实在不知道效果如何,可以先试下看改变它的数值是否能达到目的,我这里就写了个操作检查下scaling是否会达到我想到的效果。

        // //这样子能撑大,接下来写个动画实现它即可
        // setTimeout(function(){
        //     lines.scaling.x = 100;
        //     lines.scaling.z = 100;
        // },500);

确认无误之后,我就可以用动画实现它了。

以上就是画一个会变长的金箍棒的过程。全部代码如下:


/**
 * assetcontaier的demo
 */

$(function(){
    console.log('demo page is ready');

    var modelDataList = [{
        modelUrl:'/static/model/LNL/3/LNL3_F1.glb',
    },{
        modelUrl:'/static/model/LNL/LNL.glb',
    }
    ,{
        modelUrl:'/static/model/LNL/3/LNL3_F2.glb',
    }]
    var assetContainers = [];
    var currentSceneIndex = 0; 
    var engine = null;
    var scene = null;
    var initScene = function (cameraType) {
        var canvas = document.getElementById('renderCanvas');
        var engine = new BABYLON.Engine(canvas, true);
        
       
        var createScene = function () {
            scene = new BABYLON.Scene(engine);
            //默认用3D
            var camera;
            camera = new BABYLON.ArcRotateCamera("Camera", 0, 0, 100, BABYLON.Vector3.Zero(), scene);
            camera.setPosition(new BABYLON.Vector3(120, 120, 120));
            camera.attachControl(canvas, false, false);
            
            var hemisphericLight = new BABYLON.HemisphericLight("light1", new BABYLON.Vector3(0, 100, 0), scene);
    
            let loadedModelCount = 0;   //加载成功的模型
            for (var i = 0; i < modelDataList.length; i++) {
                var modelData = modelDataList[i];
                var fullPath = modelData.modelUrl;
                if(!fullPath){
                    loadedModelCount++;
                    continue;
                }
                var idx = fullPath.lastIndexOf('/');
                var folder = fullPath.substring(0, idx + 1);
                var fileName = fullPath.substring(idx + 1);
                BABYLON.SceneLoader.LoadAssetContainer(folder, fileName, scene, function (container) {
                    assetContainers.push(container);
                    loadedModelCount++;
                    if(loadedModelCount==modelDataList.length){
                        //加载完毕
                        assetContainers[currentSceneIndex].addAllToScene();
                        
                    }
                });
            }
            return scene;
        };
        scene = createScene();
        engine.runRenderLoop(function () {
            scene.render();
        });
        window.addEventListener('resize', function () {
            engine.resize();
        });
        var customLoadingUI = new ZFBabylonLoadingScreen();
        engine.loadingScreen = customLoadingUI;  //改成自定义的loading界面
        return engine;
    };

    var drawLine = function() {
        var myPoints = [];

        var point1 = new BABYLON.Vector3(0, 1, 0);
        myPoints.push(point1);
        var point2 = new BABYLON.Vector3(2, 1, 1);
        myPoints.push(point2);

        var lines = BABYLON.MeshBuilder.CreateLines("lines", {points: myPoints}, engine.scene);
        console.log(lines);

        var framePerSecond = 30;
        var totalFrames = 1500;
        var animationLine = new BABYLON.Animation("myAnimation", "scaling", framePerSecond,
                BABYLON.Animation.ANIMATIONTYPE_VECTOR3, BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
        var keys = [];
        keys.push({
            frame: 1,
            value: new BABYLON.Vector3(1, 1, 1)
        });
        keys.push({
            frame: totalFrames,
            value: new BABYLON.Vector3(100, 1, 100)
        });
        animationLine.setKeys(keys);
        var finishEvent = new BABYLON.AnimationEvent(totalFrames, function () {
            console.log("animation finish");
        }, false);
        animationLine.addEvent(finishEvent);

        lines.animations = [];
        lines.animations.push(animationLine);
        scene.beginAnimation(lines, 0, totalFrames, false);

      
        // //这样子能撑大,接下来写个动画实现它即可
        // setTimeout(function(){
        //     lines.scaling.x = 100;
        //     lines.scaling.z = 100;
        // },500);
        
    };

    engine = initScene();

    setTimeout(function(){
        drawLine(engine);
    },1000);

});

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要给引入的模型加上手写动画,需要使用Babylon.js中的动画系统。首先,需要创建一个动画对象,并指定要动画的属性和变化值。然后,需要创建一个动画帧,并指定要改变的时间和值。最后,将动画帧添加到动画对象中,并将动画对象附加到模型上。 以下是一个简单的示例代码,演示如何使用Babylon.js添加手写动画: ```javascript // 导入模型 BABYLON.SceneLoader.ImportMesh("", "models/", "myModel.babylon", scene, function (newMeshes) { var mesh = newMeshes[0]; // 创建动画对象 var animationBox = new BABYLON.Animation("myAnimation", "rotation.y", 30, BABYLON.Animation.ANIMATIONTYPE_FLOAT, BABYLON.Animation.ANIMATIONLOOPMODE_CYCLE); // 创建动画帧 var keys = []; keys.push({ frame: 0, value: 0 }); keys.push({ frame: 20, value: Math.PI / 2 }); keys.push({ frame: 40, value: Math.PI }); animationBox.setKeys(keys); // 将动画对象添加到模型上 mesh.animations.push(animationBox); // 开始动画 scene.beginAnimation(mesh, 0, 100, true); }); ``` 在上面的代码中,我们创建了一个名为“myAnimation”的动画对象,指定了要改变的属性为“rotation.y”,变化值为浮点数。然后,我们创建了三个动画帧,分别在0、20和40帧时改变旋转角度。最后,将动画对象添加到模型的动画数组中,并使用场景的beginAnimation方法启动动画。 请注意,这只是一个简单的示例,您可以根据需要修改动画对象和动画帧的属性和值。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程老师2088

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值