一、鼠標(biāo)滾輪縮放的中心點(diǎn)設(shè)置為當(dāng)前鼠標(biāo)中心點(diǎn) - 要點(diǎn)分析
鼠標(biāo)指針指向界面中的 Canvas 畫布某個(gè)位置 , Canvas 畫布中繪制著一張超大圖片 , 以該位置為中心 , 滑動(dòng)鼠標(biāo)滾輪時(shí)進(jìn)行縮放 ;
使用鼠標(biāo)滾輪縮放后 , 在 Canvas 中繪制的圖片的尺寸肯定是放大或者縮小了 , 尺寸發(fā)生了改變 ;
圖片縮放時(shí) , 鼠標(biāo)指針指向一個(gè)位置 , 該位置對(duì)應(yīng)著一個(gè)當(dāng)前 Canvas 畫布中的 x, y 坐標(biāo) , 同時(shí)可以計(jì)算出當(dāng)前位置對(duì)應(yīng)的圖片中的 水平方向的比例 和 垂直方向的比例 ;
在縮放后的圖片中 , 只要保證鼠標(biāo)指針指向相同的 x, y 坐標(biāo)時(shí) , 該位置對(duì)應(yīng)的 水平方向的比例 和 垂直方向的比例 仍然保持不變 , 那就需要移動(dòng)圖片的位置 ;
- 如果放大圖片就需要將圖片往左上方移動(dòng) ;
- 如果縮小圖片就需要將圖片往右下方移動(dòng) ;
此時(shí)可以分析出 , 如果要實(shí)現(xiàn) 鼠標(biāo)滾輪縮放的中心點(diǎn)設(shè)置為當(dāng)前鼠標(biāo)中心點(diǎn) , 需要進(jìn)行下面兩個(gè)步驟的操作 :
- 保存當(dāng)前鼠標(biāo)指針指向的位置 , 以及鼠標(biāo)指針指向位置對(duì)應(yīng)圖片中坐標(biāo)位置的比例 ;
- 鼠標(biāo)指針指向的位置不變 , 指向圖片坐標(biāo)比例不變 , 圖片尺寸發(fā)生了改變 , 重新計(jì)算當(dāng)前圖片的放置位置 , 并設(shè)置圖片位置 ;
這樣圖片縮放時(shí) , 始終可以保證鼠標(biāo)指向的部位保持位置不變 ;
1、保存當(dāng)前鼠標(biāo)指針指向的位置
首先 , 在類中定義如下成員字段 ,
- pointer_x 和 pointer_y 記錄的是鼠標(biāo)指針指向的界面中 Camvas 畫布中的坐標(biāo)位置 ;
- pointer_ratio_x 和 pointer_ratio_y 記錄的是 鼠標(biāo)指針指向位置對(duì)應(yīng)圖片中坐標(biāo)位置的比例 ;
public double pointer_ratio_x;
public double pointer_ratio_y;
public int pointer_x;
public int pointer_y;
然后 , 在鼠標(biāo)縮放之前 , 保存當(dāng)前的鼠標(biāo)位置及比例 ;
- 在鼠標(biāo)滾輪事件 MouseWheelEvent 中 , 可以直接通過(guò)調(diào)用
e.getX(), e.getY()
獲取到當(dāng)前 鼠標(biāo)指針 在 Canvas 畫布的坐標(biāo) ; - 根據(jù)該 Canvas 中的坐標(biāo) , 以及畫布的偏移 , 可以計(jì)算出該坐標(biāo)對(duì)應(yīng)圖片中的坐標(biāo)位置 ;
// 計(jì)算畫布
double canvasX = x - offsetX;
double canvasY = y - offsetY;
- 計(jì)算出當(dāng)前的圖片大小 ;
// 計(jì)算圖片大小
double imageWidth = image.getWidth(null) * scale; // 縮放后的圖像寬度
double imageHeight = image.getHeight(null) * scale; // 縮放后的圖像高度
- 有了鼠標(biāo)指針在圖片中的位置 , 圖片的尺寸 , 就可以計(jì)算出鼠標(biāo)指針在圖片中的比例 ;
// 計(jì)算比例
pointer_ratio_x = canvasX / imageWidth ;
pointer_ratio_y = canvasY / imageHeight ;
完整代碼示例 :
/**
* 記錄滾輪縮放時(shí)鼠標(biāo)指針狀態(tài)
*/
public void save(int x, int y){
// 記錄鼠標(biāo)坐標(biāo)
pointer_x = x;
pointer_y = y;
// 計(jì)算畫布
double canvasX = x - offsetX;
double canvasY = y - offsetY;
// 計(jì)算圖片大小
double imageWidth = image.getWidth(null) * scale; // 縮放后的圖像寬度
double imageHeight = image.getHeight(null) * scale; // 縮放后的圖像高度
// 計(jì)算比例
pointer_ratio_x = canvasX / imageWidth ;
pointer_ratio_y = canvasY / imageHeight ;
}
2、根據(jù)鼠標(biāo)指針指向的位置以及比例重新計(jì)算圖片位置
在鼠標(biāo)滾輪縮放完成后 , 再根據(jù)鼠標(biāo)指針指向的位置和比例 , 結(jié)合圖片縮放后的尺寸 , 重新計(jì)算畫布偏移的位置 , 以達(dá)到鼠標(biāo)指向的圖片元素位置基本保持不變的目的 ;
/**
* 計(jì)算新的比例
*/
public void restore(){
// 縮放后的尺寸
double imageWidth = image.getWidth(null) * scale; // 縮放后的圖像寬度
double imageHeight = image.getHeight(null) * scale; // 縮放后的圖像高度
// 計(jì)算整張畫布寬度
double canvasX = imageWidth * pointer_ratio_x;
double canvasY = imageHeight * pointer_ratio_y;
// 計(jì)算畫布偏移
offsetX = (int) (pointer_x - canvasX);
offsetY = (int) (pointer_y - canvasY);
}
二、繪制超大圖像 + 鼠標(biāo)拖動(dòng) + 鼠標(biāo)滾輪縮放 + 以當(dāng)前鼠標(biāo)指針位置為縮放中心 示例
在 【Java AWT 圖形界面編程】Canvas 中繪制超大圖片 ( 使用鼠標(biāo)拖動(dòng)查看全圖 | 設(shè)置 JFrame 窗口自動(dòng)關(guān)閉 | 獲取并繪制圖片 | 鼠標(biāo)拖動(dòng)計(jì)算位移 | 畫布偏移 ) 博客中 , 繪制了超大圖像 , 可以使用鼠標(biāo)拖動(dòng) ;
在 【Java AWT 圖形界面編程】使用鼠標(biāo)滾輪放大縮小 Canvas 畫布 ( 鼠標(biāo)滾輪事件監(jiān)聽器 MouseWheelListener ) 博客中 , 新增鼠標(biāo)滾輪縮放畫布示例 , 但是使用鼠標(biāo)拖動(dòng)時(shí) , 拖動(dòng)的效果也隨之縮放, 如 縮小畫布后 , 移動(dòng)鼠標(biāo) , 移動(dòng)距離對(duì)應(yīng)的縮放效果也隨之縮小 ;
在 【Java AWT 圖形界面編程】使用鼠標(biāo)滾輪放大縮小 Canvas 畫布中繪制的背景圖像 ( 鼠標(biāo)滾輪事件監(jiān)聽器 MouseWheelListener | Canvas 中繪制圖像并設(shè)置圖像大小 ) 博客中 , 使用縮放背景圖像的方式 , 實(shí)現(xiàn)縮放效果 , 并同時(shí)福袋鼠標(biāo)指針拖拽效果 ;
本博客中實(shí)現(xiàn)的案例 , 在上面的基礎(chǔ)上 , 添加了鼠標(biāo)滾輪縮放的中心點(diǎn)設(shè)置為當(dāng)前鼠標(biāo)中心點(diǎn) ;
1、代碼示例
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
public class LargeCanvas extends JPanel {
// 鼠標(biāo)按下時(shí)的坐標(biāo) 以及 更新后的坐標(biāo)
private int startX, startY;
// 當(dāng)前的位置偏移
private int offsetX = 0, offsetY = 0;
// 縮放比例,默認(rèn)為 1.0
private double scale = 1.0;
private Image image;
public double pointer_ratio_x;
public double pointer_ratio_y;
public int pointer_x;
public int pointer_y;
public LargeCanvas() {
// 畫布大小設(shè)置為 800 x 600
// 繪制的圖片是 2K 大小的圖片
setPreferredSize(new Dimension(800, 600));
// 添加鼠標(biāo)滾輪監(jiān)聽器
addMouseWheelListener(new MouseWheelListener() {
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
// 保存當(dāng)前的鼠標(biāo)位置及比例
save(e.getX(), e.getY());
int notches = e.getWheelRotation();
if (notches < 0) {
// 滾輪向上,放大畫布
scale *= 1.1;
} else {
// 滾輪向下,縮小畫布
scale /= 1.1;
}
// 基于鼠標(biāo)位置和比例, 計(jì)算最新的偏移
restore();
repaint(); // 重新繪制畫布
}
});
// 為組件設(shè)置鼠標(biāo)監(jiān)聽事件
addMouseListener(new MouseAdapter() {
public void mousePressed(MouseEvent e) {
// 記錄鼠標(biāo)按下時(shí)的坐標(biāo)
startX = e.getX();
startY = e.getY();
}
});
// 添加鼠標(biāo)動(dòng)作監(jiān)聽
addMouseMotionListener(new MouseAdapter() {
// 鼠標(biāo)拖動(dòng)事件
public void mouseDragged(MouseEvent e) {
// 統(tǒng)計(jì)本次鼠標(biāo)移動(dòng)的相對(duì)值
int dx = e.getX() - startX;
int dy = e.getY() - startY;
// 偏移量累加
offsetX += dx;
offsetY += dy;
// 重新繪圖
repaint();
// 記錄當(dāng)前拖動(dòng)后的位置
startX += dx;
startY += dy;
}
});
}
/**
* 記錄滾輪縮放時(shí)鼠標(biāo)指針狀態(tài)
*/
public void save(int x, int y){
// 記錄鼠標(biāo)坐標(biāo)
pointer_x = x;
pointer_y = y;
// 計(jì)算畫布
double canvasX = x - offsetX;
double canvasY = y - offsetY;
// 計(jì)算圖片大小
double imageWidth = image.getWidth(null) * scale; // 縮放后的圖像寬度
double imageHeight = image.getHeight(null) * scale; // 縮放后的圖像高度
// 計(jì)算比例
pointer_ratio_x = canvasX / imageWidth ;
pointer_ratio_y = canvasY / imageHeight ;
}
/**
* 計(jì)算新的比例
*/
public void restore(){
// 縮放后的尺寸
double imageWidth = image.getWidth(null) * scale; // 縮放后的圖像寬度
double imageHeight = image.getHeight(null) * scale; // 縮放后的圖像高度
// 計(jì)算整張畫布寬度
double canvasX = imageWidth * pointer_ratio_x;
double canvasY = imageHeight * pointer_ratio_y;
// 計(jì)算畫布偏移
offsetX = (int) (pointer_x - canvasX);
offsetY = (int) (pointer_y - canvasY);
}
public void paintComponent(Graphics g) {
super.paintComponent(g);
// 畫布進(jìn)行整體偏移
Graphics2D g2 = (Graphics2D)g;
// 縮放畫布
//g2.scale(scale, scale);
// 拖動(dòng)畫布
g2.translate(offsetX, offsetY);
// 獲取圖片
this.image = Toolkit.getDefaultToolkit().getImage("image.jpg");
// 繪制圖形
//g2.drawImage(image, 0, 0, this);
// 繪制圖像
int imageWidth = (int) (image.getWidth(null) * scale); // 縮放后的圖像寬度
int imageHeight = (int) (image.getHeight(null) * scale); // 縮放后的圖像高度
g2.drawImage(image, 0, 0, imageWidth, imageHeight, null);
}
public static void main(String[] args) {
// 創(chuàng)建 JFrame 窗口
JFrame frame = new JFrame("Large Canvas");
// 設(shè)置窗口關(guān)閉行為 點(diǎn)擊右上角關(guān)閉按鈕 關(guān)閉窗口并退出應(yīng)用
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 創(chuàng)建畫布
LargeCanvas canvas = new LargeCanvas();
// 將畫布放入滾動(dòng)布局
JScrollPane scrollPane = new JScrollPane(canvas);
// 將滾動(dòng)布局放入窗口
frame.getContentPane().add(scrollPane);
// 窗口自適應(yīng)
frame.pack();
// 窗口設(shè)置可見
frame.setVisible(true);
}
}
2、執(zhí)行效果
執(zhí)行后 , 將圖像中船頭的 H 標(biāo)識(shí)放置在界面中心 ;
將鼠標(biāo)指針放在 H 位置 , 縮放 , 發(fā)現(xiàn)此時(shí)縮放 , 就是以當(dāng)前鼠標(biāo)指針為中心進(jìn)行的縮放 ;文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-556426.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-556426.html
到了這里,關(guān)于【Java AWT 圖形界面編程】使用鼠標(biāo)滾輪縮放 Canvas 畫布中繪制的背景圖像 ( 繪制超大圖像 + 鼠標(biāo)拖動(dòng) + 鼠標(biāo)滾輪縮放 + 以當(dāng)前鼠標(biāo)指針位置為縮放中心 示例 )的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!