用Golang写一束365朵鲜玫瑰花束,心形视频制作全攻略

我记得第一次看到那种用365朵玫瑰拼成心形、再拍成视频的创意时,心里就在想:这玩意儿要是能用代码自动生成,该多酷啊,后来真有人让我帮忙写...

我记得第一次看到那种用365朵玫瑰拼成心形、再拍成视频的创意时,心里就在想:这玩意儿要是能用代码自动生成,该多酷啊,后来真有人让我帮忙写个程序,我才发现这事儿比想象中有趣——不是把花放那儿就行,得控制每一朵的位置、角度、颜色渐变,还得让它们最终组成一颗完美的心,今天我就用 Golang 来拆解这个过程,保证你看完就能自己动手。

为什么是365朵?为什么是心形?

365朵,代表一年365天的爱——这个寓意很浪漫,但落到代码里,365个坐标点,你要做的,是把这些点排列成一个心形轮廓。心形曲线公式 有好几种,我常用的是这个参数方程:

x = 16 * sin³(t)
y = 13 * cos(t) - 5 * cos(2t) - 2 * cos(3t) - cos(4t)

t 从0到2π变化,但问题是:怎么让365朵花均匀分布在这条曲线上? 不能随便取365个t值,否则有的地方挤成一团,有的地方稀疏得像秃头,得用 等弧长采样——这个有点绕,但你记住关键点就行:先计算整条曲线的长度,再按每段长度相等来取点,Golang里用数值积分就能算,比如辛普森法则。

// 心形曲线上的点,按等弧长采样
type Point struct {
    X, Y float64
}
// 计算两点间距离——你懂的,欧几里得那套
func dist(a, b Point) float64 {
    dx, dy := a.X-b.X, a.Y-b.Y
    return math.Sqrt(dx*dx + dy*dy)
}

第二步:让玫瑰“长”在点上

有了365个点,接下来就是生成一朵朵玫瑰,这里有个小陷阱:每朵玫瑰要有自己的属性,比如颜色、大小、朝向,你不能让它们全一样,那样视频看着像批发市场。

我通常这样定义结构体:

type Rose struct {
    Position Point   // 在画面中的位置
    Color    string  // 颜色,quot;#FF0066"
    Scale    float64 // 大小缩放,0.8到1.2之间
    Rotate   float64 // 旋转角度,随机一点更好看
}

颜色怎么选?渐变是关键,心形中间偏亮粉,边缘偏深红,这样视觉上有层次感,Golang里处理颜色可以简单粗暴——用HSL转RGB,慢慢调整色相和饱和度。

func heartColor(index, total int) string {
    // 从中心到边缘,色相从350渐变到0
    hue := 350.0 - float64(index)/float64(total)*15.0
    // 饱和度固定在80%,亮度从90%降到70%
    sat := 0.8
    lum := 0.9 - float64(index)/float64(total)*0.2
    // 转成RGB再转Hex——这个函数你得自己写,别偷懒
    return hslToHex(hue, sat, lum)
}

第三步:把玫瑰“画”出来——别直接上视频,先渲染帧

做视频的本质是 攒好多张图片,然后拼成视频,Golang里没有现成的视频库,但我们可以先渲染成图片帧,再用FFmpeg合成,这样分工明确:你管生成图片,FFmpeg管合成

每帧的生成逻辑大概是:

  1. 创建一个画布(比如用 image.RGBA
  2. 画心形背景(渐变底色)
  3. 遍历365朵玫瑰,在对应位置画上玫瑰图形
  4. 每朵玫瑰画法:先画花心(小圆),再画花瓣(用贝塞尔曲线或简单椭圆)
  5. 保存为PNG

这里最耗时的不是代码,而是设计玫瑰的样子,如果你不想手绘,可以找个开源的玫瑰SVG,解析其路径再缩放旋转,我试过用GoSVG这个包,但兼容性不太好,建议直接用数学函数画花瓣——几个椭圆叠加,加上随机偏移,看起来就像真花了。

func drawRose(img *image.RGBA, x, y, scale, rot float64, color color.Color) {
    // 画中心的花蕊——一个小圆
    // 画6片花瓣,每片旋转60度,并随机扭曲一点
    for i := 0; i < 6; i++ {
        angle := float64(i)*60 + rot
        // 计算花瓣中心的位置
        px, py := x+math.Cos(angle)*15*scale, y+math.Sin(angle)*15*scale
        // 画椭圆花瓣
        drawEllipse(img, px, py, 20*scale, 10*scale, angle, color)
    }
    // 再加一些小点缀,提亮视觉
}

第四步:让视频动起来——心形“绽放”效果

静态的心形玫瑰已经很好看了,但视频嘛,总得有点动态,我做过两种效果:

  • 从中心向外绽放:第一帧只有中心几朵,后面逐帧增加,像花苞慢慢打开
  • 围绕心形旋转:所有玫瑰围绕心形中心旋转,产生环绕立体感

实现动态的关键是控制每朵玫瑰的显现时间,给每朵玫瑰一个appearTime字段,当前帧数大于等于这个时间才绘制,绽放顺序可以按到中心点的距离来排——近的先出来,远的后出来。

type AnimatedRose struct {
    Rose
    appearTime int // 第几帧开始出现
}
// 排序:按到中心的距离从小到大
sort.Slice(roses, func(i, j int) bool {
    di := dist(roses[i].Position, center)
    dj := dist(roses[j].Position, center)
    return di < dj
})

每帧生成时,判断当前帧数是否大于 appearTime,大于就画,否则跳过,这样视频看起来就是从心尖慢慢蔓延到整个心形,特别治愈。

用Golang写一束365朵鲜玫瑰花束,心形视频制作全攻略

第五步:输出视频——Golang + FFmpeg

Golang本身不合成视频,但可以生成图片序列+调用FFmpeg,代码里直接执行系统命令:

cmd := exec.Command("ffmpeg",
    "-framerate", "24",
    "-i", "frame_%04d.png",
    "-c:v", "libx264",
    "-pix_fmt", "yuv420p",
    "heart_roses.mp4")
cmd.Run()

注意帧率——24帧每秒比较流畅,如果你有300帧(12.5秒),每帧都包含365朵玫瑰,那处理时间可能有点长。优化技巧:玫瑰的图形可以预渲染成小图片(Sprite),每帧直接粘贴,省得每次都重新画花瓣。

实际踩过的坑

  • 文件命名:帧文件名必须是四位数字,比如frame_0012.png,否则FFmpeg不认
  • 颜色空间:心形背景如果用纯白,玫瑰颜色会显得刺眼,建议背景用浅灰色或淡粉色
  • 内存:如果一次性生成300张高清图片,内存会炸,改成边生成边保存边删除,保持内存200MB以下
  • 花瓣重叠:如果花瓣画得太密,爱心内部会变成一坨,要控制花瓣大小和间距,宁可稀疏点,也别糊成一团

我最初写的时候,花瓣重叠率超过40%,出来的视频像一坨番茄酱,后来调整了花瓣缩放因子,控制在0.6到0.9之间,才清晰起来。

不想写代码?也行

如果你只想获得365朵鲜玫瑰花束制作心形视频这个结果,不在乎过程,那市面上有现成的小程序和App,但说真的,自己用Golang写一遍,你能学到的东西更多:数学曲线的应用、图像处理的基础、视频合成的流程,甚至对“爱”这个主题也有了更数字化的理解——毕竟,每一朵玫瑰都是一个结构体,每一帧都是一次for循环。

当你把最终生成的视频发给朋友,说“这是我用代码写的365朵玫瑰”时,那种成就感,比买一束真花还爽,真花会谢,代码不会。

本文来自作者[kyadmin]投稿,不代表be365立场,如若转载,请注明出处:http://www.hljbesthome.com/keji/1012.html

(11)

文章推荐

发表回复

本站作者才能评论

评论列表(4条)

  • kyadmin
    kyadmin 2026-07-02

    我是be365的签约作者“kyadmin”!

  • kyadmin
    kyadmin 2026-07-02

    希望本篇文章《用Golang写一束365朵鲜玫瑰花束,心形视频制作全攻略》能对你有所帮助!

  • kyadmin
    kyadmin 2026-07-02

    本站[be365]内容主要涵盖:be365,be365网站,be365网址,ball365体育,Be365排名

  • kyadmin
    kyadmin 2026-07-02

    本文概览:我记得第一次看到那种用365朵玫瑰拼成心形、再拍成视频的创意时,心里就在想:这玩意儿要是能用代码自动生成,该多酷啊,后来真有人让我帮忙写...

    联系我们

    工作时间:周一至周五,9:30-18:30,节假日休息

    关注我们