先上两张效果图
基本结构
综上所述,文本效果的特点是每个文本独立运动,遵循相同的运动规律,但每个文本之间保持固定的时间差。
每个字符的移动可以分为三个部分,字体大小的变化,文字位置的变化,文字颜色(透明度)的变化。
# 把每个文字与它的三个运动结合为一个基本单位
def newTextMotion(char, posFunc, sizeFunc, colorFunc):
tm={}
tm['char']=char
tm['posFunc']= posFunc
tm['sizeFunc']= sizeFunc
tm['colorFunc']= colorFunc
return tm
文字动效的展示
在任意一个时间点上,获得文字的显示效果。
# 在指定的时间,计算文字的位置、大小、颜色等
def showText(img, textMotion, time):
char= textMotion['char']
pos= textMotion['posFunc'](time)
size= textMotion['sizeFunc'](time)
color= textMotion['colorFunc'](time)
font= ImageFont.truetype(fontName, size)
draw = ImageDraw.Draw(im=img)
textSize= draw.textsize(text=char, font=font)
tx= pos[0]- textSize[0]// 2
ty= pos[1]- textSize[1]// 2
draw.text(xy=(tx, ty), text=char, fill=color, font=font)
对于一组文本,形成一个列表,得到每个时间点的显示图像为一帧
def getTextFrame(tmList, time):
textImg= Image.new('RGBA', (1280, 720))
for tm in tmList:
showText(textImg, tm, time)
return textImg
具体文字运动规律
下面我们来看看这两个特效的具体移动规律。乍一看很复杂,但分成三个动作,其实每个动作都比较简单。以此为模块,读者可以自己制作更多的文字效果。
# 文字缩小
def makeTextShrink(char, toSize, toPos, toColor, offset, dur):
def colorFunc(time):
if time< offset:
return (0,0,0,0)
if time> offset+ dur:
return toColor
return toColor[:-1] + (50+ round((time-offset)/dur*200),)
def sizeFunc(time):
if time< offset:
return toSize* 8
if time> offset+ dur:
return toSize
return toSize*8 - round((time-offset)/dur* toSize*7.5)
def posFunc(time):
if time< offset:
return (0,0)
if time> offset+ dur:
return toPos
# return (toPos[0], round((time-offset)/dur*toPos[1]))
return toPos
return newTextMotion(char, posFunc, sizeFunc, colorFunc)
# 抛物线降落(有一个回弹效果)
def makeTextParaDrop(char, toSize, toPos, toColor, offset, dur):
def colorFunc(time):
if time< offset:
return (0,0,0,0)
if time> offset+ dur:
return toColor
return toColor[:-1] + (50+ round((time-offset)/dur*200),)
def sizeFunc(time):
if time< offset:
return toSize
if time> offset+ dur:
return toSize
return toSize
def posFunc(time):
if time< offset:
return (toPos[0], 0)
if time> offset+ dur:
return toPos
r= 0.75
dur2= dur
a= toPos[1]/(dur2* dur2* (1- 2* r))
b= -2* a* dur2* r
x= (time-offset)
return (toPos[0], round(a* x* x+ b*x))
# print(toPos)
return newTextMotion(char, posFunc, sizeFunc, colorFunc)
整体设置与运行
对于一行文字,给每一行加上特效,依次给一个延迟。
# 一行文字,给定所有参数,配置运动函数与延时
def getMotionList(text, fontSize, fontColor, startPos, fromTime, dur, func):
tmList=[]
inter= round(dur/ len(text))
for i in range(len(text)):
char= text[i]
pos= (startPos[0]+ i* fontSize+ 10, startPos[1])
color= fontColor
# tm= makeTextDropMotion(char, fontSize, pos, color, 150*i)
tm= func(char, fontSize, pos, color, fromTime+inter*i, dur)
tmList.append(tm)
return tmList
这里可以传入不同的文字效果函数作为参数,具有更好的扩展性。
最后还有一个使用imageio制作gif图片的显示功能。这里注意两点。首先是显示时间应该是单字移动时间的两倍。为了保证运动,当第一个文本到位时,最后一个文本正好开始,所以时间是关系的两倍。
二是制作GIF的延迟应该和计算中使用的延迟一样,都是50毫秒(20fps)。
def showTextDrop(text, startPos, func):
fontSize= 50
color=(255, 255, 0, 255)
tmList= getMotionList(text, fontSize, color, startPos, 0, 1000, func)
frames=[]
outfilename='temp.gif'
for i in range(0, 2000, 50):
print(i)
img= Image.new('RGB', (640, 360))
# img= Image.open('back.png').resize((640, 360), Image.ANTIALIAS)
# img = img.convert("RGB")
textImg= getTextFrame(tmList, i)
r, g, b, a= textImg.split()
img.paste(textImg, (0,0), mask= a)
str1= 'tempAA.png'
img.save(str1)
im = imageio.imread(str1)
frames.append(im)
imageio.mimsave(outfilename, frames, 'GIF', duration=0.05)
if __name__=='__main__':
# showTextDrop('淡妆浓抹总相宜', (150,200), makeTextParaDrop)
showTextDrop('淡妆浓抹总相宜', (150,200), makeTextDropMotion)
本文为原创文章,版权归知行编程网所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 什么是 collections.Counter 在 python 中?12/30
- ♥ 如何在python中将系列转换为列表?08/25
- ♥ 100 个 Python 学习模块,从新手到高级11/17
- ♥ python3安装后如何启动11/05
- ♥ 你知道 Python 中的树吗?12/09
- ♥ python中的ide在哪里09/25
内容反馈