计算';间隔和增量';用于Java Swing中的滑入动画

计算';间隔和增量';用于Java Swing中的滑入动画,java,swing,Java,Swing,我正在构建一个应用程序,它的主页中有一个幻灯片,目前我使用Thread.sleep(10)并添加/分到我想要滑动的面板的x位置 例如:slideIn(30,panel_1,10)

我正在构建一个应用程序,它的主页中有一个幻灯片,目前我使用Thread.sleep(10)并添加/分到我想要滑动的面板的x位置


例如:
slideIn(30,panel_1,10)
<这将导致panel_1以30毫秒的间隔滑入,并以10倍的时间减去x,直到panel位于中间/占据幻灯片显示面板。但这种方法的缺点是滑动动画不会平滑,我希望滑动动画/过渡像引导旋转木马一样平滑。有没有办法计算滑动过渡速度的速度和增量/减量值?

事实上,我有一个几乎完美的方法。我想你可以为你的动画路径创建一个Path2D,对吗?而且你似乎也想要一个恒定的速度。例如,在计算距离和显示JPanel时,有一些对我的项目()的引用,但是要删除它们并用标准java替换它们应该不难。试试看

public abstract class PathAnimation {
    private Path2D mPath;
    private double totalLength;

    /**
     * Be careful to call path.closePath before invoking this constructor
     * @param path
     */
    public PathAnimation(Path2D path) {
        mPath = path;
        totalLength = 0;
        PathIterator iterator = mPath.getPathIterator(null);
        //Point2D currentLocation;// = path.getCurrentPoint();
        double[] location = new double[6];
        iterator.currentSegment(location);
        while (!iterator.isDone()) {
            double[] loc = new double[6];
            iterator.next();
            iterator.currentSegment(loc);
            if (loc[0] == 0 && loc[1] == 0) continue;
            double distance = MathUtils.distance(location[0], location[1], loc[0], loc[1]);
            totalLength += distance;
            location = loc;
        }
    }

    @Override
    public Point2D getLocationAtTime(int time) {
        return getLocationAtTime(time / (double) getTotalAnimationTime());
    }

    public Point2D getLocationAtTime(double pctTime) {
        double len = totalLength * pctTime;
        PathIterator iterator = mPath.getPathIterator(null);
        double[] location = new double[6];
        iterator.currentSegment(location);
        while (!iterator.isDone()) {
            double[] loc = new double[6];
            iterator.next();
            iterator.currentSegment(loc);
            double distance= MathUtils.distance(location[0], location[1], loc[0], loc[1]);
            if (distance > len) {
                double pctThere = len / distance;
                double xSpot = location[0] * (1 - pctThere) + loc[0] * pctThere;
                double ySpot = location[1] * (1 - pctThere) + loc[1] * pctThere;
                return new Point2D.Double(xSpot, ySpot);
            }
            len -= distance;
            location = loc;
        }
        throw new ArrayIndexOutOfBoundsException("Path is too short or time is too long!");
    }

    /**
     * Number of milliseconds that this animation spans
     * @return
     */
    public abstract int getTotalAnimationTime();

    public static void main(String args[]) {
        Rectangle rect = new Rectangle(10,10,20,20);
        final Path2D.Double myPath = new Path2D.Double((Shape)rect);
        myPath.closePath();
        final PathAnimation myAnimation = new PathAnimation(myPath) {
            Area star = new Area(PaintUtils.createStandardStar(15, 15, 5, .5, 0));
            @Override
            public Dimension getSizeAtTime(int time) {
                return new Dimension(15,15);
            }

            @Override
            public void paintAtTime(Graphics2D g, int time) {
                Area toPaint = star;
                if ((time / 150) % 2 == 1) {
                    Dimension size = getSizeAtTime(0);
                    toPaint = new Area(toPaint);
                    PaintUtils.rotateArea(toPaint, Math.PI / 6);
                }
                g.setColor(Color.YELLOW);
                g.fill(toPaint);
                g.setColor(Color.RED);
                g.draw(toPaint);
            }

            @Override
            public int getTotalAnimationTime() {
                return 10000;
            }
        };
        System.out.println(myAnimation.getLocationAtTime(0));
        System.out.println(myAnimation.getLocationAtTime(2500));
        System.out.println(myAnimation.getLocationAtTime(4000));
        System.out.println(myAnimation.getLocationAtTime(5000));
        System.out.println(myAnimation.getLocationAtTime(7000));
        System.out.println(myAnimation.getLocationAtTime(7500));
        System.out.println(myAnimation.getLocationAtTime(9000));
        System.out.println(myAnimation.getLocationAtTime(10000));

        final JPanel jp = new JPanel() {
            public void paintComponent(Graphics g) {
                super.paintComponent(g);
                Graphics2D g2 = (Graphics2D) g;
                int time = ((int) System.currentTimeMillis()) % myAnimation.getTotalAnimationTime();
                int time2 = (time + myAnimation.getTotalAnimationTime() / 2) % myAnimation.getTotalAnimationTime();
                Point2D pt = myAnimation.getLocationAtTime(time);
                Point2D pt2 = myAnimation.getLocationAtTime(time2);
                Dimension size = myAnimation.getSizeAtTime(time);
                g2.translate(pt.getX() - size.width / 2, pt.getY() - size.height / 2);
                myAnimation.paintAtTime(g2, time);
                g2.translate(- (pt.getX() - size.width / 2), - (pt.getY() - size.height / 2));
                g2.translate(pt2.getX() - size.width / 2, pt2.getY() - size.height / 2);
                myAnimation.paintAtTime(g2, time2);
                g2.translate(- (pt2.getX() - size.width / 2), - (pt2.getY() - size.height / 2));                
                g2.setColor(Color.BLACK);
                g2.draw(myPath);
            }
        };
        WindowUtilities.visualize(jp);
        AbstractAction action = new AbstractAction() {
            public void actionPerformed(ActionEvent ae) {
                jp.repaint();
            }
        };
        javax.swing.Timer t = new javax.swing.Timer(30, action);
        t.start();
    }
}

改变你的想法。与其按固定的增量移动,不如在给定的时间段内从起点移动到目标点,加入慢进/慢出概念意味着增量可以是可变的。我会看看计时框架、通用Tween引擎或Trident,它们都是提供基于时间的动画的动画框架