将Path作为对象设置动画的最简单方法是什么? [英] What the easiest way to animate a Path as an object traverses it?

查看:125
本文介绍了将Path作为对象设置动画的最简单方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑一个遍历长而线性路径的矩形。找出动画中早期形状的位置会很有用。在形状移动之前显示整个路径不是我想要的。通过添加窗格的路径可以轻松完成。



我想在形状后面有一条尾随线,表示形状到目前为止所经过的路径。有谁知道如何在Javafx中这样做?我正在使用Path和PathTransition在路径上为我的对象设置动画。

解决方案

有各种解决方案。取决于您选择哪一个决定您的结果。



当节点沿路径移动时,您可以在其上使用画布和绘画线。

  import javafx.animation.Animation; 
import javafx.animation.PathTransition;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.stage.Stage;
import javafx.util.Duration;

公共类PathVisualization扩展Application {

private static double SCENE_WIDTH = 400;
私人静态双SCENE_HEIGHT = 260;

帆布帆布;

@Override
public void start(Stage primaryStage)throws Exception {

Pane root = new Pane();
Path path = createPath();
canvas = new Canvas(SCENE_WIDTH,SCENE_HEIGHT);

root.getChildren()。addAll(path,canvas);

primaryStage.setScene(新场景(root,SCENE_WIDTH,SCENE_HEIGHT));
primaryStage.show();

动画动画= createPathAnimation(path,Duration.seconds(5));
animation.play();
}

private Path createPath(){

Path path = new Path();

path.setStroke(Color.RED);
path.setStrokeWidth(10);

path.getElements()。addAll(new MoveTo(20,20),new CubicCurveTo(380,0,380,120,200,120),new CubicCurveTo(0,120,0,240) ,380,240),new LineTo(20,20));

返回路径;
}

private动画createPathAnimation(路径路径,持续时间){

GraphicsContext gc = canvas.getGraphicsContext2D();

//沿路径移动节点。我们想要它的位置
Circle pen = new Circle(0,0,4);

//创建路径转换
PathTransition pathTransition = new PathTransition(duration,path,pen);
pathTransition.currentTimeProperty()。addListener(new ChangeListener< Duration>(){

Location oldLocation = null;

/ **
* Draw从旧位置到新位置的一行
* /
@Override
public void changed(ObservableValue<?extends Duration> observable,Duration oldValue,Duration newValue){

//跳过0/0
if(oldValue == Duration.ZERO)
return;

//获取当前位置
double x = pen.getTranslateX();
double y = pen.getTranslateY();

//初始化位置
if(oldLocation == null){
oldLocation = new Location();
oldLocation.x = x;
oldLocation.y = y;
ret瓮;
}

//绘制线
gc.setStroke(Color.BLUE);
gc.setFill(Color.YELLOW);
gc.setLineWidth(4);
gc.strokeLine(oldLocation.x,oldLocation.y,x,y);

//使用当前的
oldLocation.x = x更新旧位置
oldLocation.y = y;
}
});

return pathTransition;
}

公共静态类位置{
double x;
双倍;
}

public static void main(String [] args){
launch(args);
}
}

这是截图。红色是实际路径,蓝色是在画布上绘制的路径:





其他解决方案使用e。 G。



带有线条图的解决方案也有其缺点。如果选择1秒,您将看到线段。绕过这种情况的可能性是自己平滑路径。但是为此你必须将路径分成几段,这有点数学。



稍微偏离主题,但如何沿着鼠标坐标绘制也可能是为了给你提供想法。


Consider a rectangle traversing a long, linear path. It would be useful to figure out where the shape had gone earlier in the animation. Displaying the entire path before the shape moves is not what I want. That is easily done by adding the path to the pane.

I want a trailing line behind the shape representing the path that the shape has traversed through so far. Does anyone know how to do this in Javafx? I am using Path and PathTransition to animate my object along a path.

解决方案

There are various solutions. Depending on which one you choose decides your outcome.

You could use a Canvas and paint lines on it while a Node moves along the Path.

import javafx.animation.Animation;
import javafx.animation.PathTransition;
import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.stage.Stage;
import javafx.util.Duration;

public class PathVisualization extends Application {

    private static double SCENE_WIDTH = 400;
    private static double SCENE_HEIGHT = 260;

    Canvas canvas;

    @Override
    public void start(Stage primaryStage) throws Exception {

        Pane root = new Pane();
        Path path = createPath();
        canvas = new Canvas(SCENE_WIDTH,SCENE_HEIGHT);

        root.getChildren().addAll(path, canvas);

        primaryStage.setScene(new Scene(root, SCENE_WIDTH, SCENE_HEIGHT));
        primaryStage.show();

        Animation animation = createPathAnimation(path, Duration.seconds(5));
        animation.play();
    }

    private Path createPath() {

        Path path = new Path();

        path.setStroke(Color.RED);
        path.setStrokeWidth(10);

        path.getElements().addAll(new MoveTo(20, 20), new CubicCurveTo(380, 0, 380, 120, 200, 120), new CubicCurveTo(0, 120, 0, 240, 380, 240), new LineTo(20,20));

        return path;
    }

    private Animation createPathAnimation(Path path, Duration duration) {

        GraphicsContext gc = canvas.getGraphicsContext2D();

        // move a node along a path. we want its position
        Circle pen = new Circle(0, 0, 4);

        // create path transition
        PathTransition pathTransition = new PathTransition( duration, path, pen);
        pathTransition.currentTimeProperty().addListener( new ChangeListener<Duration>() {

            Location oldLocation = null;

            /**
             * Draw a line from the old location to the new location
             */
            @Override
            public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {

                // skip starting at 0/0
                if( oldValue == Duration.ZERO)
                    return;

                // get current location
                double x = pen.getTranslateX();
                double y = pen.getTranslateY();

                // initialize the location
                if( oldLocation == null) {
                    oldLocation = new Location();
                    oldLocation.x = x;
                    oldLocation.y = y;
                    return;
                }

                // draw line
                gc.setStroke(Color.BLUE);
                gc.setFill(Color.YELLOW);
                gc.setLineWidth(4);
                gc.strokeLine(oldLocation.x, oldLocation.y, x, y);

                // update old location with current one
                oldLocation.x = x;
                oldLocation.y = y;
            }
        });

        return pathTransition;
    }

    public static class Location {
        double x;
        double y;
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Here's a screenshot how it looks like. Red is the actual path, Blue is the path that is drawn on the Canvas:

Other solutions use e. g. a clip. However, if you choose the same Duration as I did above (i. e. 5 seconds) with that technique, you'll get gaps like this:

The solution with the line drawing has its drawbacks as well. If you choose 1 second, you'll see the line segments. A possibiliy to circumvent this would be to smooth the path yourself. But for that you'd have to get into splitting the path into segments and that's a bit math-y.

Slightly offtopic, but how to paint along the mouse coordinates may also be interesing for you to give you ideas.

这篇关于将Path作为对象设置动画的最简单方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆