2

谁说后端不能画出美丽的动图?让我来给大家拜个年!

 5 months ago
source link: https://www.cnblogs.com/guoxiaoyu/p/17991503
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

今天我们要介绍的是Python的内置库——小海龟(turtle),它是一个非常实用的绘画工具,不仅可以帮助我们绘制图形,还能让我们查看整个绘画过程。即使对绘画一窍不通的人也能够使用它来创作出生动、形象的gif动图。现在正是龙年即将到来,距离过年也只有几天的时间了。因此,我今天的主要目的就是使用小海龟这个工具,画一副我心目中的拜年gif,提前向大家拜个早年!

turtle

我也可以简单地介绍一下turtle这个工具库。简而言之,turtle允许我们通过控制一个小海龟来绘制图形。这只海龟的起点坐标为(0,0),根据我们的指令,它可以按照我们给出的方向进行移动,并在移动过程中留下轨迹。最后,海龟会将轨迹显示出来,从而形成我们想要的图形。坐标的显示方式是按照严格的四象限来划分的。

image

当然,你有能力通过调整小海龟的速度来控制绘画的速度。默认情况下,小海龟的速度设置为最快的0,最慢的是1。你可以通过增加速度设置的数值来加快绘画的速度,数值越接近10,绘画速度就会越快。当速度设置超过10时,小海龟将会以0的速度进行绘画。

另外,值得一提的是,使用这个小海龟工具时,你可以随时将它重置到初始位置。此外,你还可以自由控制小海龟是否与绘图区域接触。换句话说,如果你不希望小海龟留下路径,可以将它抬起,就像我们使用中性笔时抬起笔尖一样。除此之外,其他方面没有什么特别需要强调的了。

确实,使用这个小海龟工具进行绘图确实需要花费一些精力。你需要逐步修改坐标、选择颜色、改变方向等等。这整个过程的难度甚至比前端开发还要高。。

首先,我认为每逢过年,福字是必不可少的元素。因此,在我的绘图中,福字是一个至关重要的元素,所以我首先会画一个福字,然后再进行其他绘图内容。

相关api

turtle.bgcolor:设置背景颜色。主要是先练习,你自己选择一个好看的颜色就行。

turtle.color:同时设置画笔和填充颜色

turtle.speed:控制小海龟的速度

turtle.penup:抬笔的动作,这样的话,你再怎么动小海龟也不会有轨迹出现

turtle.pendown:放笔的动作,再动就要出现轨迹了

turtle.home:直接回到原点

turtle.forward:让小海龟换方向

turtle.write:简单的开始写字,当然了,如果你不用这个api的话,按照你的提示轨迹,可以一笔一划的写出来一个字,这个api不会一笔一划,就是简单的把你想要的字放上去而已。

done:全部完成。不写这个api的话,做完图后,整个窗口会自动关闭。

让我们先来欣赏一下我所创作的效果图吧。

image

我很乐意与大家分享我所创作的效果图,并附上源码,供大家参考和学习。请看下方源码:

import turtle              # 导入turtle库(模块)
turtle.bgcolor("#ffffff")  # 设置背景颜色为
turtle.speed(7)
# turtle.speed(10)        # 可减慢画正方形和写字的速度

### ②画灰色阴影
turtle.color("#404040")   # 同时设置画笔和填充颜色都为#404040,一种深灰色。
a=100                     # 正方形内等腰直角三角形的直角边为a
b=2**0.5*a                # 斜边为b ,等腰直角三角形的斜边=√2倍的直角边

turtle.penup()
turtle.goto(-210,180)             # 步骤1光束画完后,让海龟返回原点,即海龟移动至坐标(0,0),并设置朝向为初始方向(向右)。
turtle.forward(a)
turtle.pendown()

turtle.begin_fill()
turtle.left(135)
turtle.forward(b)
turtle.left(90)
turtle.forward(b)
turtle.left(90)
turtle.forward(b)
turtle.left(90)
turtle.forward(b)
turtle.end_fill()

### ③ 画正方形红纸
turtle.color("#ea182a")   # 同时设置画笔和填充颜色都为#ea182a,一种红色。
a=100
b=2**0.5*a

turtle.penup()
turtle.home()     # 第2步灰色阴影画完后,让海龟返回原点,即海龟移动至坐标(0,0),并设置朝向为初始方向(向右)。
turtle.goto(-205,180)
turtle.forward(a)
turtle.pendown()

turtle.begin_fill()
turtle.left(135)
turtle.forward(b)
turtle.left(90)
turtle.forward(b)
turtle.left(90)
turtle.forward(b)
turtle.left(90)
turtle.forward(b)
turtle.end_fill()

### ④ 写文字“福”
turtle.color("black")
turtle.penup()
turtle.goto(-210,175)            # 让海龟返回原点
turtle.setheading(-90)   # 让海龟头部朝下
turtle.forward(50)      # 让海龟向下移动150个像素。这个数字需要不断调试。
turtle.pendown()
turtle.write("福", align="center",font=("黑体",90,"bold"))

### 海龟绘图结束,隐藏海龟
turtle.hideturtle()
turtle.done()

在这个喜庆的新年时刻,作为作者我承认自己的语文水平有限,并不擅长写春联。不过,我想简单地为大家奉上一首诗作《元日》,以表达我的祝福。希望大家喜欢,祝愿大家新年快乐!

涉及api

turtle.pensize:就是我们要使用多大号的笔。越大线条越粗。

turtle.shape:显示一下小海龟的形状

turtle.hideturtle:隐藏小海龟的形状,因为作画的时候 ,默认时显示小海龟的,如果你不想看见他直接隐藏即可。

首先,让我们一起观看一下我所准备的效果图吧。在此我想强调一点,效果图中的小箭头是由于生成gif时产生的,实际效果并没有这些箭头存在。

image

同样源码附上,给大家一个参考:

# 海龟写古诗《元日》
### 程序初始化设置
import turtle
turtle.bgcolor("#b1352b")     # 设置背景颜色为#b1352b,一种红色。ffffff为白色
turtle.speed(0)               # 设置海龟绘图的速度,参数为0时最快
turtle.pensize(1)             # 设置画笔粗细,即竖线的粗线为1
turtle.pencolor("#f2ea99")    # 设置画笔颜色,即竖线和书法的颜色为#f2ea99,一种黄色。000000为黑色

fontname="黑体"                # 字体名称
fontsize=35                   # 字体大小
column1="爆竹声中一岁除"        # column是列的英文单词
column2="春风送暖入屠苏"
column3="千门万户曈曈日"
column4="总把新桃换旧符"
column5="宋王安石元日"
column6="努力的小雨书"
colwidth=100                  # 设置列宽colwidth

### ① 画竖线
x=245                         # 确定第一条竖线顶端的横坐标
y=230                         # 确定第一条竖线顶端的纵坐标
for i in range(6):            # 循环6次,画6根竖线
    turtle.penup()            # 海龟抬笔,没有移动(绘画)痕迹
    turtle.goto(x,y)          # 海龟移动至坐标(x,y)
    turtle.pendown()          # 海龟落笔,移动(绘画)有痕迹
    turtle.setheading(-90)    # 让海龟的头部朝下
    turtle.forward(460)       # 让海龟前进460个像素,即竖线的长度是460像素
    x=x-colwidth              # 将横坐标重新赋值为原横坐标减去列宽colwidth

### ② 海龟写诗《元日》
turtle.speed(5)               # 重新设置海龟写字的速度
# 写第1列
x=200                         # 设置第1列文字第1个字的横坐标
y=160                         # 设置第1列文字第1个字的纵坐标
for i in range(7):            # 第1列共显示7个字,所以循环7次
    turtle.penup()            # 海龟抬笔,没有移动(绘画)痕迹
    turtle.goto(x,y)          # 海龟移动至坐标(x,y)
    turtle.pendown()          # 海龟落笔,移动(绘画)有痕迹
    turtle.write(column1[i], align="center",font=(fontname,fontsize,"normal"))
    y=y-60                    # 每个字间隔60个像素

# 写第2列
x=x-colwidth
y=160
for i in range(7):             # 第2列共显示7个字,所以循环7次
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()
    turtle.write(column2[i], align="center",font=(fontname,fontsize))  #第3个参数省略时默认为"normal"
    y=y-60

# 写第3列
x=x-colwidth
y=160
for i in range(7):
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()
    turtle.write(column3[i], align="center",font=(fontname,fontsize))
    y=y-60

# 写第4列
x=x-colwidth
y=160
for i in range(7):
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()
    turtle.write(column4[i], align="center",font=(fontname,fontsize))
    y=y-60

### ③ 写落款
# 写第5列
x=x-80                       # 设置第5列第一个字的横坐标位置
y=100                        # 设置第5列第一个字的纵坐标位置
for i in range(6):           # 第5列共显示6个字,所以循环6次
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()
    turtle.write(column5[i], align="center",font=(fontname,20,))
    y=y-30                   # 落款每个字的间隔是30。字小间隔也要小

# 写第6列
x=x-40
y=100
for i in range(6):           # 第6列共显示9个字,所以循环9次
    turtle.penup()
    turtle.goto(x,y)
    turtle.pendown()
    turtle.write(column6[i], align="center",font=(fontname,20))
    y=y-30

turtle.penup()
turtle.forward(10)
turtle.pendown()
turtle.setheading(0)         # 让海龟的头部朝右
turtle.color("#e1f4d6")      # 设置海龟显示的颜色
turtle.shape("classic")       # 设置海龟显示的形状

# 海龟写完水印文字后,返回原点
turtle.penup()    
turtle.home()              
turtle.pendown()
turtle.done()

在过年期间,若是不放烟花,咋都说不过去。然而,单独谈论烟花确实很难创作,因为它是一种行动,与福字和诗歌不同。烟花必须要有动势,也不能忽略烟花自身需要逐渐消失的特点。这其中存在着许多难题,因为一旦消失了,我之前写的诗句和文字都会消失,就白费功夫了。

一顿搜索下才查找到了回滚这么一个动作。但是回滚这个动作不能让人看见啊,一个烟花放完了总不能自己还能再缩回去啊,所以又继续查,发现了类似于快进这样一个功能,让你看不见中间的流程直接输出结果。

终于,我期盼已久的烟火终于来临。然而,我不愿让它自行燃放,我想亲自参与其中,为大家拜个早年。因此,我决定将烟花的燃放变得更有趣,设计成只有在点击鼠标后才能绽放。

设计api

turtle.tracer:是否显示轨迹

turtle.getscreen():获取整个屏幕,因为我们要鼠标的点击事件。

turtle.undo():这个就是做回滚操作的,但是如果你不想看见动作,你需要和下一个api连用。

turtle.tracer:这个方法里面有一个delay,可以在几毫秒中跳过多少个步骤。这个需要你计算。

src.onclick(follow):发送点击事件,注意这个follow函数自动传入两个参数也就是x,y两个坐标值。

让我们先来欣赏一下效果图吧。尽管它的外观可能不是非常出色,但总体而言,我对它还是比较满意的。

image

同样的源码附上,给大家一个参考:

import turtle
import time
import random
from turtle import *

colors = ['red', 'blue', 'yellow', 'white',
            'green', 'orange', 'purple', 'seagreen',
            'indigo', 'cornflowerblue']

turtle.tracer(False)
turtle.ht()
src = turtle.getscreen() 

def draw_firework(count, dis, ang):
    for c in range(count):
        forward(dis)
        left(ang)        
        
def follow(startx,starty):
    need_list = [] 
    ccol = random.choice(colors)
    dist = random.randint(50, 80)
    if dist <= 60:
        angle = 171
    else:
        angle = random.choice([174, 175, 176])
    add = (dist - 30) / 10
    count = int(360 / (180 - angle))
    need_list.append([startx, starty, ccol, dist, angle, add, count])
    draw(need_list)

def draw(lis):
    pensize(2)
    for t in range(5):
        for li in lis:
            x, y, col, dis, ang, add, count = li
            penup(), goto(x - t * add / 2, y), pendown()
            color('#b1352b', col)
            begin_fill()
            setheading(0)
            draw_firework(count, t * add + 30, ang)
            end_fill()
        update()
        time.sleep(0.015)
        print('tracer-',tracer())
        print('count-',count)
        turtle.tracer(count*2+8,1)
        for i in range(count*2+8):
            undo()
    turtle.ht() 
    pensize(5)
    for t in range(10):
        for li in lis:
            x, y, col, dis, ang, add, count = li
            count = int(count / 4)
            penup(), goto(x - add * 5 + 10, y), pendown()
            setheading(-90)
            stara = dis / 2 - 10
            penup(), left(90), backward(2 * t), right(90)
            for i in range(count):
                penup()
                pencolor(col)
                circle(stara + t * 2, 360 / count - 1)
                pendown()
                circle(stara + t * 2, 1)
        update()
        time.sleep(0.03)
        # clear()
        turtle.tracer(count*4,1)
        for i in range(count*4):
            undo()

turtle.ht()
src.onclick(follow)
turtle.done()

所有的元素都已经完成,剩下的只需拼装在一起。我觉得这里的背景显得过于单一,所以我决定直接使用一张图作为背景。当然,如果你有时间,完全可以自己单独制作一张背景图。不多说了,祝福大家龙年快乐!愿你们的生活像龙一样充满力量和勇气,愿你们在新的一年里,追逐梦想,勇往直前,不断超越自我。愿你们的家庭幸福美满,团圆和谐。愿你们的事业蒸蒸日上,财源广进。愿你们的身体健康强壮,心灵充实。让我们一起庆祝龙年,共同创造美好的未来!

image

最近帕鲁很火,博主也找了一下简单教程,有兴趣的小伙伴可以看一下:【10秒开服】幻兽帕鲁全自动部署教程,难道你还想手动搭建游戏服务器吗?快来学习这个简单又快速的方法!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK