弹簧行为模拟
基本上,我想模拟绘画图像上的弹簧行为。 我想让它通过几次迭代运行(比如固定在一个弹簧上)。
我在网上find的所有例子都会导致这个类 – FloatSpring.java
它应该提供所需的计算来将点A移动到点B,并使用类似弹簧的效果,这取决于各种FloatSpring类的设置。 问题是,我没有find一个明确的例子,如何正确使用它。
我做了这个小例子来testingFloatSpring
:
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倍变焦。 像简单的animation过渡。
FloatSpring类应该没问题 – 我只是不明白如何正确使用它。 准确地说 – 我应该指定什么作为springK
和dampingK
值,也是time
属性的目的不明确…
我真的很感激那里的帮助。
这是一个使用FloatSpring
的工作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(); } } }