随着HTML5的火热,越来越多的人投入到HTML5开发中了,canvas作为HTML5中比较重要的一个元素,在很多官网的主页面中被使用到。今天我们一起来看看如何使用canvas画出一个梦幻的星空背景,还会有流星运动。
本文的代码已经放到Github上了,感兴趣的可以自取,Github地址如下。
https://github.com/zhouxiongking/article-pages/blob/master/articles/starry/starry.html
HTML5
首先我们来看看通过canvas实现的星空效果图,如下所示。
效果图
接下来我们看看这个效果是如何通过代码一步步实现的。
首先来看看页面上的HTML代码,只有一个Div元素。
HTML代码
首先我们需要定义一些常量,比如画布的宽和高,星星数量,流星个数。在这个星空中流星其实是星星的一个,只是添加了动态效果。
页面初始化
然后是设定一个定时器,通过一段随机时间生成一个流星的索引号。
流星索引号
紧接着来看看生成一个星星的方法,该方法返回一个星星的各项参数,包括x,y轴坐标,透明度,x,y轴偏移量。
生成星星的参数
然后是最重要的render方法,通过该方法可以将星星渲染至画布上,我们将这个方法拆开看,首先是对流星的绘制,流星索引号通过上面metor方法获得。
画流星
然后是对于星星各项参数的处理,比如有的星星生成的点坐标超出了屏幕宽高,有的透明度是负数,都要将其处理成正常参数。
各项参数判断
最后是在画布中进行绘制。
画布绘制
至此,这个画面效果的讲解完毕,如果代码正确的话,就可以看到文中出现的效果图。
今天这篇文章主要是借助HTML5中的canvas画出了一个梦幻星空的效果,你学会了吗?
PConline 资讯】7月24日消息:NASA发现新地球!7月24日凌晨零时,NASA举办媒体电话会议宣布开普勒空间望远镜的最新发现——NASA发现新地球“Kepler 452b”。
NASA发现新地球
据悉,开普勒空间望远镜所发现的Kepler 452b,位于天鹅座,绕着一颗与太阳非常相似的恒星运行。那颗恒星的质量比太阳多4%,亮度高出太阳10%。Kepler-452到那颗恒星的距离跟地球到太阳的距离相同。
另外,“Kepler 452b”与地球的相似指数为0.98。Kepler 452b的直径比地球大60%,Kepler-452公转一圈是385天,地球为365天。Kepler 452b应该有60亿年历史,地球为45亿年。
Kepler 452b是迄今为止发现的最接近地球的“孪生星球”,极有可能存在大气层和流动水。
对于“NASA发现新地球”,NASA表示,由于缺乏关键数据,现在不能说Kepler 452b究竟是不是“另外一个地球”,只能说它是“迄今最接近另外一个地球”的系外行星。
尽管如此,这仍是人类认识茫茫宇宙的又一里程碑。宇宙深邃迷人,我们无法像宇航员那样直接看到眼前的宇宙美景,但却不妨碍我们将身边的智能设备化身天文观测站,欣赏茫茫星海。下面小编为大家推荐几款用来看星星的天文软件,让大家尽享璀璨的星河美景。
谷歌的地图类服务一直很赞,无论是天文地理,谷歌都有涉及而且做得相当出彩。在桌面版本的谷歌地球上谷歌已经整合了星空探索功能,受到了广大用户的好评。那么这款谷歌出品的App谷歌星空表现如何呢?我们一起来看看。
软件名称: | 谷歌星空 |
软件版本: | 1.6.4 |
软件大小: | 2.16MB |
软件授权: | 免费 |
适用平台: | Android |
下载地址: | http://dl.pconline.com.cn/download/77978.html |
打开谷歌星空,会先出现一个启动界面,这个界面有点模糊,看来并没有采用高清素材。谷歌星空最后一次更新是在2011年年底,那时候还没有什么高分辨率的机器,希望谷歌星空能够进一步改进吧。进入App后直接进会锁定你所在的地理位置,并呈现当前天空上的星辰分布,简单直接。如果你的Android设备支持电子罗盘功能的话,谷歌星空可以根据你的设备对准的方位显示相应的天体,十分有趣,但不知道是什么原因画面会有些抖动。
谷歌星空的启动界面和主界面
谷歌星空可以显示天空中的恒星、星座、天球网格等等,我们可以通过触摸屏幕呼出开关按钮来决定什么才会被显示,也可以关闭自动位移天空的功能。谷歌星空的操作方法很简单,双指张合可以控制视野大小。谷歌星空还具有其他一些功能,我们一起来看看。
触摸屏幕和点击菜单键可以呼出不同的功能
查找天体功能
一些设置选项
可查看NASA照片,也可以查看特性时间的天体运行
总的来说,谷歌星空使用起来很简单,但信息量不算大。谷歌星空为谷歌官方出品,有谷歌情结的朋友可以下载尝试。
星图是一款用以观测星空的App,在天文爱好者中有着十分不错的口碑。下面我们来试用以下星图,看看有何神通之处。
软件名称: | 星图(Star Chart) |
软件版本: | 2.3.4 |
软件大小: | 15.20MB |
软件授权: | 免费 |
适用平台: | Android |
下载地址: | http://dl.pconline.com.cn/download/91726.html |
和谷歌星空类似,星图启动之时也会先弹出一个欢迎界面,接下来就进入到星空浏览了。说实在,星图所显示的星空比谷歌星空华丽多了,宇宙更有层次感,而且银河、星座、星云等元素都处理得如梦似幻。
星图的界面童话一般,犹如银河铁道之夜
点击某个天体,星图会出现该天体的详细信息,有时候甚至还会带上图片。如果你查看的是月球或者是太阳系的行星,星图会为你提供这个星球的三维图像,转动观察该星球的视角时,宇宙背景也会相应改变,十分逼真。
可查看天体信息,甚至有相关天体的3D模型
点击菜单键可以唤出星图的功能菜单。“增强现实模式”就是和谷歌星空一样,在装载了电子罗盘的Android设备上可以随手机所对方位转动星空。夜间模式则可以模拟红外线观测。当然,改变观测地理位置、搜索星体等功能也没有拉下。我们一起来看看星图的功能吧。
使用功能按钮可打开夜间模式
可设置天空中显示何种信息,可设置地理位置
查找天体很方便
Stellarium虚拟天文馆是一款星空观测软件。虽然通过Stellarium看到的星空没有大自然中的壮丽,但是却能对星空进行更详细多角度的观测,银河、夏日大三角、流星雨等皆不在话下。下面我们一起透过Stellarium,来看看灯火掩盖下的星辰。
软件名称: | Stellarium(虚拟天文馆) |
软件版本: | 0.11.3 |
软件大小: | 56.66MB |
软件授权: | 免费 |
适用平台: | Win9X WinNT Win2000 WinXP Win2003 |
下载地址: | http://dl.pconline.com.cn/html_2/1/131/id=11187&pn=0.html |
首先安装好Stellarium,打开后可以看到主界面。此时很多人一看,大概就已经开始呼唤坑爹了吧——软件界面不仅是英文的,而且连一颗星星也看不到!不用急,先按F2或者软件界面左侧的“设定”按钮,在弹出的设置菜单中把语言调为中文。看不到星星的朋友是因为打开软件之时该地点为白天,此时只需要把软件底部“大气层”的选项关闭就可以了,或者你喜欢一直等到晚上也可以。
设置好语言
时间是白天的话关闭大气层就能看到星空了
之后,我们需要调节一下所在地点。按F6或者软件左侧的“所在地点”按钮呼出菜单,则可设置所在地点。有趣的是,观星地点可不限于地球——诸位喜欢的话也可以看看火星人眼里的夜空。
设置观测地点
在月球上看地球的感觉也不错
也可以做做火星人
接着按F4或者软件左侧的“星空及显示”按钮作一些设置。我们可以设置Stellarium显示什么星体、星体如何显示、使用黄道或者赤道坐标等等,功能十分丰富。
“星空及显示”设定
当然,我们也可以通过按F3或者软件左侧的“搜索”按钮寻找天体。
搜索不支持中文
不过只能通过拜耳命名法的希腊字母来寻找,对于一般人来说不太方便。
Stellarium不仅可以观察现时的星空,还能够洞悉过去未来天体的运行。我们只需要按F5或者点击软件左侧的“时间/日期”按钮既可设置时间,真心不需要从白天等到晚上。想回到当前时间,按“8”即可。
我们把时间设到一次流星雨的爆发夜
设置流星数量
华丽的流星雨就出现了
此外,在软件的底部可以对星空的显示进行快捷设置。可以开关坐标系、星座连线、星座标识、时间流动等等功能,十分便捷。
可以显示星座图绘,也可以通过底部按钮实现其他功能
事实上,Stellarium这款软件在天文爱好者中一直享有不错的口碑——星图准确,资料齐全,使用方便,功能强大。虽然Google Earth也能观测星空,而且拥有丰富的天文资料(来自哈勃望远镜的天文照片尤为珍贵),但使用起来却没有Stellarium那么直观,观测点也不是地表。就“看星星”这一功能而言,小编认为Stellarium更加合适。
观望太阳系(Eyes on the Solar System)
观望太阳系是由NASA的喷气推进实验室(Jet Propulsion Lab)针对Mac和PC平台发布的一款观星软件(点击下载)。通过它可以看到现场直播模拟画面——来源于新视野号。
通过软件我们可以观看直播模拟画面
虽然只是模拟,毕竟从那么远的距离要做视频直播还是不大现实的事情,但这种模拟应该可以满足很多人的好奇心。NASA在这上面发布最新的探测照片,有兴趣的同学可以下载欣赏。
键盘也能翻页,试试“← →”键
乐高蝙蝠侠攻击飞艇99
超吊炸天!微星GT80顶配
2015新款!NB 999跑鞋522
索康尼男士复古跑鞋198
可插卡迷你蓝牙音响39.9
Moto x 32GB全网通2K3
微信突然屏蔽Uber?
电视盒子都不能装App了?
揭秘六大科技谎言
神配置 MX5Pro要逆天
Win10预览版锁屏壁纸
微软Bing5月高清壁纸
唯美花朵摄影高清壁纸
《刺客信条:枭雄》
《史努比》电影壁纸
八云紫动漫壁纸桌面
超甜美校园美女壁纸
萌萌的古装少女壁纸
天给大家带来的是模板项目实战,先给大家看一下效果图
说明:
movies = [
{
'id': '34532',
'title': u'胖子行动队',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2526215398.webp',
'rating': u'7.6',
'comment_count': 39450,
'authors': u'宝贝儿 / 李成敏 Clara Lee / 文章 Zhang Wen'
},
{
'id': '394558',
'title': u'李茶的姑妈',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2533384240.webp',
'rating': u'6.3',
'comment_count': 38409,
'authors': u'钱晨光 / 吴瑾蓉 / 黄才伦'
},
{
'id': '26921827',
'title': u'找到你',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2534471408.webp',
'rating': u'4.3',
'comment_count': 682,
'authors': u'姚晨 / 马伊琍 / 袁文康'
},
{
'id': '26287884',
'title': u'悲伤逆流成河',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2529701498.webp',
'rating': u'7.5',
'comment_count': 33060,
'authors': u'赵英博 / 任敏 / 辛云来'
},
{
'id': '26287884',
'title': u'嗝嗝老师',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2535365481.webp',
'rating': u'7.5',
'comment_count': 33060,
'authors': u'拉妮·玛克赫吉 / 内拉吉·卡比 / 萨钦'
}
]
# 电视剧
tvs = [
{
'id': '235434',
'title': u'如懿传',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2460165077.jpg',
'rating': u'7.4',
'comment_count': 49328,
'authors': u'拉妮·玛克赫吉 / 内拉吉·卡比 / 萨钦'
},
{
'id': '48373095',
'title': u'奇葩说第五季',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2534020405.jpg',
'rating': u'8.4',
'comment_count': 2483,
'authors': u'伊藤沙莉 / 中川大志 / 上原实矩 / 森绘梨佳 / 樱田通 /'
},
{
'id': '27005982',
'title': u'最亲爱的你',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2508399162.jpg',
'rating': u'7.6',
'comment_count': 25532,
'authors': u'杰西·普莱蒙 / 莫莉·香侬 / 布莱德利·惠特福德 / Maude Apatow / 麦迪逊·贝蒂 /'
},
{
'id': '30290917',
'title': u'我们无法成为野兽',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2537556934.jpg',
'rating': u'3.7',
'comment_count': 8493,
'authors': u'钟汉良 / 杨颖 / 甘婷婷 / 孙艺洲 / 亓航 /'
},
{
'id': '292843',
'title': u'奇遇人生',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2533929218.jpg',
'rating': u'8.2',
'comment_count': 23456,
'authors': u'托马斯·哈登·丘奇 / 泰伦斯·霍华德 / 波伊德·霍布鲁克 / 瑞斯·维克菲尔德 / 马尔洛·托马斯 /'
}
]
我们先来完成首页的功能
大家可以先自己试着做一下,然后再看船长的代码:
先新建一个项目microPro:
app.py
# coding: utf-8
from flask import Flask
import flask
app = Flask(__name__) # type: Flask
app.debug = True
# 电影
movies = [
{
'id': '34532',
'title': u'胖子行动队',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2526215398.webp',
'rating': u'7.6',
'comment_count': 39450,
'authors': u'宝贝儿 / 李成敏 Clara Lee / 文章 Zhang Wen'
},
{
'id': '394558',
'title': u'李茶的姑妈',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2533384240.webp',
'rating': u'6.3',
'comment_count': 38409,
'authors': u'钱晨光 / 吴瑾蓉 / 黄才伦'
},
{
'id': '26921827',
'title': u'找到你',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2534471408.webp',
'rating': u'4.3',
'comment_count': 682,
'authors': u'姚晨 / 马伊琍 / 袁文康'
},
{
'id': '26287884',
'title': u'悲伤逆流成河',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2529701498.webp',
'rating': u'7.5',
'comment_count': 33060,
'authors': u'赵英博 / 任敏 / 辛云来'
},
{
'id': '26287884',
'title': u'嗝嗝老师',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2535365481.webp',
'rating': u'7.5',
'comment_count': 33060,
'authors': u'拉妮·玛克赫吉 / 内拉吉·卡比 / 萨钦'
}
]
# 电视剧
tvs = [
{
'id': '235434',
'title': u'如懿传',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2460165077.jpg',
'rating': u'7.4',
'comment_count': 49328,
'authors': u'拉妮·玛克赫吉 / 内拉吉·卡比 / 萨钦'
},
{
'id': '48373095',
'title': u'奇葩说第五季',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2534020405.jpg',
'rating': u'8.4',
'comment_count': 2483,
'authors': u'伊藤沙莉 / 中川大志 / 上原实矩 / 森绘梨佳 / 樱田通 /'
},
{
'id': '27005982',
'title': u'最亲爱的你',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2508399162.jpg',
'rating': u'7.6',
'comment_count': 25532,
'authors': u'杰西·普莱蒙 / 莫莉·香侬 / 布莱德利·惠特福德 / Maude Apatow / 麦迪逊·贝蒂 /'
},
{
'id': '30290917',
'title': u'我们无法成为野兽',
'thumbnail': u'https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2537556934.jpg',
'rating': u'3.7',
'comment_count': 8493,
'authors': u'钟汉良 / 杨颖 / 甘婷婷 / 孙艺洲 / 亓航 /'
},
{
'id': '292843',
'title': u'奇遇人生',
'thumbnail': u'https://img1.doubanio.com/view/photo/s_ratio_poster/public/p2533929218.jpg',
'rating': u'8.2',
'comment_count': 23456,
'authors': u'托马斯·哈登·丘奇 / 泰伦斯·霍华德 / 波伊德·霍布鲁克 / 瑞斯·维克菲尔德 / 马尔洛·托马斯 /'
}
]
@app.route('/')
def hello_world():
context = {
"movies": movies,
"tvs": tvs
}
return flask.render_template('index.html', **context)
if __name__ == '__main__':
app.run()
这里只需要渲染数据即可,即将**context传给模板。
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>首页</title> <style> *{ padding: 0; margin: 0; list-style: none; text-decoration: none; font-family: "Microsoft Ya Hei"; } .page{ width: 375px; height: 667px; background: #d1fcff; } .page .searich-group{ padding: 14px 8px; background: #41b357; } .page .searich-group .search-input{ {# 块级元素 #} display: block; height: 30px; width: 100%; background: #fff; {# 与盒子整体匹配 #} box-sizing: border-box; {# 搜索框不显示 #} border: none; {# 鼠标点击搜索框后不显示边框 #} outline: none; {# 边框圆角 #} border-radius: 5px; } .list-group{ background: #fff; padding: 17px 18px; } .list-group .group-top{ font-size: 18px; {# 获取浮动元素 #} overflow: hidden; } .group-top .group-title{ float: left; color: #000; } .group-top .more-btn{ float: right; } .any-group{ margin-top: 20px; overflow: hidden; } .any-group .item-group{ width: 100px; float: left; margin-right: 8px; } .item-group .thumbnail{ width: 100%; height: 140px; } .item-group .item-title{ text-align: center; margin-top: 12px; } .item-group .item-rating{ color: #acacac; text-align: center; font-size: 12px; } .item-rating img{ width: 10px; height: 10px; } </style> </head> <body> <div class="page"> {# 搜索框 #} <div class="searich-group"> <input class="search-input" type="text" placeholder="请输入查询条件"> </div> {# 电影 #} <div class="list-group"> <div class="group-top"> <span class="group-title">电影</span> <a href="#" class="more-btn">更多</a> </div> <div class="any-group"> {% for movie in movies[0:3] %} <div class="item-group"> <img src="{{ movie.thumbnail }}" class="thumbnail" alt=""> <p class="item-title">{{ movie.title }}</p> <p class="item-rating"> {# 确定整星个数 #} {% set lights = ((movie.rating|int)/2)|int %} {# 确定半个星个数 #} {% set halfs = ((movie.rating|int)%2) %} {# 灰色星星个数 #} {% set grays = 5 - lights - halfs %} {# 渲染高亮星星 #} {% for light in range(0, lights) %} <img src="{{ url_for('static', filename='img/rate_light.png') }}"> {% endfor %} {# 渲染半高亮星星 #} {% for light in range(0, halfs) %} <img src="{{ url_for('static', filename='img/rate_half.jpg') }}"> {% endfor %} {# 渲染灰色星星 #} {% for light in range(0, grays) %} <img src="{{ url_for('static', filename='img/rate_gray.png') }}"> {% endfor %} {{ movie.rating }} </p> </div> {% endfor %} </div> </div> {# 电视剧 #} <div class="list-group"> <div class="group-top"> <span class="group-title">电视剧</span> <a href="#" class="more-btn">更多</a> </div> <div class="any-group"> {% for tv in tvs[0:3] %} <div class="item-group"> <img src="{{ tv.thumbnail }}" class="thumbnail" alt=""> <p class="item-title">{{ tv.title }}</p> <p class="item-rating"> {# 确定整星个数 #} {% set lights = ((tv.rating|int)/2)|int %} {# 确定半个星个数 #} {% set halfs = ((tv.rating|int)%2) %} {# 灰色星星个数 #} {% set grays = 5 - lights - halfs %} {# 渲染高亮星星 #} {% for light in range(0, lights) %} <img src="{{ url_for('static', filename='img/rate_light.png') }}"> {% endfor %} {# 渲染半高亮星星 #} {% for light in range(0, halfs) %} <img src="{{ url_for('static', filename='img/rate_half.jpg') }}"> {% endfor %} {# 渲染灰色星星 #} {% for light in range(0, grays) %} <img src="{{ url_for('static', filename='img/rate_gray.png') }}"> {% endfor %} {{ tv.rating }} </p> </div> {% endfor %} </div> </div> </div> </body> </html>
上面代码综合了之前学过的知识,包括:flask for 循环、set模板赋值其余都是前端的内容,这里不做过多的阐述。
观察index.html中设置星星显示数量代码,我们发现在电影和电视剧两部分的代码是大体一致的,遇到重复代码就要想到优化,这里就可以用到我们学过的宏来简化上面的代码:
<div class="list-group"> <div class="group-top"> <span class="group-title">电影</span> <a href="#" class="more-btn">更多</a></div><div class="any-group"> {% for movie in movies[0:3] %} <div class="item-group"> <img src="{{ movie.thumbnail }}" class="thumbnail" alt=""> <p class="item-title">{{ movie.title }}</p> <p class="item-rating"> {# 确定整星个数 #} {% set lights = ((movie.rating|int)/2)|int %} {# 确定半个星个数 #} {% set halfs = ((movie.rating|int)%2) %} {# 灰色星星个数 #} {% set grays = 5 - lights - halfs %} {# 渲染高亮星星 #} {% for light in range(0, lights) %} <img src="{{ url_for('static', filename='img/rate_light.png') }}"> {% endfor %} {# 渲染半高亮星星 #} {% for light in range(0, halfs) %} <img src="{{ url_for('static', filename='img/rate_half.jpg') }}"> {% endfor %} {# 渲染灰色星星 #} {% for light in range(0, grays) %} <img src="{{ url_for('static', filename='img/rate_gray.png') }}"> {% endfor %} {{ movie.rating }} </p> </div> {% endfor %}</div>
将以上代码提取出来作为宏,我们发现变化的只有两个——电影/电视剧、movies/tvs,其余都一样,所以我们可以将这两个作为变量传入:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<style>
*{
padding: 0;
margin: 0;
list-style: none;
text-decoration: none;
font-family: "Microsoft Ya Hei";
}
.page{
width: 375px;
height: 667px;
background: #d1fcff;
}
.page .searich-group{
padding: 14px 8px;
background: #41b357;
}
.page .searich-group .search-input{
{# 块级元素 #}
display: block;
height: 30px;
width: 100%;
background: #fff;
{# 与盒子整体匹配 #}
box-sizing: border-box;
{# 搜索框不显示 #}
border: none;
{# 鼠标点击搜索框后不显示边框 #}
outline: none;
{# 边框圆角 #}
border-radius: 5px;
}
.list-group{
background: #fff;
padding: 17px 18px;
}
.list-group .group-top{
font-size: 18px;
{# 获取浮动元素 #}
overflow: hidden;
}
.group-top .group-title{
float: left;
color: #000;
}
.group-top .more-btn{
float: right;
}
.any-group{
margin-top: 20px;
overflow: hidden;
}
.any-group .item-group{
width: 100px;
float: left;
margin-right: 8px;
}
.item-group .thumbnail{
width: 100%;
height: 140px;
}
.item-group .item-title{
text-align: center;
margin-top: 12px;
}
.item-group .item-rating{
color: #acacac;
text-align: center;
font-size: 12px;
}
.item-rating img{
width: 10px;
height: 10px;
}
</style>
</head>
<body>
{% macro listGroup(category, items) %}
<div class="list-group">
<div class="group-top">
<span class="group-title">{{ category }}</span>
<a href="#" class="more-btn">更多</a>
</div>
<div class="any-group">
{% for item in items[0:3] %}
<div class="item-group">
<img src="{{ item.thumbnail }}" class="thumbnail" alt="">
<p class="item-title">{{ item.title }}</p>
<p class="item-rating">
{# 确定整星个数 #}
{% set lights = ((item.rating|int)/2)|int %}
{# 确定半个星个数 #}
{% set halfs = ((item.rating|int)%2) %}
{# 灰色星星个数 #}
{% set grays = 5 - lights - halfs %}
{# 渲染高亮星星 #}
{% for light in range(0, lights) %}
<img src="{{ url_for('static', filename='img/rate_light.png') }}">
{% endfor %}
{# 渲染半高亮星星 #}
{% for light in range(0, halfs) %}
<img src="{{ url_for('static', filename='img/rate_half.jpg') }}">
{% endfor %}
{# 渲染灰色星星 #}
{% for light in range(0, grays) %}
<img src="{{ url_for('static', filename='img/rate_gray.png') }}">
{% endfor %}
{{ item.rating }}
</p>
</div>
{% endfor %}
</div>
</div>
{% endmacro %}
<div class="page">
{# 搜索框 #}
<div class="searich-group">
<input class="search-input" type="text" placeholder="请输入查询条件">
</div>
{# 电影 #}
{{ listGroup('电影', movies) }}
{# 电视剧 #}
{{ listGroup('电视剧', tvs) }}
</div>
</body>
</html>
上面我们利用宏将首页代码进行了第一次优化。如果我们现在还有其他页面,试想一下,首页上面的搜索框
以及页面背景
是否可以提取为公用的,其他页面在应用到的时候通过继承来实现呢?答案是肯定的。
所以我们现在新建base.html文件,并且将页面布局代码,提出,再想一下,既然名为公用也就意味着其他代码也可以继承这个base.html,那么页面内容:
这部分代码是不是就不可以再在base.html里了【答:是】,但是我们又要往base.html这里面插入上图部分代码,那要用什么呀?block对吧。此外,按照习惯,我们同样将样式style以文件的形式提取出来,此时头部搜索样式与内容部分样式肯定是不能提取在一个文件里的,因为在一个文件里每次都会加载所有的代码,这样在head中就没必要加载内容的样式,所以我们把样式分别提取成css文件,一个是搜索栏和页面背景,命名为base.css:
*{ padding: 0; margin: 0; list-style: none; text-decoration: none; font-family: "Microsoft Ya Hei";}.page{ width: 375px; height: 667px; background: #d1fcff;}.page .searich-group{ padding: 14px 8px; background: #41b357;}.page .searich-group .search-input{ /* {# 块级元素 #} */
display: block; height: 30px; width: 100%; background: #fff; /* {# 与盒子整体匹配 #} */
box-sizing: border-box; /* {# 搜索框不显示 #} */
border: none; /* {# 鼠标点击搜索框后不显示边框 #} */
outline: none; /* {# 边框圆角 #} */
border-radius: 5px;}
另一个是页面样式,命名为index_page.css:
.list-group{ background: #fff; padding: 17px 18px;}.list-group .group-top{ font-size: 18px; /* {# 获取浮动元素 #} */
overflow: hidden;}.group-top .group-title{ float: left; color: #000;}.group-top .more-btn{ float: right;}.any-group{ margin-top: 20px; overflow: hidden;}.any-group .item-group{ width: 100px; float: left; margin-right: 8px;}.item-group .thumbnail{ width: 100%; height: 140px;}.item-group .item-title{ text-align: center; margin-top: 12px;}.item-group .item-rating{ color: #acacac; text-align: center; font-size: 12px;}.item-rating img{ width: 10px; height: 10px;}
在static文件夹下新建css文件夹,然后分别新建以上两个文件:
综上,我们最后base.html文件代码应该如下:
base.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
<link rel="stylesheet" href="{{ url_for('static', filename='css/base.css') }}">
{% block head %}{% endblock %}
</head>
<body>
<div class="page">
{# 搜索框 #}
<div class="searich-group">
<input class="search-input" type="text" placeholder="请输入查询条件">
</div>
{% block content %}{% endblock %}
</div>
</body>
</html>
其中block head填充的是内容部分的样式代码。现在公用部分已经提取好,回到index.html,我们发现要做的工作只需要
1.继承`base.html`
2\. 填充`block`
即可。
index.html
{% extends 'base.html' %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/index_page.css') }}">
{% endblock %}
{% block content %}
{% macro listGroup(category, items) %}
<div class="list-group">
<div class="group-top">
<span class="group-title">{{ category }}</span>
<a href="#" class="more-btn">更多</a>
</div>
<div class="any-group">
{% for item in items[0:3] %}
<div class="item-group">
<img src="{{ item.thumbnail }}" class="thumbnail" alt="">
<p class="item-title">{{ item.title }}</p>
<p class="item-rating">
{# 确定整星个数 #}
{% set lights = ((item.rating|int)/2)|int %}
{# 确定半个星个数 #}
{% set halfs = ((item.rating|int)%2) %}
{# 灰色星星个数 #}
{% set grays = 5 - lights - halfs %}
{# 渲染高亮星星 #}
{% for light in range(0, lights) %}
<img src="{{ url_for('static', filename='img/rate_light.png') }}">
{% endfor %}
{# 渲染半高亮星星 #}
{% for light in range(0, halfs) %}
<img src="{{ url_for('static', filename='img/rate_half.jpg') }}">
{% endfor %}
{# 渲染灰色星星 #}
{% for light in range(0, grays) %}
<img src="{{ url_for('static', filename='img/rate_gray.png') }}">
{% endfor %}
{{ item.rating }}
</p>
</div>
{% endfor %}
</div>
</div>
{% endmacro %}
{# 电影 #}
{{ listGroup('电影', movies) }}
{# 电视剧 #}
{{ listGroup('电视剧', tvs) }}
{% endblock %}
执行文件,页面显示不变。
接着我们来完成更多的模块,点击更多后页面显示效果如上图。
我们先来分析上面这个页面,我们发现除了搜索栏下面的图片区域有些变化以外,其余都是base.html的布局,所以我们首先想到可以继承base.html,而图片显示规则则和我们前面定义过的宏完全一致,我们就可以导入写好的宏。所以我们先在templates文件夹下新建moreList.html文件:
我们已经在base.html中保留了block,所以页面新的布局只需要通过block进行插入即可:
moreList.html
{% extends 'base.html' %}
{% from 'macros/macros.html' import itemGroup %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/item.css') }}">
<style>
.content{
padding: 25px 10px;
}
</style>
{% endblock %}
{% block content %}
<div class="content">
{% for item in items %}
{{ itemGroup(item) }}
{% endfor %}
</div>
{% endblock %}
当然,我们还要将更多加上链接,我们先定义函数:
@app.route('/list/<int:category>/')def itemList(category):
# 如果category等于1:返回电影
# 如果category等于2:返回电视剧
# 否则返回空数组
items = [] if category == 1:
items = movies elif category == 2:
items = tvs else:
items = [] return flask.render_template('moreList.html', items=items)
这里我们新加了一个整型的category参数,方便我们对进入的页面到底是电影还是电视剧进行分辨,在macros.html文件中需要加上更多的链接:
<a href="{{ url_for('itemList', category=category) }}" class="more-btn">更多</a>
这样就会完成点击更多后的页面跳转和跳转后的页面布局了。以上就是一个完整的一个项目实战实操。
如果对接口、性能、自动化测试、面试经验交流等感兴趣的,可以关注我的头条号,我会不定期的发放免费的资料,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家。欢迎分享,欢迎评论,欢迎转发。需要资料的同学可以关注小编+转发文章+私信【测试资料】
*请认真填写需求信息,我们会在24小时内与您取得联系。