前语

之前有部电视剧《点燃我温暖你》没火,可是其中李峋的爱心代码却在程序圈超级火,这圣诞节快到了了,给我们来一波爱心代码的教学。期望我们能在圣诞节该浪漫的浪漫、该脱单的脱单,加油兄弟!一起我也把完成思路经过动画给我们说清楚,期望各个言语的大佬都能一起开发出来,浪漫2022!(开发了能够在谈论区留个言哦~)

特别说明:勇哥的粉丝,能够谈论区或私信留言给我,我直接把你想写的话和姓名,直接给你打包好!

解释一下,创作思路:

  • 程序以信封的方式,能够增加浪漫与惊喜的仪式感!
  • 心的形状+玫瑰花的形状,两层美丽,不怕你的她不喜欢!
  • 心跳+呼吸灯的作用,意义:你的心围她而动的深刻意义!
  • 内部心不断滚动的作用,意义:你的心围她而动的深刻意义!(两层强调更具浪漫)

【圣诞节】会呼吸的玫瑰爱心代码 -李峋爱心续 动画演示思路 代码开源 一起浪漫吧

要点学习或必要技术

  • 关于不规则图形的制作示例:从本文中将学习到java中GeneralPath制作不规则图形的高档应用。
  • 关于不规则图形的填充示例:从本文中将学习到不规则图形的,特别是射线突变填充等高档应用。
  • 关于不规则图形的动画示例:从本文中将学习到图形平移、旋转、以及多层次的平移等高档应用。

心的概括思路及完成

制作好基本概括之后,填充的色彩、特效等才不会溢出概括,因而我们第一步需求画好重要的概括线,完成思路如下:

经过二次曲线(Java中是QuadCurve2D)来画出概括线,概括线分为以下九段:

  • 第一段为心的最上左面
  • 第二段为心的最上右边
  • 第三段心的最下,有点起伏让心看起来中心点平滑一些;留意上面线段比下面线段长,有主次感;
  • 第四段为右上角
  • 第五段为右边
  • 第六段为右下角
  • 第七段为左下角,与第六段对称
  • 第八段为左面,与第五段对称
  • 第九段为左上角,与第四段对称

PS:有人可能不明白,为什么要画这么杂乱?勇哥给解释一下,这样画,有9个点和9个线段,蕴含长长久久的意思!懂了吧~

来看一下动画演示的作用吧:

【圣诞节】会呼吸的玫瑰爱心代码 -李峋爱心续 动画演示思路 代码开源 一起浪漫吧

参阅代码:

GeneralPath generalPath = new GeneralPath();
// 左面
g2d.setColor(bgColor);
generalPath.moveTo(getWidth()/2-6,getHeight()*3/10);
generalPath.quadTo(getWidth()/2,getHeight()*3/10+5,getWidth()/2+6,getHeight()*3/10);// 上中
generalPath.quadTo(getWidth()*5/8,getHeight()*2/10,getWidth()*3/4,getHeight()*2/10);// 右上
generalPath.quadTo(getWidth(),getHeight()*2/10+10,getWidth()-5,getHeight()*2/5);
generalPath.quadTo(getWidth(),getHeight()*3/5,getWidth()/2+5,getHeight()*4/5);
generalPath.quadTo(getWidth()/2,getHeight()*4/5+3,getWidth()/2-5,getHeight()*4/5);
generalPath.quadTo(10,getHeight()*3/5,5,getHeight()*2/5);
generalPath.quadTo(0,getHeight()*2/10,getWidth()*1/4,getHeight()*2/10);
generalPath.quadTo(getWidth()*3/8,getHeight()*2/10,getWidth()/2-6,getHeight()*3/10);

玫瑰心思路及完成

有了概括就能够完成玫瑰花的作用了,思路就两步如下:

  • 纯色填充不好看,使用射线填充,纯色(#ffffff)到赤色(#ff0000)的射线突变
  • 仿制9个突变好的心,依照中心点堆叠起来玫瑰花的作用

PS:这个地方又是9,看得出勇哥的用心规划了吧~

动画演示一番,期望得的点赞:

【圣诞节】会呼吸的玫瑰爱心代码 -李峋爱心续 动画演示思路 代码开源 一起浪漫吧

参阅完成代码:

for (int i = 0; i < 9; i++) {
  AffineTransform transform = g2d.getTransform();
  transform.scale(0.6d, 0.6d);
  transform.translate(getWidth() *0.34, getHeight()*0.34);
  if(i>3) {
    transform.rotate(theta % 360, getWidth() / 2, getHeight() / 2);
   }
  g2d.setTransform(transform);
  g2d.draw(generalPath);
  g2d.setColor(Color.RED);
  Color[] colors = { Color.RED, Color.WHITE, Color.RED };
  float[] dist = {0.13f, 0.55f, 1.0f };
  Point2D center = new Point2D.Float(0.5f * getWidth(), 0.5f * getHeight()-10);
​
  RadialGradientPaint p = new RadialGradientPaint(center, 0.5f * getWidth()*per, dist, colors);
  g2d.setPaint(p);
  g2d.fill(generalPath);
}

呼吸作用&内部心旋转思路及完成

呼吸作用,能够经过控制射线的巨细份额来控制:

  • 定义per变量,等于1时,表明上一步的突变作用,1.4时表明白色圆圈扩展1.4倍,横竖缩小
  • 经过线程每100ms修正一下缩放份额,步长为0.1

内部心旋转思路:

  • 定义theta变量,表明内部心旋转的视点
  • 经过线程每100ms修正一下视点值,步长为2度
double theta = 0;// 选择的视点
float per = 1;// 镜像的巨细份额
boolean isAdd = true;// 镜像巨细是+核算还是-核算@Override
public void run() {
  while (true){
    try {
      theta += 2;
      if (isAdd) {
        per += 0.1;
        if (per > 1.3) {
          isAdd = false;
         }
       } else {
        per -= 0.1;
        if (per < 0.6) {
          isAdd = true;
         }
       }
      repaint();
      Thread.sleep(100);
     } catch (InterruptedException e) {
     }
   }
}