PyCairo 中的透明度
在 PyCairo 教程的这个部分,我们将讨论透明度。我们将提供一些基本的定义和三个有趣的透明度的例子。
透明度是指透过一种材料能够看到的品质。理解透明度最简单的方法是想象一块玻璃或水。技术上来说,光线可以穿过玻璃,因而我们可以看到玻璃后面的物体。
在计算机图形学中,我们可以用 alpha 合成 实现透明度效果。Alpha 合成是一个将一幅图片和背景结合起来创建部分透明的外观的过程。合成过程使用 alpha 通道。在用于表达半透明(透明度)的图像文件格式中,alpha 通道是一个 8-bit 的layer。每像素额外的 8 bits 被用作一个 mask 并代表256级的半透明度。
透明的矩形
第一个例子将绘制 10 个具有不同半透明度的矩形。
def on_draw(self, wid, cr):for i in range(1, 11):cr.set_source_rgba(0, 0, 1, i * 0.1)cr.rectangle(50 * i, 20, 40, 40)cr.fill()
set_source_rgba()
方法有一个 alpha 参数来提供透明度。
for i in range(1, 11):cr.set_source_rgba(0, 0, 1, i * 0.1)cr.rectangle(50 * i, 20, 40, 40)cr.fill()
这段代码创建了 10 个矩形,它们的 alpha 值分别为 0.1,…,1。
Puff 效果
在下面的例子中,我们创建一个 puff 效果。例子将显示一个增长的居中的文字,并从一些点开始逐渐褪色。这是一个非常常见的效果,我们经常可以在闪光动画中看到它。paint_with_alpha()
方法对于创建这个效果非常重要。
#!/usr/bin/python'''
ZetCode PyCairo tutorialThis program creates a 'puff'
effect.author: Jan Bodnar
website: zetcode.com
last edited: August 2012
'''import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
import cairoclass cv(object):SPEED = 14TEXT_SIZE_MAX = 20ALPHA_DECREASE = 0.01SIZE_INCREASE = 0.8class Example(Gtk.Window):def __init__(self):super(Example, self).__init__()self.init_ui()def init_ui(self):self.darea = Gtk.DrawingArea()self.darea.connect("draw", self.on_draw)self.add(self.darea)self.timer = Trueself.alpha = 1.0self.size = 1.0GLib.timeout_add(cv.SPEED, self.on_timer)self.set_title("Puff")self.resize(350, 200)self.set_position(Gtk.WindowPosition.CENTER)self.connect("delete-event", Gtk.main_quit)self.show_all()def on_timer(self):if not self.timer: return Falseself.darea.queue_draw()return Truedef on_draw(self, wid, cr):w, h = self.get_size()cr.set_source_rgb(0.5, 0, 0)cr.paint()cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_BOLD)self.size = self.size + cv.SIZE_INCREASEif self.size > cv.TEXT_SIZE_MAX:self.alpha = self.alpha - cv.ALPHA_DECREASEcr.set_font_size(self.size)cr.set_source_rgb(1, 1, 1)(x, y, width, height, dx, dy) = cr.text_extents("ZetCode")cr.move_to(w / 2 - width / 2, h / 2)cr.text_path("ZetCode")cr.clip()cr.paint_with_alpha(self.alpha)if self.alpha <= 0:self.timer = Falsedef main():app = Example()Gtk.main()if __name__ == "__main__":main()
这个例子在窗口中创建一段不断增长并褪色的文本。
class cv(object):SPEED = 14TEXT_SIZE_MAX = 20ALPHA_DECREASE = 0.01SIZE_INCREASE = 0.8
这里我们定义了一些将在例子中使用的常量。
self.alpha = 1.0self.size = 1.0
这两个变量存储当前的 alpha 值和字体大小。
GLib.timeout_add(cv.SPEED, self.on_timer)
每隔 14 ms,on_timer()
方法被调用一次。
def on_timer(self):if not self.timer: return Falseself.darea.queue_draw()return True
在 on_timer()
方法中,我们通过 queue_draw()
方法重绘 DrawingArea widget。
def on_draw(self, wid, cr):w, h = self.get_size()cr.set_source_rgb(0.5, 0, 0)cr.paint()cr.select_font_face("Courier", cairo.FONT_SLANT_NORMAL,cairo.FONT_WEIGHT_BOLD). . .
在 on_draw()
方法中,我们获取窗口的客户区域的宽度和高度。这些值被用于使文字居中。我们将以某种暗红色填充窗口的背景。我们为文字选择一个 Courier 字体。
(x, y, width, height, dx, dy) = cr.text_extents("ZetCode")
我们获取文字的一些度量值。我们将只使用文字宽度。
cr.move_to(w / 2 - width / 2, h / 2)
我们移动到一个可以使文字在窗口中居中的位置。
cr.text_path("ZetCode")cr.clip()cr.paint_with_alpha(self.alpha)
我们用 text_path()
方法获取文字的 path。我们用 clip()
方法将绘制限定在当前的path。paint_with_alpha()
方法使用一个 alpha 值的 mask,在当前的裁剪区域内,绘制当前的 source。
图像倒影
在下一个例子中,我么将秀出一个倒影图像。这个效果创造了一种图像倒映在水中的感觉。
#!/usr/bin/python'''
ZetCode PyCairo tutorialThis program creates an image reflection.author: Jan Bodnar
website: zetcode.com
last edited: August 2012
'''import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
import cairo
import sysclass Example(Gtk.Window):def __init__(self):super(Example, self).__init__()self.init_ui()self.load_image()self.init_vars()def init_ui(self):darea = Gtk.DrawingArea()darea.connect("draw", self.on_draw)self.add(darea)self.set_title("Reflection")self.resize(300, 350)self.set_position(Gtk.WindowPosition.CENTER)self.connect("delete-event", Gtk.main_quit)self.show_all()def load_image(self):try:self.s = cairo.ImageSurface.create_from_png("slanec.png")except Exception as e:print(e)sys.exit(1)def init_vars(self):self.imageWidth = self.s.get_width()self.imageHeight = self.s.get_height()self.gap = 40self.border = 20def on_draw(self, wid, cr):w, h = self.get_size()lg = cairo.LinearGradient(w / 2, 0, w / 2, h * 3)lg.add_color_stop_rgba(0, 0, 0, 0, 1)lg.add_color_stop_rgba(h, 0.2, 0.2, 0.2, 1)cr.set_source(lg)cr.paint()cr.set_source_surface(self.s, self.border, self.border)cr.paint()alpha = 0.7step = 1.0 / self.imageHeightcr.translate(0, 2 * self.imageHeight + self.gap)cr.scale(1, -1)i = 0while (i < self.imageHeight):cr.rectangle(self.border, self.imageHeight - i,self.imageWidth, 1)i = i + 1cr.save()cr.clip()cr.set_source_surface(self.s, self.border,self.border)alpha = alpha - stepcr.paint_with_alpha(alpha)cr.restore()def main():app = Example()Gtk.main()if __name__ == "__main__":main()
在语法方面,需要注意一下 Python 2.7 和 Python 3 在异常处理方面的差异。一个倒映的城堡的废墟就显示在窗口中了。
def load_image(self):try:self.s = cairo.ImageSurface.create_from_png("slanec.png")except Exception as e:print(e)sys.exit(1)
在 load_image()
方法中,由一幅 PNG 图片创建一个图像 surface。
def init_vars(self):self.imageWidth = self.s.get_width()self.imageHeight = self.s.get_height()self.gap = 40self.border = 20
在 init_vars()
方法中,我们获取图像的宽度和高度。同时定义两个变量。
lg = cairo.LinearGradient(w / 2, 0, w / 2, h * 3)lg.add_color_stop_rgba(0, 0, 0, 0, 1)lg.add_color_stop_rgba(h, 0.2, 0.2, 0.2, 1)cr.set_source(lg)cr.paint()
窗口的背景由一个渐变绘制填充。绘制是一个平滑的由黑色到深灰色的混合。
cr.translate(0, 2 * self.imageHeight + self.gap)cr.scale(1, -1)
这段代码翻转图像,并将它平移到原始图像的下方。平移操作是必须的,因为放缩操作使得图像翻转并将图像向上平移。为了理解发生了什么,可以简单地拍一张照片,将它放在桌子上,然后反转它。
i = 0while (i < self.imageHeight):cr.rectangle(self.border, self.imageHeight - i,self.imageWidth, 1)i = i + 1cr.save()cr.clip()cr.set_source_surface(self.s, self.border,self.border)alpha = alpha - stepcr.paint_with_alpha(alpha)cr.restore()
这是最后的部分。我们使第二幅图片变得透明。但透明度不是固定的。这幅图片渐渐地褪色。倒影图像是一行接一行绘制的。clip()
方法将绘制限定在高度为 1 的矩形中。paint_with_alpha()
在绘制图像 surface 的当前裁剪区域时会将透明度也考虑进来。
等待效果 Demo
在这个例子中,我们使用透明效果创建一个等待效果的 demo。我们将绘制 8 跳线,它们逐渐的淡出,以创造一种假象,好像线在移动一般。这种效果经常被用于告知用户,一个耗时比较久的任务正在后台运行。一个例子是 Interne 上的流视频。
#!/usr/bin/python'''
ZetCode PyCairo tutorialThis program creates a 'waiting' effect.author: Jan Bodnar
website: zetcode.com
last edited: August 2012
'''import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk, GLib
import cairo
import mathclass cv(object):trs = ((0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0),(1.0, 0.0, 0.15, 0.30, 0.5, 0.65, 0.8, 0.9),(0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65, 0.8),(0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65),(0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5),(0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3),(0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15),(0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0,))SPEED = 100CLIMIT = 1000NLINES = 8class Example(Gtk.Window):def __init__(self):super(Example, self).__init__()self.init_ui()def init_ui(self):self.darea = Gtk.DrawingArea()self.darea.connect("draw", self.on_draw)self.add(self.darea)self.count = 0GLib.timeout_add(cv.SPEED, self.on_timer)self.set_title("Waiting")self.resize(250, 150)self.set_position(Gtk.WindowPosition.CENTER)self.connect("delete-event", Gtk.main_quit)self.show_all()def on_timer(self):self.count = self.count + 1if self.count >= cv.CLIMIT:self.count = 0self.darea.queue_draw()return Truedef on_draw(self, wid, cr):cr.set_line_width(3)cr.set_line_cap(cairo.LINE_CAP_ROUND)w, h = self.get_size()cr.translate(w / 2, h / 2)for i in range(cv.NLINES):cr.set_source_rgba(0, 0, 0, cv.trs[self.count % 8][i])cr.move_to(0.0, -10.0)cr.line_to(0.0, -40.0)cr.rotate(math.pi / 4)cr.stroke()def main():app = Example()Gtk.main()if __name__ == "__main__":main()
我们以八个不同的 alpha 值绘制了八条直线。
class cv(object):trs = ((0.0, 0.15, 0.30, 0.5, 0.65, 0.80, 0.9, 1.0),(1.0, 0.0, 0.15, 0.30, 0.5, 0.65, 0.8, 0.9),(0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65, 0.8),(0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5, 0.65),(0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3, 0.5),(0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15, 0.3),(0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0, 0.15),(0.15, 0.3, 0.5, 0.65, 0.8, 0.9, 1.0, 0.0,))
. . .
这是一个 Demo 中会用到的透明度值的二维元组。有 8 行,每一行表示一种状态。8 条直线中的每一条将连续使用这些值。
SPEED = 100CLIMIT = 1000NLINES = 8
SPEED
常量控制动画的速度。CLIMIT
是 self.count
变量的最大值。达到这个限制之后,变量会被重置为 0。NLINES
是这个例子中绘制的直线的条数。
GLib.timeout_add(cv.SPEED, self.on_timer)
我们使用定时器函数创建动画。每一个 cv.SPEED
ms,on_timer() 方法会被调用一次。
def on_timer(self):self.count = self.count + 1if self.count >= cv.CLIMIT:self.count = 0self.darea.queue_draw()return True
在 on_timer()
方法中,我们增加 self.count
变量。如果变量达到了 cv.CLIMIT
常量,它会被设置为 0。我们避免溢出,并且不使用非常大的数字。
def on_draw(self, wid, cr):cr.set_line_width(3)cr.set_line_cap(cairo.LINE_CAP_ROUND). . .
我们使线更粗一点,以使得它们更容易被看到。我们用圆形的帽子绘制直线。
w, h = self.get_size()cr.translate(w / 2, h / 2)
我们将我们的绘制定位在窗口的中心。
for i in range(cv.NLINES):cr.set_source_rgba(0, 0, 0, cv.trs[self.count % 8][i])cr.move_to(0.0, -10.0)cr.line_to(0.0, -40.0)cr.rotate(math.pi / 4)cr.stroke()
在 for
循环中,我们用不同的透明度值,绘制了八条旋转的直线。线之间由 45 度角隔开。
本章我们讨论了透明度。
原文
Done.
PyCairo 中的透明度相关推荐
- PyCairo 中的图片
PyCairo 教程的这个部分,我们将讨论图片.我们将演示如何在 GTK 窗口中显示一幅 PNG 或JPEG 图片.我们也将在图片上绘制一些文字. 显示一幅 PNG 图片 在第一个例子中,我们将显示一 ...
- PyCairo 中的文本
PyCairo 教程的这个部分,我们将与文本打交道. 灵魂伴侣 在第一个例子中,我们将在窗口中显示一些歌词. def on_draw(self, wid, cr):cr.set_source_rgb( ...
- PyCairo 中的剪裁和屏蔽
在 PyCairo 教程的这个部分,我们将讨论剪裁和屏蔽操作. 剪裁 裁剪 是将绘制限定在某一区域内.这样做有一些效率的因素,或者为了创建有趣的效果.PyCairo 有一个 clip() 方法用于设置 ...
- 透明表盘 指南针 app_指南:在Web设计中使用透明度(不透明度)
透明度是一种使我们能够看到其底下的效果 . 在设计中,透明度可能会造成一个看起来比实际更宽敞的区域的错觉. 如果做得对,甚至可以使整体设计看起来更优雅. 在Photoshop中,可以通过减小不透明度或 ...
- html图层透明度,ps图层透明度怎么调整?Photoshop中调整图层透明度的三种方法介绍...
Photoshop里面怎么调整图层的透明度?作为一个"切图仔",切图的时候,看到总有透明的图层估计是最头痛的事,不知道其他人怎么样,个人却是最怕做透明的样式..扯远了,但确实因为要 ...
- IE8浏览器中图片透明度设置
在IE浏览器中自IE9之后的图片透明度的设置方法都是一致的,而且是最简便的设置方式,CSS代码如下: filter: alpha(opacity=70); 若果要兼容其他的浏览器的话,我通常的做法是直 ...
- html中透明度怎么写,css中控制透明度
CSS中如何控制层的透明度? 在CSS样式中设置背景的透明度,下面一个具体的实例.把类为box的层设为透明. .box{width:300px; height:200px; margin:0 auto ...
- PyCairo 中的变换
在 PyCairo 图形学编程教程的这个部分,我们将讨论变换. 一个 仿射变换 由 0 个或多个线性变换(旋转,放缩或切变)和平移(移位)组成.多个线性变换可以结合为以单个矩阵表示. 旋转 是将一个刚 ...
- PyCairo 中的形状和填充
PyCairo 教程的这个部分,我们创建一些基本的和更高级的形状.我们使用纯色,模式和渐变填充这些形状.渐变将在另一章中讨论. 基本形状 PyCairo 有一些基本的方法可以用来绘制简单的形状. de ...
最新文章
- http://wenku.baidu.com/view/26afdb8371fe910ef12df8ccRevit采用DWG和FBX两种格式导入3D max方法的总结...
- 踏上《软件设计精要与模式》第二版的征途
- Python 的电子邮件编程
- Linux 进程后台运行的几种方式 screen
- 报错The sandbox is not in sync with the Podfile.lock
- 特斯拉计划在2023年推出2.5万美元电动汽车,或无方向盘
- spark学习-61-源代码:ShutdownHookManager虚拟机关闭钩子管理器
- Spring mvc 中 DispatcherServlet 的学习和理解
- koa操作mongodb,封装mongdb操作方法
- [转载] python文件操作--写入文件
- jQuery 图像裁剪插件Jcrop
- 使用 vue_VUE使用ECharts教程
- CentOS中的网络管理
- 在线计算机进制换算,进制转换计算器
- 推荐 :聊天机器人开发中的机器学习(附链接)
- 苹果恢复出厂设置系统也会还原吗_刷机、恢复出厂设置和还原设置,你还不知道有什么区别?...
- android仿酷狗界面,Android仿酷狗动感歌词(支持翻译和音译歌词)显示效果
- 抓包技术(浏览器APP小程序PC应用)
- win11安装低版本CAD报致命错误解决方案
- Android之人脸识别
热门文章
- Request_继承体系
- 构造函数和实例对象之间的关系 构造函数创建对象带来的问题 原型
- 对计算机的理解大一1000,大一计算机实训报告总结范文-求计算机实习报告1000字左右,急急急?...
- html中加入一个计时器,向html中的计时器添加毫秒
- drop 很慢 物化视图_终于解决了物化视图复制的问题
- flask echarts词云可视化_基于flask框架的高校舆情分析系统
- Web应用安全--攻防对抗发展趋势
- Java Streams,第 4 部分: 从并发到并行
- 数据结构---队列C语言实现
- 2015年中国人才招聘趋势报告