弹簧行为模拟

时间:2012-06-27 14:30:37

标签: java swing timer paintcomponent imageicon

基本上,我想在绘制的图像上模拟弹簧行为。我想让它通过几次迭代来上下缩放(就像在弹簧上修复一样)。

我在网上找到的所有示例都会导致此类 - 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类应该没问题 - 我只是不明白如何正确使用它。确切地说 - 我应该指定什么springKdampingK值以及time属性目的不明确......

我真的很感激那里的任何帮助。

1 个答案:

答案 0 :(得分:6)

这是一个使用sscce的工作FloatSpring

bungee

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();
        }
    }
}