<> use pyton Make text effects

First two renderings

<> Basic structure

To summarize the characteristics of special effects of words , Each text moves independently , All in accordance with a law of motion , But there is a fixed time difference between each text . The movement of each word can be divided into three parts , Font size changes , Change of text position , Text color ( transparency ) Changes in .
# Combine each text with its three movements into a basic unit def newTextMotion(char, posFunc, sizeFunc, colorFunc):
tm={} tm['char']=char tm['posFunc']= posFunc tm['sizeFunc']= sizeFunc tm[
'colorFunc']= colorFunc return tm
<> Display of text dynamic effect

At any point in time , Get text display .
# at hour named , Position of calculation text , size , Color, etc 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)
For a set of text , Form a list , Get the display diagram of each time point , As a frame
def getTextFrame(tmList, time): textImg= Image.new('RGBA', (1280, 720)) for tm
in tmList: showText(textImg, tm, time) return textImg
<> Rules of specific characters movement

Let's take a look at the specific movement rules of these two special effects . At first glance, it's complicated , But after splitting into three movements , In fact, each is relatively simple . As a module , Readers can make more special effects by themselves .
# Text reduction def makeTextShrink(char, toSize, toPos, toColor, offset, dur): def
colorFunc(time): if time< offset: return (0,0,0,0) if time> offset+ dur: return
toColorreturn 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) # Parabolic descent ( Has a rebound effect ) 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
toSizeif 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)
<> Overall setup and operation

For a line of text , Add special effects for each , And give a delay in turn .
# One line of text , Given all parameters , Configure motion function and delay 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
here , Pass in different text effect functions as parameters , Good expansibility .

Finally, a demonstration function , Used imageio To make gif chart . Here are two things to watch out for , The first is that the display time should be twice as long as the single character movement time . To ensure sportiness , When the first text is in place , Last text just started , So it's twice the time .
The second is production GIF The time delay of should be consistent with the time delay for calculation , It's all here 50 millisecond (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(' Light make-up and heavy make-up are always suitable ', (150,200), makeTextParaDrop) showTextDrop(' Light make-up and heavy make-up are always suitable ', (
150,200), makeTextDropMotion)
<> Full source code

Post the complete code .
from PIL import Image, ImageDraw, ImageFont import imageio fontName= r
'.\happy1.ttf' # Combine each text with its three movements into a basic unit def newTextMotion(char, posFunc, sizeFunc
, colorFunc): tm={} tm['char']=char tm['posFunc']= posFunc tm['sizeFunc']=
sizeFunc tm['colorFunc']= colorFunc return tm # at hour named , Position of calculation text , size , Color, etc 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) # Text reduction 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
toSizereturn 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) # Parabolic descent ( Has a rebound effect ) 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
toSizeif 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 getTextFrame(tmList, time): textImg= Image.
new('RGBA', (1280, 720)) for tm in tmList: showText(textImg, tm, time) return
textImg# One line of text , Given all parameters , Configure motion function and delay 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 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) #
writeGif('temp.gif', frames, duration=0.1, subRectangles=False) # imageio.
mimsave(outfilename, frames, 'GIF', duration=0.05) # The generation method is not bad either if __name__==
'__main__': # showTextDrop(' Light make-up and heavy make-up are always suitable ', (150,200), makeTextParaDrop) showTextDrop(
' Light make-up and heavy make-up are always suitable ', (150,200), makeTextDropMotion)

Technology
©2019-2020 Toolsou All rights reserved,
python primitive -- lock Lock Output string at specified position --PTA Share has surpassed Ningde Era !LG Chemical confirmation to spin off battery business unit Bayesian decision making Linux File name validity detection PHP Printout logDijkstra Algorithmic Python realization - Shortest path problem about Bellman-Ford Personal understanding of algorithms Hack Bar 2.1.2 Press F9 No response Determine whether the current object is an array 4 Methods