仿写抖音旋转汉字时钟

一直对抖音上的各种人脸处理算法很感兴趣,个别的我觉得目前的水平我能写个简单的实现方式,但是涉及复杂的,还是太菜了。但是之前在抖音上看到了一个用网页写的旋转汉字时钟的视频,感觉很好玩,而且我觉着写出来完全没问题,就用Pygame 和之前实现的旋转立方体的底层代码实现了一下。原视频地址找不到了,只有个模糊的印象,所以就跟着感觉走了。最终实现的东西,需要运算量较大,而且速度很慢。所以我若是有时间了,我会移植为C或者C++语言再看看。因为我的代码都是由之前的C语言改来的,所以改回去不会很难,只有麻烦不麻烦。

另外,本文及实现的内容纯粹是为了好玩而完全自己编写的,且原视频中介绍的是用其他代码实现的,而且我也没有记录原作者是谁,无法进行感谢。但不论怎样,若是有侵权的地方望告知,会立刻进行处理。

先上图:

也能调整大小(非动态),只要修改文件中的一个全局变量就可以修改大小了:

上一篇的 pygame实现旋转立方体 里面已经实现了点阵字库的读取和显示,当时只是写了个单个字符的,现在拓展一下,支持多个字符的就可以了。因为主要用到中文字符,也就没添加英文字符的支持。其实很简单,原理相通的。

多字符的实现无非就是计算多字符对应点阵的坐标,然后进行投影计算就可以了。

然后根据圆的坐标方程得出圆上某点与角度的关系,可以得到此角度下字符应该显示在什么位置,然后将旋转后的字符在此位置显示,就好了。

当知道圆的半径和某点的角度值后,就能得到坐标关系式,如下:

   已知 圆心:(x0,y0)      半径:r   角度:a0    求圆上任意一点坐标:(x1,y1),可得公式如下:

          x1=x0+r*cos(a0 * 3.14/180)
          y1=y0+r*sin(a0 * 3.14/180)

     然后将字符串沿Z轴旋转(当前角度a0 减去 90度)的度数就能够将字符旋转到a0的角度,符合当前角度。选择适当的半径,就能够将字符调整到合适的位置,然后输出显示就可以了。

中文字符串16x16点阵的显示:在Transform3D.py 文件中

 1 def Show3D16x16Char(font,ax,ay,az,x,y,Z_Size,frontcolor,backcolor,model=1.5,fontmultiple=1.0):
 2     ‘‘‘**********************************************************/
 3     |**函数: Show3D16x16Font
 4     |**功能:显示3D的16x16字符,为从汉字库读取的字符数据,支持数千个汉字
 5     |        本函数需要 binascii  库的支持,不支持此库的环境无法运行本函数
 6     |**说明:font:欲显示的汉字,目前只支持一个字符的显示,只支持汉字的显示
 7     |        sx,sy,sz :角度值
 8     |        x,y: 欲显示的坐标位置
 9     |        Z_Size:距旋转轴的距离
10     |        frontcolor,backcolor:颜色,前景色和背景色
11     |        model:显示模式,只有模式为1时才填充背景色,否则只填充前景色
12     |
13     |**作者: wcc  执念执战
14     |**时间:2019-6-3
15     |********************************************************‘‘‘
16     length = len(font)
17     if length == 0:#字符数要大于一个
18         return
19     if length == 1: #只支持一个字符的显示
20         text = font
21     else:
22         text = font[0]
23
24
25
26     m=0
27     i=0
28     k=0
29     j=0
30     XO=0
31     YO=0
32     #fontmultiple=1.0 #放大倍数,放到外面统一调整
33
34
35     gMAT=[[0.0 for i in range(4)]  for n in range(4)]
36     Point0=zuobiaostruct()
37     Point1=zuobiaostruct()
38     PointDis=zuobiaostruct()
39
40     gMAT=structure_3D()                        #//构建单位矩阵
41     gMAT=Translate3D(gMAT,-8,-8,-8);         #//平移变换矩阵
42     gMAT=Scale_3D(gMAT,fontmultiple,fontmultiple,fontmultiple);                #//比例变换矩阵
43     gMAT=Rotate_3D(gMAT,ax,ay,az);            #//旋转变换矩阵
44
45     for m in range(length): #理论上就是将单个的字符延长为多个字符,最重要的就是坐标的确定和计算
46
47         text=font[m]
48         gb2312 = text.encode(‘gb2312‘)
49         hex_str = binascii.b2a_hex(gb2312)
50         result = str(hex_str,encoding = ‘utf-8‘ )  #换算出汉字对应的字符地址
51         if eval(‘0x‘ + result[:2]) <128:
52             print("请输入中文")  #目前只支持gb2312中文字符,英文字符没加。原理一样,可以取模保存起来
53             return
54         else:
55
56             area = eval(‘0x‘ + result[:2]) - 0xA0
57             index = eval(‘0x‘ + result[2:]) - 0xA0 #换算为16进制地址
58             offset = (94 * (area - 1)+ (index - 1))*32  #得出具体地址
59             font_rect = None
60             with open("D:/Mystudy/Python/pyGame/HZK16","rb") as f: #16x16字符集的地址,从中读取出一个字符的点阵数据
61                 f.seek(offset)
62                 font_rect = f.read(32)#得到32个点阵数据
63             f.close()
64
65
66         #gMAT=Translate3D(gMAT,8,8,8);             #//平移变换矩阵       x:调节距离中心点的位置,相当于下面Point0.z
67
68
69
70         for i in range(16):
71             for k in range(8):
72                 temp = 0x01 << k
73                 for j in range(2):
74                     data=font_rect[i*2+j]  #取出数据
75                     if data & temp == temp:
76
77                         Point0.x=16-(k+(1-j)*8)+m*16+m*2 #第m个字符的当前点的坐标
78                         ‘‘‘
79                             每个字符16个像素,第m个字符共m*16个像素,每两个字符间的间距设为2,则m*16+m*2,前面的时实现当前点阵坐标的计算
80                         ‘‘‘
81                         Point0.y=i #(i*8)+k
82                         Point0.z=Z_Size        #//此参数能够改变字符距离旋转轴中心的距离
83
84                         Point1=vector_matrix_MULTIPLY(Point0,gMAT)#//矢量与矩阵相乘
85                         PointDis=PerProject(Point1,XO,YO)       #//映射投影
86                         Gui_Point(PointDis.x+x,PointDis.y+y,frontcolor)
87                     else:
88                         if model ==1: #模式为1 时才会绘制底色
89                             Point0.x=16-(k+(1-j)*8)+m*16+m*2
90                             Point0.y=i #(i*8)+k
91                             Point0.z=Z_Size        #//此参数能够改变字符距离旋转轴中心的距离
92
93                             Point1=vector_matrix_MULTIPLY(Point0,gMAT)#//矢量与矩阵相乘
94                             PointDis=PerProject(Point1,XO,YO)       #//映射投影
95                             Gui_Point(PointDis.x+x,PointDis.y+y,backcolor)
96      

下面是实现旋转时钟的代码:

  1 # -*- coding: utf-8 -*-
  2 """
  3 Created on Sat Jun 29 15:22:12 2019
  4
  5 @author: Administrator
  6 """
  7
  8 from Transform3D import *
  9
 10
 11 import pygame
 12 import time
 13 import math
 14
 15 fontmultiple=0.8   #字符倍数比例函数,修改次数据可以实现整体的放大和缩小,建议此数值在0.8-1.3 之间,看起来比较合适
 16
 17 SCREEN_X_MAX = int(800*fontmultiple) #屏幕的宽和高
 18 SCREEN_Y_MAX = int(800*fontmultiple)
 19
 20 BLACK=(0,0,0)
 21 WHITE=(255,255,255)
 22 RED=(255,0,0)
 23 GREEN=(0,255,0)
 24 BLUE=(0,0,255)
 25
 26 ForeColor = RED #前景色和背景色
 27 BackColor = BLACK
 28
 29
 30 pygame.init()
 31 screen = pygame.display.set_mode((SCREEN_X_MAX,SCREEN_Y_MAX))
 32
 33
 34 #myfont=pygame.font.Font(None,1)
 35 #textImage=myfont.render("test",True,WHITE)
 36
 37 Week_zw=("一","二","三","四","五","六","日") #周的中文
 38 Day_zw=("零","一","二","三","四","五","六","七","八","九","十") #可用于所有需要0-10的中文的地方
 39 Mouth_day=[31,28,31,30,31,30,31,31,30,31,30,31] #月份时长表
 40
 41
 42
 43 ‘‘‘
 44 圆: (x-a)^2+(y-b)^2=r^2
 45     a,b:圆心坐标
 46     r:半径
 47
 48     圆心:(x0,y0)
 49     半径:r
 50     角度:a0
 51     圆上任意一点:(x1,y1)
 52     x1=x0+r*cos(a0 * 3.14/180)
 53     y1=y0+r*sin(a0 * 3.14/180)
 54 ‘‘‘
 55 def Show_Year(x0,y0,r,angel):
 56     ‘‘‘
 57     显示年
 58     ‘‘‘
 59
 60     timenow=time.localtime(time.time())
 61     yearstr=Day_zw[(int)(timenow[0]/1000)]+Day_zw[int((timenow[0]%1000)/100)]+Day_zw[int((timenow[0]%100)/10)]+Day_zw[int((timenow[0]%10))]+"年"
 62     Show3D16x16Char(yearstr,0,0,angel-90,x0,y0,1,ForeColor,BackColor,0,fontmultiple)
 63 def Show_Week(x0,y0,r,agl):
 64     ‘‘‘
 65     显示周
 66     ‘‘‘
 67     timenow=time.localtime(time.time()) #获取时间
 68     for i in range(7):
 69         angel=360/7
 70
 71         if i < timenow[6]:
 72             angel=agl-angel*(timenow[6]-i)
 73             ForeColor=RED
 74         elif i >timenow[6]:
 75             angel=agl+angel*(i-timenow[6])
 76             ForeColor=RED
 77         else :
 78             angel=agl  #当前周设为90度,即在水平方向上
 79             ForeColor=WHITE
 80
 81         x1=x0 + r * math.sin(angel * 3.14/180) #由角度计算出当前应在的坐标点
 82         y1=y0 + r * math.cos(angel * 3.14/180)
 83         Show3D16x16Char("周"+Week_zw[i],0,0,angel-90,(int)(x1),(int)(y1),1,ForeColor,BackColor,0,fontmultiple)#输出旋转后的字符串
 84
 85 def Show_Month(x0,y0,r,agl):
 86     ‘‘‘
 87     显示月份
 88     ‘‘‘
 89     timenow=time.localtime(time.time())#获取时间
 90     for i in range(1,13): #一年12个月
 91         angel=360/12
 92
 93         if i < timenow[1]:
 94             angel=agl-angel*(timenow[1]-i) #其他月份相应得到角度推算
 95             ForeColor=RED
 96         elif i >timenow[1]:
 97             angel=agl+angel*(i-timenow[1])
 98             ForeColor=RED
 99         else :
100             angel=agl  #当前月份设为90度,即在水平方向上
101             ForeColor=WHITE
102         x1=x0 + r * math.sin(angel * 3.14/180) #由角度计算出当前应在的坐标点
103         y1=y0 + r * math.cos(angel * 3.14/180)
104         if i>10:
105             monthstr=Day_zw[10]+Day_zw[i%10]+"月"  #得出要显示的字符串
106         else:
107             monthstr = Day_zw[i]+"月"
108         Show3D16x16Char(monthstr,0,0,angel-90,(int)(x1),(int)(y1),1,ForeColor,BackColor,0,fontmultiple)#显示字符串
109
110 def Show_Day(x0,y0,r,agl):
111     ‘‘‘
112     显示日期
113     ‘‘‘
114     timenow=time.localtime(time.time()) #获取时间
115     if (timenow[0]%4==0 and timenow[0]%100 !=0) or (timenow[0]%400 == 0):
116         Mouth_day[1]=29 #闰年,补全二月的时长表
117     else:
118         Mouth_day[1]=28
119
120         #Mouth_day 为月份的时长表
121     for i in range(1,Mouth_day[timenow[1]-1]+1):
122         angel=360/Mouth_day[timenow[1]-1]
123
124         if i < timenow[2]:
125             angel=agl-angel*(timenow[2]-i)#其他日期相应得到角度推算
126             ForeColor=RED
127         elif i >timenow[2]:
128             angel=agl+angel*(i-timenow[2])
129             ForeColor=RED
130         else :
131             angel=agl  #当前日期设为90度,即在水平方向上
132             ForeColor=WHITE
133         x1=x0 + r * math.sin(angel * 3.14/180)#由角度计算出当前应在的坐标点
134         y1=y0 + r * math.cos(angel * 3.14/180)
135         if i>20:
136             if i%10 !=0:
137                 daystr= Day_zw[(int)(i/10) ]+ Day_zw[10] +Day_zw[i%10]+"日"#得出要显示的字符串
138             else:
139                 daystr= Day_zw[(int)(i/10) ]+ Day_zw[10]+"日"
140         elif i>10:
141             daystr= Day_zw[10]+Day_zw[i%10]+"日"
142         else:
143             daystr=Day_zw[i]+"日"
144         Show3D16x16Char(daystr,0,0,angel-90,(int)(x1),(int)(y1),1,ForeColor,BackColor,0,fontmultiple)#显示字符串
145
146
147 def Show_Hour(x0,y0,r,agl):
148     ‘‘‘
149     显示时
150     ‘‘‘
151
152     timenow=time.localtime(time.time())#获取时间
153
154     for i in range(0,24):
155         angel=360/24
156
157         if i < timenow[3]:
158             angel=agl-angel*(timenow[3]-i)#其他时间相应得到角度推算
159             ForeColor=RED
160         elif i >timenow[3]:
161             angel=agl+angel*(i-timenow[3])
162             ForeColor=RED
163         else :
164             angel=agl  #当前时间设为90度,即在水平方向上
165             ForeColor=WHITE
166         x1=x0 + r * math.sin(angel * 3.14/180)
167         y1=y0 + r * math.cos(angel * 3.14/180)
168         if i>20:
169             if i%10 !=0:
170                 daystr= Day_zw[(int)(i/10) ]+ Day_zw[10] +Day_zw[i%10]+"时"  #得到要显示的字符串
171             else:
172                 daystr= Day_zw[(int)(i/10) ]+ Day_zw[10]+"时"
173         elif i>10:
174             daystr= Day_zw[10]+Day_zw[i%10]+"时"
175         else:
176             daystr=Day_zw[i]+"时"
177         Show3D16x16Char(daystr,0,0,angel-90,(int)(x1),(int)(y1),1,ForeColor,BackColor,0,fontmultiple) #显示角度计算后的字符串
178
179 def Show_Min(x0,y0,r,agl):
180     ‘‘‘
181     显示分
182     ‘‘‘
183
184     timenow=time.localtime(time.time())
185
186     for i in range(0,60):
187         angel = 360/60
188
189         if i < timenow[4]:
190             angel=agl-angel*(timenow[4]-i)-(360/60/60 * timenow[5] ) #将秒数也代入角度计算中就可以得到更精确的角度偏移,而且每秒钟都会移动,好看
191             ForeColor=RED
192         elif i > timenow[4]:
193             angel = agl + angel * (i-timenow[4]) - (360/60/60 * timenow[5] )
194             ForeColor = RED
195         else :
196             angel = agl - (360/60/60 * timenow[5] )  #当前日期设为90度-秒钟的角度,实现动态显示
197             ForeColor = WHITE
198         x1 = x0 + r * math.sin(angel * 3.14/180) #由角度计算出当前应在的坐标点
199         y1 = y0 + r * math.cos(angel * 3.14/180)
200         if i>=20:
201             if i%10 !=0:
202                 daystr = Day_zw[(int)(i/10) ]+ Day_zw[10] +Day_zw[i%10]+"分" #得到要显示的字符串
203             else:
204                 daystr = Day_zw[(int)(i/10) ]+ Day_zw[10]+"分"
205         elif i>10:
206             daystr = Day_zw[10]+Day_zw[i%10]+"分"
207         else:
208             daystr = Day_zw[i]+"分"
209         Show3D16x16Char(daystr,0,0,angel-90,(int)(x1),(int)(y1),1,ForeColor,BackColor,0,fontmultiple)#显示角度计算后的字符串
210
211
212 i=0
213 while True:
214     for event in pygame.event.get():
215         if event.type in (QUIT,KEYDOWN):
216             pygame.quit()
217             sys.exit()
218
219     i+=1  #开始的动画,调整大小可以调整速度,因为没优化,所以显示速度很慢,数据大一些动画能尽早结束
220     if i>90:
221         i=90
222
223     Show_Year(SCREEN_X_MAX/2-40*fontmultiple,SCREEN_Y_MAX/2,32,90) #显示年
224     Show_Week(SCREEN_X_MAX/2,SCREEN_Y_MAX/2,65*fontmultiple,180-i) #显示周
225     Show_Month(SCREEN_X_MAX/2,SCREEN_Y_MAX/2,110*fontmultiple,i)    #显示月份
226     Show_Day(SCREEN_X_MAX/2,SCREEN_Y_MAX/2,170*fontmultiple,180-i)  #显示日期
227     Show_Hour(SCREEN_X_MAX/2,SCREEN_Y_MAX/2,245*fontmultiple,i)     #显示时
228     Show_Min(SCREEN_X_MAX/2,SCREEN_Y_MAX/2,325*fontmultiple,180-i)  #显示分
229
230     pygame.draw.circle(screen,ForeColor,((int)(SCREEN_X_MAX/2),(int)(SCREEN_Y_MAX/2)),int(55*fontmultiple),1) #显示几个圆
231     pygame.draw.circle(screen,ForeColor,((int)(SCREEN_X_MAX/2),(int)(SCREEN_Y_MAX/2)),int(100*fontmultiple),1)
232     pygame.draw.circle(screen,ForeColor,((int)(SCREEN_X_MAX/2),(int)(SCREEN_Y_MAX/2)),int(160*fontmultiple),1)
233     pygame.draw.circle(screen,ForeColor,((int)(SCREEN_X_MAX/2),(int)(SCREEN_Y_MAX/2)),int(235*fontmultiple),1)
234     pygame.draw.circle(screen,ForeColor,((int)(SCREEN_X_MAX/2),(int)(SCREEN_Y_MAX/2)),int(315*fontmultiple),1)
235
236     pygame.display.update()
237     screen.fill(0)  #屏幕清零
238     #time.sleep(30/1000)

其他调用的代码都在 Transform3D.py文件中,可在我的另一篇博客《python+基本3D显示》中下载,然后将上面的字符串显示代码加进去,就可以了。

本文水平有限,内容很多词语由于知识水平问题不严谨或很离谱,但主要作为记录作用,能理解就好了,希望以后的自己和路过的大神对必要的错误提出批评与指点,对可笑的错误不要嘲笑,指出来我会改正的。

另外,转载使用请注明作者和出处,不要删除文档中的关于作者的注释。

随梦,随心,随愿,恒执念,为梦执战,执战苍天!    ------------------执念执战

原文地址:https://www.cnblogs.com/zhinianzhizhan/p/11129717.html

时间: 2024-10-03 10:14:45

仿写抖音旋转汉字时钟的相关文章

仿写及比较标哥的iOS时钟动画

一.前言 以前看各种绚丽的UI特效动画代码,采用的方法是会先运行一篇,然后直接去看实现代码.初学时抱着瞻仰的态度去接触,去认识,是没有错的.但是在了解了像素.动画渲染机制,CoreAnimation API,推导过二维.三维的仿射矩阵之后,我们可以改变阅读UI动画博文或者是源码的方式了. Talk is cheap, show me the code——Linus Torvalds. 大量的仿写:一定一定要多写——叶孤城__ 在CodeReview线下大会上的发言. 最近安居客.猿题库.蘑菇街.

使用原生js仿写win10时钟

学习web前端已经一月了,突然就像做一点什么,于是就仿写了一个win10时钟(农历计算准确度太差,于是就忽略不写了~~) 一.HTML布局 1 <div class="wrap"> 2 <div class="time-present"> 3 <div class="time-local"> 4 <span id="hours">13</span><span&g

仿抖音上下滑动分页视频

目录介绍 01.先来看一下需求 02.有几种实现方式 2.1 使用ViewPager 2.2 使用RecyclerView 03.用ViewPager实现 3.1 自定义ViewPager 3.2 ViewPager和Fragment 3.3 修改滑动距离翻页 3.4 修改滑动速度 04.用RecyclerView实现 4.1 自定义LayoutManager 4.2 添加滑动监听 4.3 监听页面是否滚动 4.4 attach和Detached 05.优化点详谈 5.1 ViewPager改变

E4A写的app,点按钮,直接进入抖音指定用户界面

今天在网上看到有一个人,直接进抖音某个指定用户的界面,一般模拟的方式,要先通过搜索的方式,再选用户,点进去 但是这样操作,不大友好,也影响速度 最理想的方式,是通过 "无障碍",直接控制抖音进入指定的界面 一般要先分析抖音app的,用apkTool反编译出 AndroidManifest.xml文件 然后分析xml代码,找到相应的 intent-filter 在他的AndroidManifest.xml中应该注册了一个相应的scheme来接收参数并且跳转到用户页面的那个activity里面去 清

仿抖音上下滑动播放视频(兼容安卓,ios,小程序,h5)

仿抖音上下滑动播放视频(兼容安卓,ios,小程序,h5) 运行条件 HBuilder X 2.2.2 安装后,从插件市场导入,即可真机运行 vue 项目地址 github https://github.com/15157757001/scroll-video uniapp插件市场 https://ext.dcloud.net.cn/plugin?id=664 说明 插件分别用swiper实现(多端兼容)和css3动画实现(暂时只支持app),可自行切换. 插件在uni-app编译模式下编写(已切

iOS 仿抖音 视频裁剪

1.最近做短视频拍摄.其中的裁剪界面要做得和抖音的视频裁剪效果一样 需求:  裁剪有一个最大裁剪时间.最小裁剪时间.左右拖动可以实时查看对应的视频画面.拖动进度条也能查看对应的画面 .拖动底部视图也能查看对应视频.查看的对应视频始终是进度条对应的位置 2.设计思路 底部是一个视频播放器 SJVideoPlayView 播放器上面试一个视频裁剪视图 SJVideoCropView 里面包含一个  UICollectionView  用来加载视频缩略图 左右滑块以及进度条 拖动左右滑块.进度条.以及

抖音短视频去水印下载方法

前言 抖音短视频APP里虽然有保存视频的按钮,但这种方式保存的视频右下角有抖音的水印,并且这种方式不适用于电脑. 所以,写这篇文章来分享如何下载没有水印的抖音视频到本地,此方法适用于电脑和手机,且不需要安装任何软件和插件. 简单的下载方法 1. 去抖音APP里点开某个视频,点击分享按钮,在分享弹框中点击复制链接或通过分享到微信QQ等获取分享链接.如果是朋友分享给你的链接,直接复制那个分享链接即可. 2. 然后在浏览器(电脑和手机上都可以)中打开我们需要用到的在线抖音短视频解析下载工具:http:

世上万千变化,在你我心里,一对一视频交友+抖音短视频,才会让创业者的你一鸣惊人!

做直播的都认为社交是直播最高的境界,尤其大BOSS如腾讯.花椒.小米之类,出手瞄准的就是社交.社交虽然不赚钱,但自带吸粉光环,天生巨星气质帝王命格.不过社交这件事却也是最难的,普天之下也只有一个QQ一个微信,其他的不被斩尽杀绝也只能偏安一隅,无法与起比肩.而今出现的一对一视频交友+直播+抖音短视频瞬间吸粉无数,那么对于这一行业的创业者来说,搭建自己的直播系统,最应该知道的是什么?接下来小编就整理了详细的文档来给大家讲解.呆萌视频直播系统是什么?呆萌直播是集PC端直播.移动端直播(含iOS与And

营销圈说:抖音大火背后是什么样的一种营销模式

"南抖音,北快手",说到抖音,很多人并不陌生,准确来说是很熟悉,作为当下很火的社交软件之一,于2016年9月正式上线,短短两年时间已经占领市场,据调查报告显示,抖音目前的日活跃量过万,播放量过亿,且好评度高,当前版本评分次数平均200次,五分好评为174次,用户体验满意度是很高的,那么,它是如何做到的呢?营销圈为你讲解抖音大火背后的营销模式.一.15秒时间,攻破年轻人的心理当今社会是一个快餐式消费的时代,人们无论做什么都追求一个字"快",快意味着什么?是短,抖音的营