You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Cairo实现填充形状外部区域(保留透明孔洞)

如何用Cairo实现带透明圆形孔洞的蓝色背景?

嘿,我刚好能解决你这个问题!你需要的是“在蓝色背景上挖一个透明圆形洞”的效果,Cairo里有两种非常实用的实现方式,我给你详细拆解并附上C和Python的代码示例:

方法1:利用奇偶填充规则(Even-Odd Fill Rule)

Cairo默认的填充规则是WINDING,它会填充所有路径包围的区域;而EVEN_ODD规则会交替填充——路径重叠偶数次的区域不会被填充,刚好可以用来做“挖洞”效果。

C语言示例

#include <cairo.h>
#include <math.h>

int main() {
    // 创建300x300的ARGB32格式surface(支持透明)
    cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 300);
    cairo_t *cr = cairo_create(surface);

    // 先把整个surface初始化为透明
    cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
    cairo_paint(cr);

    // 切换到奇偶填充规则
    cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);

    // 设置蓝色背景的颜色(不透明蓝)
    cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0);
    // 绘制覆盖整个surface的矩形
    cairo_rectangle(cr, 0, 0, 300, 300);

    // 在中心绘制一个半径80的圆形(这就是我们要的孔洞)
    cairo_arc(cr, 150, 150, 80, 0, 2 * M_PI);

    // 填充路径:奇偶规则会让圆形区域(两层路径重叠)不被填充,保持透明
    cairo_fill(cr);

    // 保存为PNG文件
    cairo_surface_write_to_png(surface, "transparent_hole_bg.png");

    // 清理资源
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
    return 0;
}

Python(Pycairo)示例

import cairo

# 创建300x300的透明surface
surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 300, 300)
cr = cairo.Context(surface)

# 初始化透明背景
cr.set_source_rgba(0.0, 0.0, 0.0, 0.0)
cr.paint()

# 设置奇偶填充规则
cr.set_fill_rule(cairo.FILL_RULE_EVEN_ODD)

# 绘制蓝色背景矩形
cr.set_source_rgba(0.0, 0.0, 1.0, 1.0)
cr.rectangle(0, 0, 300, 300)

# 绘制中心圆形孔洞
cr.arc(150, 150, 80, 0, 2 * 3.14159265)

# 填充路径
cr.fill()

# 保存结果
surface.write_to_png("transparent_hole_bg_python.png")

方法2:使用DEST_OUT绘图操作符

另一种更直接的思路是:先铺满蓝色背景,然后用DEST_OUT操作符绘制圆形——这个操作符会把圆形区域的内容清除为透明,相当于直接“挖洞”。

C语言示例

#include <cairo.h>
#include <math.h>

int main() {
    cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 300, 300);
    cairo_t *cr = cairo_create(surface);

    // 先绘制整个蓝色背景
    cairo_set_source_rgba(cr, 0.0, 0.0, 1.0, 1.0);
    cairo_paint(cr);

    // 设置操作符为DEST_OUT:保留目标(蓝色背景)中不在源路径内的部分,源路径内变透明
    cairo_set_operator(cr, CAIRO_OPERATOR_DEST_OUT);

    // 绘制中心圆形,这里的颜色不影响,操作符决定最终效果
    cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
    cairo_arc(cr, 150, 150, 80, 0, 2 * M_PI);
    cairo_fill(cr);

    // 保存并清理
    cairo_surface_write_to_png(surface, "transparent_hole_operator.png");
    cairo_destroy(cr);
    cairo_surface_destroy(surface);
    return 0;
}

Python(Pycairo)示例

import cairo

surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, 300, 300)
cr = cairo.Context(surface)

# 绘制蓝色背景
cr.set_source_rgba(0.0, 0.0, 1.0, 1.0)
cr.paint()

# 设置DEST_OUT操作符,用于清除圆形区域为透明
cr.set_operator(cairo.OPERATOR_DEST_OUT)

# 绘制圆形孔洞
cr.arc(150, 150, 80, 0, 2 * 3.14159265)
cr.fill()

# 保存结果
surface.write_to_png("transparent_hole_operator_python.png")

两种方法的适用场景

  • 如果需要创建多个不规则孔洞,方法1的奇偶填充规则会更灵活——你只需要在矩形内部添加更多路径即可。
  • 如果只是单个简单孔洞,方法2的代码更简洁,逻辑也更直观。

两种方法都能完美实现你要的“蓝色背景+透明圆形孔洞”效果,你可以根据自己的实际需求选择~

内容的提问来源于stack exchange,提问作者BobMorane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:12:30