前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【Java AWT 图形界面编程】在 Canvas 画布中绘制箭头图形 ( 数据准备 | 几个关键的计算公式 | 绘制箭头直线和尾翼 )

【Java AWT 图形界面编程】在 Canvas 画布中绘制箭头图形 ( 数据准备 | 几个关键的计算公式 | 绘制箭头直线和尾翼 )

作者头像
韩曙亮
发布2023-04-01 11:55:12
1.5K0
发布2023-04-01 11:55:12
举报
文章被收录于专栏:韩曙亮的移动开发专栏

文章目录

一、在 Canvas 画布中绘制箭头图形 - 要点分析


1、数据准备

绘制箭头时 , 先设置一条直线的起始点和终止点 , 箭头绘制在该线段上 ;

代码语言:javascript
复制
    /**
     * 起始点 X, Y 坐标
     * 终止点 X, Y 坐标
     */
    private int startX, startY, endX, endY;

为箭头指定一个长度 , 该长度的末尾是 箭头终点 , 在直线上确定箭头终点 , 该终点延伸出两个尾翼 , 尾翼也指定一个长度 ;

代码语言:javascript
复制
    /**
     * 箭头 左右两个尾翼 长度
     */
    private int arrowWingLength = 20;

    /**
     * 箭头终点在直线的位置
     */
    private float arrowEndRatio = 0.5F;

    /**
     * 箭头长度
     */
    private int arrowLength;

2、绘制直线

先把箭头附着的直线 , 绘制出来 ;

代码语言:javascript
复制
        // 绘制直线
        g.drawLine(startX, startY, endX, endY);

3、绘制箭头尾翼

首先 , 确定起始点和终止点 , 在 x , y 轴上的差值 ;

代码语言:javascript
复制
        // 计算起始点和终止点在 x, y 方向的差值
        int deltaX = endX - startX;
        int deltaY = endY - startY;

然后 , 计算出起始点到终止点的角度 , deltaY / deltaX 是该角度的正切 , 已知正切值 , 计算角度 , 使用 Math.atan2 函数即可 , 最终计算的角度是 该直线 与 x 轴夹角 ;

代码语言:javascript
复制
        // 计算 直线的角度
        double angle = Math.atan2(deltaY, deltaX);

再后 , 使用勾股定理计算直线的长度 ;

代码语言:javascript
复制
        // 计算直线的长度
        int len = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);

再后 , 根据比例计算出箭头的长度 , 根据该长度 , 确定箭头终点的坐标 ; 下图中蓝色的箭头 , 就是计算出的箭头尾部相对于起始点的增量 ;

代码语言:javascript
复制
        // 设置箭头终点在直线的位置 , 根据比例计算出箭头长度
        arrowLength = (int) (len * arrowEndRatio);
        
        // 箭头终点坐标
        int arrowEndX = (int) (startX + arrowLength * Math.cos(angle));
        int arrowEndY = (int) (startY + arrowLength * Math.sin(angle));

最后 , 绘制箭头的两个尾翼 , 箭头的位置 ; 尾翼的起始点 arrowEndX, arrowEndY , 终止点需要根据角度计算出来 ;

代码语言:javascript
复制
        // 绘制箭头 尾翼 线段 , 直线的角度 增减 45 度 , 即可获得尾翼的角度
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle + Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle + Math.PI / 4)));
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle - Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle - Math.PI / 4)));

完整代码示例 :

代码语言:javascript
复制
    // 绘制箭头
    private void drawArrow(Graphics g, int startX, int startY, int endX, int endY) {
        // 计算起始点和终止点在 x, y 方向的差值
        int deltaX = endX - startX;
        int deltaY = endY - startY;

        // 计算 直线的角度
        double angle = Math.atan2(deltaY, deltaX);

        // 计算直线的长度
        int len = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);

        // 设置箭头终点在直线的位置 , 根据比例计算出箭头长度
        arrowLength = (int) (len * arrowEndRatio);

        // 箭头终点坐标
        int arrowEndX = (int) (endX - arrowLength * Math.cos(angle));
        int arrowEndY = (int) (endY - arrowLength * Math.sin(angle));

        // 绘制箭头 尾翼 线段 , 直线的角度 增减 45 度 , 即可获得尾翼的角度
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle + Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle + Math.PI / 4)));
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle - Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle - Math.PI / 4)));
    }

二、代码示例


代码示例 :

代码语言:javascript
复制
import java.awt.*;

public class ArrowCanvas extends Canvas {

    /**
     * 起始点 X, Y 坐标
     * 终止点 X, Y 坐标
     */
    private int startX, startY, endX, endY;

    /**
     * 箭头 左右两个尾翼 长度
     */
    private int arrowWingLength = 20;

    /**
     * 箭头终点在直线的位置
     */
    private float arrowEndRatio = 0.5F;

    /**
     * 箭头长度
     */
    private int arrowLength;



    public ArrowCanvas(int startX, int startY, int endX, int endY) {
        this.startX = startX;
        this.startY = startY;
        this.endX = endX;
        this.endY = endY;

        // 设置画布大小
        setSize(400, 400);
    }

    public void paint(Graphics g) {
        // 绘制直线
        g.drawLine(startX, startY, endX, endY);

        // 绘制箭头
        drawArrow(g, startX, startY, endX, endY);
    }

    // 绘制箭头
    private void drawArrow(Graphics g, int startX, int startY, int endX, int endY) {
        // 计算起始点和终止点在 x, y 方向的差值
        int deltaX = endX - startX;
        int deltaY = endY - startY;

        // 计算 直线的角度
        // 返回的是 这条直线 与 x 轴的夹角
        // deltaY / deltaX  是该角度的正切
        // 已知正切值 , 计算角度 , 使用  Math.atan2 函数即可
        // 最终计算的角度是 该直线 与 x 轴夹角
        double angle = Math.atan2(deltaY, deltaX);

        // 计算直线的长度
        int len = (int) Math.sqrt(deltaX * deltaX + deltaY * deltaY);

        // 设置箭头终点在直线的位置 , 根据比例计算出箭头长度
        arrowLength = (int) (len * arrowEndRatio);

        // 箭头终点坐标
        int arrowEndX = (int) (startX + arrowLength * Math.cos(angle));
        int arrowEndY = (int) (startY + arrowLength * Math.sin(angle));

        // 绘制箭头 尾翼 线段 , 直线的角度 增减 45 度 , 即可获得尾翼的角度
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle + Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle + Math.PI / 4)));
        g.drawLine(arrowEndX, arrowEndY, (int) (arrowEndX - arrowWingLength * Math.cos(angle - Math.PI / 4)), (int) (arrowEndY - arrowWingLength * Math.sin(angle - Math.PI / 4)));
    }

    public static void main(String[] args) {
        // 创建窗口并添加 ArrowCanvas 组件
        Frame f = new Frame("ArrowCanvas Example");
        ArrowCanvas ac = new ArrowCanvas(50, 50, 200, 200);
        f.add(ac);

        // 设置窗口大小并可见
        f.setSize(400, 400);
        f.setVisible(true);
    }
}

执行结果 :

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2023-03-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、在 Canvas 画布中绘制箭头图形 - 要点分析
    • 1、数据准备
      • 2、绘制直线
        • 3、绘制箭头尾翼
        • 二、代码示例
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档