#### 说明

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

}

 

版权声明:本文为dgwblog原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/dgwblog/p/9924657.html