Моделирование поведения пружины

По сути, я хочу имитировать поведение пружины на нарисованном изображении. Я хочу, чтобы он выполнялся через несколько итераций, масштабируя его вверх и вниз (как будто он закреплен на пружине).

Все примеры, которые я нашел в сети, ведут к этому классу - FloatSpring.java

Он должен обеспечивать необходимые вычисления для перемещения точки A в точку B, применяя пружинный эффект, который зависит от различных настроек класса FloatSpring. Проблема в том, что я не нашел ни одного четкого примера, как его правильно использовать.

Я сделал этот небольшой пример, чтобы протестировать FloatSpring на:

public static void main ( String[] args )
{
    // Some image to bounce
    final ImageIcon icon =
            new ImageIcon ( WebProgressOverlayExample.class.getResource ( "icons/ava1.jpg" ) );

    // Component to paint image on
    JComponent spring = new JComponent ()
    {
        // Zoom value (1f = 100% = normal size)
        float zoom = 1f;

        {
            // Basic spring settings
            final FloatSpring fs = new FloatSpring ( 100 );
            fs.setPosition ( zoom );

            // Animation delay
            final int delay = 1000 / 24;

            // Animator
            new Timer ( delay, new ActionListener ()
            {
                private float elapsed = 0f;

                public void actionPerformed ( ActionEvent e )
                {
                    // Increasing elapsed time and updating spring
                    elapsed += delay;
                    fs.update ( 3f, elapsed );

                    // Updating zoom value and component
                    zoom = fs.getPosition ();
                    repaint ();
                }
            } ).start ();
        }

        protected void paintComponent ( Graphics g )
        {
            super.paintComponent ( g );

            // Scaled image
            int width = Math.round ( icon.getIconWidth () * zoom );
            int height = Math.round ( icon.getIconHeight () * zoom );
            g.drawImage ( icon.getImage (), getWidth () / 2 - width / 2,
                    getHeight () / 2 - height / 2, this );
        }

        public Dimension getPreferredSize ()
        {
            return new Dimension ( 500, 500 );
        }
    };

    JFrame frame = new JFrame ();
    frame.add ( spring );
    frame.pack ();
    frame.setLocationRelativeTo ( null );
    frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );
    frame.setVisible ( true );
}

В этом примере свойство zoom должно измениться с 1f на 3f в течение цикла таймера и, наконец, привести отображаемое на компоненте изображение к 3-кратному увеличению. Что-то вроде простого анимированного перехода.

Класс FloatSpring должен быть в порядке - я просто не понимаю, как его правильно использовать. Точнее - что я должен указать в качестве значений springK и dampingK, а также неясно назначение свойства time...

Я был бы очень признателен за любую помощь там.


person Mikle Garin    schedule 27.06.2012    source источник


Ответы (1)


Вот рабочий sscce с использованием FloatSpring.

банджи

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Icon;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.Timer;
import javax.swing.UIManager;

/**
* @see http://stackoverflow.com/a/11233735/230513
*/
public class Test {

    private static Spring spring = new Spring();

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                JFrame frame = new JFrame();
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(spring);
                frame.add(new JButton(new AbstractAction("Start") {

                    @Override
                    public void actionPerformed(ActionEvent e) {
                        spring.start();
                    }
                }), BorderLayout.SOUTH);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                spring.start();
            }
        });
    }

    private static class Spring extends JComponent {

        private static final int SIZE = 500;
        private static final int DELAY = 1000 / 20; // ~20Hz
        private final Icon icon = UIManager.getIcon("OptionPane.informationIcon");
        private final FloatSpring fs = new FloatSpring(42);
        private final int target = 0;
        private final float delta = 1f / SIZE;
        private float elapsed = 0f;
        private Timer timer = new Timer(DELAY, new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                if ((int) fs.getPosition() < (target + 1)) {
                    timer.stop();
                    return;
                }
                elapsed += delta;
                fs.update(target, elapsed);
                repaint();
            }
        });

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            int x = (getWidth() - icon.getIconWidth()) / 2;
            int y = (int) fs.getPosition();
            icon.paintIcon(this, g, x, y);
            int xc = x + icon.getIconWidth() / 2;
            g.drawLine(xc, 0, xc, y);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(SIZE / 2, SIZE);
        }

        public void start() {
            timer.stop();
            elapsed = 0;
            fs.setPosition(SIZE - icon.getIconHeight());
            fs.setVelocity(0);
            timer.start();
        }
    }
}
person trashgod    schedule 27.06.2012
comment
Спасибо, это именно то, что я искал! - person Mikle Garin; 28.06.2012