Direct2D教程(八)梯度色画刷

简介:

概述

单色画刷产生的颜色是单一的,比如一个红色画刷只能输出红色,而渐变画刷则不同,它可以输出多种颜色,这些颜色通常是连续的,从一个颜色平滑过渡到另一个颜色,看起来有渐变的效果。渐变画刷又分为两种,一种是ID2D1LinearGradientBrush(线性渐变画刷),另一种是ID2D1RadialGradientBrush(放射渐变画刷),下图显示了这两种画刷的效果。

线性渐变画刷

这种画刷的颜色从一个位置线性渐变到另外一个位置,所以在创建这种画刷之前需要确定以下两个属性

  • 起始位置及颜色
  • 终止位置及颜色

在Direct2D中,结构体D2D1_GRADIENT_STOP用来表示一个位置及其颜色,其定义如下:

struct D2D1_GRADIENT_STOP {
  FLOAT        position;
  D2D1_COLOR_F color;
};

其中第一个成员position表示位置,这个值得范围必须是[0.0, 1.0]。第二个成员color表示颜色。我们用两个这样的结构体变量就可以表示起始/终止位置及颜色了。

在创建画刷时,需要指定画刷的会制范围,如果待填充图形的范围大于画刷的会制范围,我们需要告诉D2D如何处填充超出范围的部分。这需要通过颜色的扩展方式来指定,颜色扩展的方式用D2D1_EXTEND_MODE这个枚举类型来表示,它的定义如下:

typedef enum  { 
  D2D1_EXTEND_MODE_CLAMP   = 0,
  D2D1_EXTEND_MODE_WRAP    = 1,
  D2D1_EXTEND_MODE_MIRROR  = 2
} D2D1_EXTEND_MODE;

如果大家了解纹理的话,对这几种方式一定不陌生,他们的含义如下:

  • D2D1_EXTEND_MODE_CLAMP,表示按照边缘的颜色进行扩展
  • D2D1_EXTEND_MODE_WRAP,表示重复画刷的颜色
  • D2D1_EXTEND_MODE_MIRROR,也是重复画刷的颜色,不过是以相反的方向进行,所以像镜面效果一样

这三种扩展方式的效果图如下,这里,矩形的宽度是画刷绘制范围的2倍,也就是说,颜色的扩展是从矩形的中间开始的。

D2D1_EXTEND_MODE_CLAMP

D2D1_EXTEND_MODE_WRAP

D2D1_EXTEND_MODE_MIRROR

下面开始具体的创建步骤,首先定义两个梯度点并指定其位置及颜色,这里第一个点位置是0,颜色是黄色,第二个点位置是1,颜色是红色。

D2D1_GRADIENT_STOP gradientStops[2] ;
gradientStops[0].color = D2D1::ColorF(D2D1::ColorF::Yellow) ;
gradientStops[0].position = 0.f ;
gradientStops[1].color = D2D1::ColorF(D2D1::ColorF::Red) ;
gradientStops[1].position = 1.f ;

其次,创建梯度点集合,这个集合将作为参数用来创建梯度色画刷,我们使用函数CreateGradientStopCollection来完成这个任务,它的定义如下:

复制代码
virtual HRESULT CreateGradientStopCollection(
  [in]   const D2D1_GRADIENT_STOP *gradientStops,
  UINT gradientStopsCount,
  D2D1_GAMMA colorInterpolationGamma,
  D2D1_EXTEND_MODE extendMode,
  [out]  ID2D1GradientStopCollection **gradientStopCollection
) = 0;
复制代码

参数说明:

  • gradientStops,梯度点数组,也就是上面刚刚创建的。
  • gradientStopsCount,梯度点个数,这里是两个。
  • colorInterpolationGamma,这个参数用来控制颜色插值的方式,有如下两种:
typedef enum  { 
  D2D1_GAMMA_2_2  = 0,
  D2D1_GAMMA_1_0  = 1
} D2D1_GAMMA;

这两种方式的效果图如下,这里我们使用D2D1_GAMMA_2_2。

extendMode,指定颜色超出绘制范围时如何扩展。这里我们使用D2D1_EXTEND_MODE_CLAMP,也就是按照边缘色扩展。

gradientStopCollection,这个参数用来接收创建后的梯度点集合。

创建梯度点集合的代码如下,所有参数前面均已说明。

复制代码
// Create gradient stops collection
ID2D1GradientStopCollection* pGradientStops = NULL ;
hr = pRenderTarget->CreateGradientStopCollection(
    gradientStops,
    2, 
    D2D1_GAMMA_2_2,
    D2D1_EXTEND_MODE_CLAMP,
    &pGradientStops
    ) ;
if (FAILED(hr))
{
    MessageBox(NULL, "Create gradient stops collection failed!", "Error", 0);
}
复制代码

最后,创建线性梯度色画刷。我们使用函数CreateLinearGradientBrush,看看它的定义:

virtual HRESULT CreateLinearGradientBrush(
  [in]            const D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES *linearGradientBrushProperties,
  [in, optional]  const D2D1_BRUSH_PROPERTIES *brushProperties,
  [in]            ID2D1GradientStopCollection *gradientStopCollection,
  [out]           ID2D1LinearGradientBrush **linearGradientBrush
) = 0;

参数说明:

  • linearGradientBrushProperties,用来指定画刷的起始位置和终止位置。
  • brushProperties,这是个可选参数,用来指定画刷的透明度及变换矩阵,这里我们指定其为NULL。
  • gradientStopCollection,梯度点集合,一般我们指定两个即可,分别是起始位置和终止位置。
  • linearGradientBrush,用来接收创建好的画刷。

具体代码如下,画刷的起始和结束位置分别对应矩形的左上角点和右下角点。

复制代码
// Create a linear gradient brush to fill in the rectangle
hr = pRenderTarget->CreateLinearGradientBrush(
    D2D1::LinearGradientBrushProperties(
    D2D1::Point2F(roundRect.rect.left, roundRect.rect.top),
    D2D1::Point2F(roundRect.rect.right, roundRect.rect.bottom)),
    pGradientStops,
    &pLinearGradientBrush
    ) ;

if (FAILED(hr))
{
    MessageBox(hWnd, "Create linear gradient brush failed!", "Error", 0) ;
    return ;
}
复制代码

效果图

放射渐变画刷

这种画刷的颜色从一个中心点向周围扩散,呈放射状,这可能也是其名字的由来吧。创建这种画刷的步骤和上面一样,先创建梯度点及其集合,然后使用函数CreateRadialGradientBrush创建画刷,关于如何创建梯度点及其集合,前面已经说了,所以这里只看创建画刷的步骤。函数CreateRadialGradientBrush的定义如下:

HRESULT CreateRadialGradientBrush(
  const D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES &radialGradientBrushProperties,
  [in]   ID2D1GradientStopCollection *gradientStopCollection,
  [out]  ID2D1RadialGradientBrush **radialGradientBrush
);

参数说明:

  • radialGradientBrushProperties,画刷属性,用以下结构体来表示:
struct D2D1_RADIAL_GRADIENT_BRUSH_PROPERTIES {
  D2D1_POINT_2F center;
  D2D1_POINT_2F gradientOriginOffset;
  FLOAT         radiusX;
  FLOAT         radiusY;
};
    • center, 梯度中心点,从此点开始向外围放射
    • gradientOriginOffset,起始点偏移,一般设置为(0,0)
    • radiusX,椭圆x轴长度
    • radiusY,椭圆y轴长度
  • gradientStopCollection,梯度点集合
  • radialGradientBrush,用来接收创建后的画刷

代码如下:

创建椭圆

D2D1_ELLIPSE g_Ellipse = D2D1::Ellipse(D2D1::Point2F(300, 300), 200, 150);

创建画刷,这里我们指定起始颜色为黄色,终止颜色为蓝色,填充图形为椭圆,颜色从椭圆的中心向周围发散。

复制代码
// Create a linear gradient brush to fill in the rectangle
hr = pRenderTarget->CreateRadialGradientBrush(
    D2D1::RadialGradientBrushProperties(
    g_Ellipse.point,
    D2D1::Point2F(0, 0),
    g_Ellipse.radiusX,
    g_Ellipse.radiusY),
    pGradientStops,
    &pRadialGradientBrush
    ) ;

if (FAILED(hr))
{
    MessageBox(hWnd, "Create linear gradient brush failed!", "Error", 0) ;
    return ;
}
复制代码

效果图

使用渐变画刷配合椭圆及圆角矩形可以创建出非常漂亮的Button控件,如果你喜欢自定义控件,不妨试一试。

== Happy Coding ==


本文转自zdd博客园博客,原文链接:http://www.cnblogs.com/graphics/archive/2012/11/22/2764876.html,如需转载请自行联系原作者

相关文章
|
人工智能 Serverless 数据库
在函数计算上部署专属的Agent平台
Agent 是公认的可以将AI能力跟具体业务结合的技术方案,而Agent Platform 是将Agent开发流程进行整合抽象后的平台工程,能够极大的提升Agent的构建和发布效率,帮助企业获取先机。本篇文章介绍如何在函数计算上部署一套Serverless架构的Agent平台- [AgentCraft](https://agentcraft-docs.serverless-developer.com/)
83672 7
在函数计算上部署专属的Agent平台
|
4月前
|
人工智能 监控 安全
中国AI专利数全球领先,算力总规模位居第二
在数字化时代,人工智能与算力成为全球科技竞争核心。中国AI专利占全球60%,算力规模位居第二,展现其在数字技术领域的强大实力。政策支持、科研投入与市场需求推动AI专利快速增长,算力基础设施不断完善,助力产业数字化转型。中国在AI与算力领域的领先优势,不仅提升其全球科技竞争力,也为全球技术发展贡献力量。未来,中国将持续推动技术创新、产业应用与国际合作,助力全球科技进步。
203 0
|
机器学习/深度学习 数据采集 人工智能
Machine Learning机器学习之贝叶斯网络(BayesianNetwork)
Machine Learning机器学习之贝叶斯网络(BayesianNetwork)
|
存储 网络协议 Java
网络通信的核心机制:Socket如何实现高效数据传输(上)
网络通信的核心机制:Socket如何实现高效数据传输
|
SQL 关系型数据库 MySQL
mysql数据库故障排查
mysql数据库故障排查
557 0
|
9月前
|
自然语言处理 安全 数据可视化
企业级开源CMS新标杆,三分钟搭建多语言官网!
HuoCMS是基于ThinkPHP6和Vue3研发的现代化内容管理系统,专为中小企业及开发者打造全场景数字化解决方案。系统采用MIT开源协议,支持多语言、多终端适配,内置可视化编辑器与SEO优化体系,已成功应用于300+企业官网项目。
278 5
|
Web App开发 存储 监控
iLogtail 开源两周年:UC 工程师分享日志查询服务建设实践案例
本文为 iLogtail 开源两周年的实践案例分享,讨论了 iLogtail 作为日志采集工具的优势,包括它在性能上超越 Filebeat 的能力,并通过一系列优化解决了在生产环境中替换 Filebeat 和 Logstash 时遇到的挑战。
484 101
|
Java Maven
Maven的生命周期
Maven生命周期分为清理、构建和站点生成三部分,每部分含多个固定顺序执行的阶段。清理包括pre-clean和clean;构建涵盖validate、compile、test、package、install及deploy;站点生成则有pre-site、site、post-site与site-deploy。
328 6
|
机器学习/深度学习 人工智能 算法
AI辅助医疗影像:提高诊断准确性
【10月更文挑战第2天】医学影像技术是现代医学诊断的关键手段,但传统方法依赖医生经验,存在误诊风险。AI辅助医疗影像通过自动化图像识别、疾病预测和辅助诊断决策,显著提升了诊断准确性与效率。利用深度学习、数据增强及迁移学习等技术,AI不仅能快速分析影像,还能提供个性化诊疗建议,并实时监测疾病变化。尽管面临数据质量、算法可解释性和伦理法律等挑战,但多模态影像分析、跨学科合作及VR融合等趋势将推动AI在医疗影像领域的广泛应用,助力实现更精准、高效的医疗服务。
1011 3
|
JavaScript
详细讲解JS的解构赋值(Es6)
详细讲解JS的解构赋值(Es6)