使用Java繪制心形動(dòng)畫的代碼示例
代碼說明
動(dòng)畫原理:
使用
Timer定期更新心形的縮放比例(scale變量)縮放比例在0.8到1.2之間循環(huán)變化,產(chǎn)生心跳效果
每次縮放變化后調(diào)用
repaint()重繪組件
心形繪制:
使用
Path2D類和貝塞爾曲線繪制心形createHeart()方法創(chuàng)建心形路徑通過改變
size參數(shù)實(shí)現(xiàn)縮放效果
視覺效果:
黑色背景襯托紅色心形
添加了半透明的紅色發(fā)光效果增強(qiáng)視覺效果
啟用了抗鋸齒使圖形更平滑
運(yùn)行方法
將代碼保存為
HeartAnimation.java編譯運(yùn)行:
javac HeartAnimation.java && java HeartAnimation
你將看到一個(gè)400x400的窗口,其中有一個(gè)跳動(dòng)的紅色心形
import javax.swing.*;
import java.awt.*;
import java.awt.geom.Path2D;
import java.util.ArrayList;
import java.util.Random;
public class Main extends JPanel {
private float scale = 1.0f;
private float delta = 0.01f;
private final Color heartColor = new Color(255, 50, 50);
private ArrayList<Particle> particles = new ArrayList<>();
private Random random = new Random();
public Main() {
// 設(shè)置定時(shí)器來更新動(dòng)畫
Timer timer = new Timer(30, e -> {
scale += delta;
// 改變縮放方向時(shí)產(chǎn)生粒子
if (scale > 1.2f) {
delta = -0.01f;
createParticles();
} else if (scale < 0.8f) {
delta = 0.01f;
}
// 更新粒子
updateParticles();
repaint();
});
timer.start();
}
// 創(chuàng)建粒子
private void createParticles() {
int width = getWidth();
int height = getHeight();
int centerX = width / 2;
int centerY = height / 2;
int size = (int) (100 * scale);
// 創(chuàng)建20-30個(gè)新粒子
int particleCount = 20 + random.nextInt(10);
for (int i = 0; i < particleCount; i++) {
// 粒子從心形邊緣發(fā)射
double angle = random.nextDouble() * 2 * Math.PI;
double distance = size * (0.5 + random.nextDouble() * 0.3);
int x = centerX + (int)(distance * Math.cos(angle));
int y = centerY + (int)(distance * Math.sin(angle) * 0.8);
// 隨機(jī)速度和顏色
float speedX = (random.nextFloat() - 0.5f) * 3f;
float speedY = (random.nextFloat() - 0.8f) * 3f;
Color color = new Color(
255,
50 + random.nextInt(100),
50 + random.nextInt(100),
150 + random.nextInt(100)
);
particles.add(new Particle(x, y, speedX, speedY, color));
}
}
// 更新粒子位置和生命周期
private void updateParticles() {
for (int i = particles.size() - 1; i >= 0; i--) {
Particle p = particles.get(i);
p.update();
// 移除生命周期結(jié)束的粒子
if (p.life <= 0) {
particles.remove(i);
}
}
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2d = (Graphics2D) g;
// 啟用抗鋸齒
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
int width = getWidth();
int height = getHeight();
// 設(shè)置漸變背景
GradientPaint gradient = new GradientPaint(
0, 0, new Color(10, 10, 30),
width, height, new Color(30, 10, 50)
);
g2d.setPaint(gradient);
g2d.fillRect(0, 0, width, height);
// 先繪制粒子(在心形后面)
for (Particle p : particles) {
p.draw(g2d);
}
// 計(jì)算心形位置和大小
int centerX = width / 2;
int centerY = height / 2;
int size = (int) (100 * scale);
// 創(chuàng)建心形路徑
Path2D heart = createHeart(centerX, centerY, size);
// 繪制心形
g2d.setColor(heartColor);
g2d.fill(heart);
// 添加發(fā)光效果
g2d.setColor(new Color(255, 100, 100, 100));
for (int i = 1; i <= 5; i++) {
Path2D glowHeart = createHeart(centerX, centerY, size + i * 3);
g2d.fill(glowHeart);
}
}
private Path2D createHeart(int centerX, int centerY, int size) {
Path2D path = new Path2D.Double();
// 心形貝塞爾曲線
path.moveTo(centerX, centerY - size / 4);
// 左半邊心形
path.curveTo(
centerX - size / 2, centerY - size,
centerX - size, centerY,
centerX, centerY + size / 2
);
// 右半邊心形
path.curveTo(
centerX + size, centerY,
centerX + size / 2, centerY - size,
centerX, centerY - size / 4
);
return path;
}
// 粒子類
private class Particle {
float x, y;
float speedX, speedY;
Color color;
int life;
float size;
Particle(float x, float y, float speedX, float speedY, Color color) {
this.x = x;
this.y = y;
this.speedX = speedX;
this.speedY = speedY;
this.color = color;
this.life = 30 + random.nextInt(70); // 生命周期30-100幀
this.size = 2 + random.nextFloat() * 3; // 大小2-5像素
}
void update() {
x += speedX;
y += speedY;
speedY += 0.05f; // 重力效果
life--;
size *= 0.98f; // 逐漸縮小
}
void draw(Graphics2D g2d) {
float alpha = (float)life / 100f; // 根據(jù)生命周期計(jì)算透明度
if (alpha < 0) alpha = 0;
if (alpha > 1) alpha = 1;
g2d.setColor(new Color(
color.getRed(),
color.getGreen(),
color.getBlue(),
(int)(color.getAlpha() * alpha)
));
g2d.fillOval((int)x, (int)y, (int)size, (int)size);
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("帶粒子效果的心形動(dòng)畫");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(500, 500);
frame.setLocationRelativeTo(null);
Main animation = new Main();
frame.add(animation);
frame.setVisible(true);
}
}效果如圖

總結(jié)
到此這篇關(guān)于使用Java繪制心形動(dòng)畫的文章就介紹到這了,更多相關(guān)Java繪制心形動(dòng)畫內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
mybatis?查詢返回Map<String,Object>類型
本文主要介紹了mybatis?查詢返回Map<String,Object>類型,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03
解決Maven項(xiàng)目報(bào)錯(cuò):failed?to?execute?goal?org.apache.maven.plug
這篇文章主要介紹了解決Maven項(xiàng)目報(bào)錯(cuò):failed?to?execute?goal?org.apache.maven.plugins:maven-compiler-plugin:3.13.0的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2025-05-05
java實(shí)現(xiàn)驗(yàn)證碼類生成中文驗(yàn)證碼
java實(shí)現(xiàn)的漢字輸入驗(yàn)證碼,主要包含兩個(gè)類,一個(gè)是生成驗(yàn)證碼,一個(gè)是判斷驗(yàn)證碼輸入是否正確,實(shí)現(xiàn)原理非常簡(jiǎn)單,將漢字和干擾線生成圖片并將漢字保存到session,前臺(tái)獲取每次生成驗(yàn)證碼圖片并用文本框值和session值比較,功能就怎么簡(jiǎn)單2014-01-01
Mybatis實(shí)現(xiàn)單個(gè)和批量定義別名typeAliases
這篇文章主要介紹了Mybatis實(shí)現(xiàn)單個(gè)和批量定義別名typeAliases,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09
SpringBoot接入輕量級(jí)分布式日志框架(GrayLog)的操作方法
這篇文章主要介紹了SpringBoot接入輕量級(jí)分布式日志框架(GrayLog)的方法,本文通過圖文實(shí)例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03
關(guān)于Java的動(dòng)態(tài)代理機(jī)制
這篇文章主要介紹了關(guān)于Java的動(dòng)態(tài)代理機(jī)制,動(dòng)態(tài)代理就是,在程序運(yùn)行期,創(chuàng)建目標(biāo)對(duì)象的代理對(duì)象,并對(duì)目標(biāo)對(duì)象中的方法進(jìn)行功能性增強(qiáng)的一種技術(shù),需要的朋友可以參考下2023-05-05

