1. 程式人生 > >Swing實現canvas-nest.js 原始碼

Swing實現canvas-nest.js 原始碼

#### 說明

canvas-nest.js 原始碼

http://www.bubuko.com/infodetail-2237716.html

地址:https://gitee.com/dgwcode/MyJavaCode/tree/master/Canvas-nest-swing

 

 

 

實現過程

1. 繪製一個容器
2. 用隨機數生成座標,繪製100個點
3. 用隨機數生成每個點的運動方向,每次x軸位移多少,y軸位移多少
4. 每1/60秒用for迴圈重新計算點的座標,重繪畫布
5. 兩個for迴圈巢狀,判斷每個點與其他點的距離,若小於90px,則繪製連線,且連線的rgba透明度根據距離而變化6.新增滑鼠吸附事件,滑鼠進入畫布後實時監聽其位置,並在上述for迴圈中判斷與滑鼠的距離,設點為r,距離為dist,若dist>70且dist<140,rx-=0.03xdist,r.y-=0.03y_dist,即可實現吸附效果(前半段為加速,後半段為吸附)

 Code

package main.canvas;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import
java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import javax.swing.JFrame; import javax.swing.JPanel; import java.awt.BorderLayout; import java.awt.Color; public class MainFrame extends JFrame { private static final long serialVersionUID = -8808883923263763897L;
private static volatile MainFrame instance; public MainFrame() { this.setTitle("Canvas Nest"); this.setSize(new Dimension(660, 470)); this.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); this.setLocation((Toolkit.getDefaultToolkit().getScreenSize().width - this.getWidth()) / 2, (Toolkit.getDefaultToolkit().getScreenSize().height - this.getHeight()) / 2); this.setMinimumSize(new Dimension(400, 300)); this.setResizable(true); this.setVisible(true); this.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); /** * 100個點位置與方向的初始化 */ R[] r = new R[100]; M mousePoint = new M();//監聽滑鼠位置 for (int i = 0; i < r.length; i++) { r[i] = new R(); r[i].x = (float) (Math.random() * 660); r[i].y = (float) (Math.random() * 470); r[i].xa = (float) (2 * Math.random() - 1);//方向 r[i].ya = (float) (2 * Math.random() - 1);//方向 } JPanel panel = new JPanel() { private static final long serialVersionUID = -7507627235240618009L; @Override public void paint(Graphics g1) { Graphics2D g_point = (Graphics2D) g1;// Graphics2D g_line = (Graphics2D) g1;// g_point.setColor(Color.blue); // 通過鍵值設定渲染的抗鋸齒 g_line.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g_point.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); super.paint(g_point); super.paint(g_line); for (int i = 0; i < r.length; i++) { for (int j = 0; j < r.length; j++) { // 畫點 實際上可用filloval實現 g_point.drawLine((int) r[i].x, (int) r[i].y, (int) r[i].x, (int) r[i].y); if (r[i] != r[j]) { // 得到兩個不同點的座標 構成算出第三條邊的長度dist float x_dist = r[i].x - r[j].x; float y_dist = r[i].y - r[j].y; float dist = (float) (x_dist * x_dist + y_dist * y_dist); // 根據距離算出透明度 float a = 0; if (dist > 0 && dist < 8100) { a = (1 - (dist / 8100)) * 100; g_line.setColor(new Color(0, 100, 150, (int) a)); g_line.drawLine((int) r[i].x, (int) r[i].y, (int) r[j].x, (int) r[j].y); } } } } } }; panel.setBackground(Color.WHITE); getContentPane().add(panel, BorderLayout.CENTER); /** * 滑鼠事件處理程式碼 */ panel.addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseMoved(MouseEvent e) { mousePoint.x = (float) e.getX(); mousePoint.y = (float) e.getY(); } }); panel.addMouseListener(new MouseAdapter() { @Override public void mouseExited(MouseEvent e) { mousePoint.x = null; mousePoint.y = null; } }); new Thread(new Runnable() { @Override public void run() { while (true) { try { for (int i = 0; i < r.length; i++) { // 僅僅加上方向值 r[i].x += r[i].xa; r[i].y += r[i].ya; /** * 當前隨機點如果在可視view中 那麼 */ r[i].xa *= r[i].x > 660 || r[i].x < 0 ? -1 : 1; r[i].ya *= r[i].y > 470 || r[i].y < 0 ? -1 : 1; // 在視窗的可視大小環境中 if (mousePoint.x != null && mousePoint.y != null) { float x_dist = r[i].x - mousePoint.x; float y_dist = r[i].y - mousePoint.y; float dist = (float) (x_dist * x_dist + y_dist * y_dist); if (dist > 4900 && dist < 19600) { r[i].x -= 0.03 * x_dist; r[i].y -= 0.03 * y_dist; } } } /** * 4.每1/60秒用for迴圈重新計算點的座標,重繪畫布 * 5.兩個for迴圈巢狀,判斷每個點與其他點的距離, * 若小於90px,則繪製連線,且連線的rgba透明度根據距離而變化 */ panel.repaint(); Thread.sleep(1000 / 60); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); } public static MainFrame getIstance() { if (instance == null) { synchronized (MainFrame.class) { if (instance == null) { instance = new MainFrame(); } } } return instance; } private class R { float x; float y; float xa; float ya; } private class M { Float x; Float y; } }