122
社区成员
发帖
与我相关
我的任务
分享| 这个作业属于哪个课程 | 2302软件工程 |
|---|---|
| 这个作业要求在哪里 | 结对第二次作业——编程实现 |
| 这个作业的目标 | 采用web技术来实现原型中的功能,完成基本功能和附加功能 |
| 其他参考文献 | CSS教程、Git学习-菜鸟教程 |
| PSP | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) | 具体工作 |
|---|---|---|---|---|
| Planning | 计划 | 10 | 20 | 阅读作业要求 |
| • Estimate | • 估计这个任务需要多少时间 | 10 | 20 | 分配每个人的工作 |
| Development | 开发 | 940 | 1070 | |
| • Analysis | • 需求分析 (包括学习新技术)) | 180 | 200 | 104:1. 回顾web代码语句 2.学习echarts插件 3. 学习建立分支和git协作 202:1.学习解析json文件 |
| • Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 10 | 10 | 确定html css js的规范 |
| • Coding | • 具体编码 | 720 | 800 | 104:1.关于比赛界面,跳水动画,互动问答 2.每日赛程界面 3.二级导航,导航动画 4.奖牌地图界面 202:1.首页页面 2.选手信息页面 3.具体赛况页面 4.奖牌排名榜单页面 |
| • Code Review | • 代码复审 | 10 | 30 | 检查代码正确性 |
| • Test | • 测试 | 20 | 30 | 查看每个页面是否能正常显示 |
| Reporting | 报告 | 120 | 150 | 共同撰写博客 |
| • Size Measurement | • 计算工作量 | 30 | 20 | 复盘时间进度 |
| • Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 60 | 60 | 美化界面 |
| 合计 | 2240 | 2350 |
选手信息界面按国家首字母排名,显示所有参赛选手的姓名和出生年月日。
参考官网的赛程安排界面,点击日期可在页面内跳转到对应日期的赛程安排。
点击时间表的比赛显示本场比赛的选手排名、选手信息、落后积分等。
对跳水奖牌数量进行排名,显示奖牌总数和金银铜的数量。
关于比赛的功能是为了让用户能更好的了解本次多哈世锦赛的更多相关知识,使网站更加有趣味性。
在界面开头设置了跳水的动画,与本网站的内容相互呼应,使网站更丰富。
接下来是对FINA的一些介绍,可以点击链接到百度百科更详细的了解。
最后是一些相关知识的小互动。
三道选择题,点击提交之后在弹窗中可以看到正确的题目数量和正确答案,增加互动趣味。
扣进世锦赛的主题,添加了网页的美观性。同时增加了趣味答题小卡片,增添了网页的互动性.。
对本次世锦赛的精彩瞬间的图片轮播,可以让用户体验世锦赛的氛围。
采用地图的方式,将奖牌数量直观的显示,移动到国家可以高亮显示国家区域并显示国家名称和奖牌数量。点击左侧的数量可以看到对应国家被高亮显示。



HTML+CSS+JS
由于之前的作业已经进行过数据爬取,本次作业直接对已有的json文件进行读取。
首页实现了轮播图,把赛事的照片循环播放,每隔2s更换照片一次或者点击箭头切换。增添了网页的趣味性。
在实现选手信息的时候,由于不会js如何解析json数据而我们又只做纯前端,所以本来想一个一个手动输入 ,但选手实在是太多了!手动输是个非常不现实的事,所以上网学习了js的解析方法,用了getJSON函数,由于是一打开页面就显示数据,所以用了自启动函数function() {}();
- 通过组合块叠加的方式,将图片和文字块组合成一个赛事块,包括时间和比赛名称以及预决赛的区分。模仿官网的赛程风格。
- 再一个一个组合起来形成一列赛程。
- 添加日期栏并置顶,可以跳转到当天赛程。点击日期时,加重显示。
- 点击箭头可以查看详细赛程。
- 奖牌地图
- 通过echarts插件和世界地图的json文件实现。
- 在echarts官网中有很多基本的图表实例,本次的地图是参考“香港人口密度”的示例实现。视觉映射组件、地图和标记内容的组合。
- 奖牌排名
- 通过对图片的不同层次的组合和JavaScript的窗口监听来做成跳水的动画效果
- 通过“z-index”不同的值可以实现上下层次区分,将背景图片置于底层,再叠加跳水的运动员,顶层是水面。
- 添加事件句柄可以获取到窗口下移和上移,再返回指定元素距离顶部、左边的位置并增加值达到跳水的效果。
- 显示一些FINA的介绍
- 互动问答使用户更有参与感
- 通过列表和
input组件还有button的组合,加上js的函数调用,可以实现选择题并弹窗。- 通过for循环问题的答案来判断每道题是否选择正确。
- 弹窗提示正确的题数,是在循环中实现的。
- 最后通过变量传递给弹窗。
由于时间比较紧张,而且我们都没有做前后端分离的经历,因此选择只做纯前端。
用localStorage储存比赛名称,在每日赛程页面点击某一条比赛时,通过localStorage传递点击的比赛名称。
function fun1()
{
const param = {
name:'Women 1m SpringBoard Preliminaries'
}
const params = JSON.stringify(param); // 因为localStorage只能存字符串,所以需要转化成JSON 字符串。
localStorage.setItem('params',params);
}
在详细赛况的js代码中,用localStorage获得比赛名称,并找到对应的json文件,用自启动函数来解析数据并把数据写入table表格中
<script>
//获取由每日赛况页面点击传进来的参数:比赛名称
const param = JSON.parse(localStorage.params);
const temp=param.name;
//自启动函数,页面一加载就能看到内容
var Ajax = function () {
document.getElementById("temp").innerHTML=temp;
var url="./data/"+temp+".json";
$.getJSON(url, function (data) {
displayData(data)//传入一个函数
});
}();
var displayData= function(data){
console.log(data);
var ranktable=document.getElementById("ranktable");
var result=data['Results'];
//解析json数据
for(i = 0; i < result.length; i++)
{
var obj=result[i];
var rank=obj['Rank'];
var nation=obj['NAT'];
var fullname=obj['FullName'];
var pts=obj['TotalPoints'];
var ptsBehind=obj['PointsBehind'];
if(temp.includes("Synchronised"))
{
var competitors=obj['Competitors'];
var first=competitors[0];
var last=competitors[1];
var age=first['AthleteResultAge']+"/"+last['AthleteResultAge'];
}
else
{
var age=obj['AthleteResultAge'];
}
if(ptsBehind==null){
ptsBehind="0";
}
var tr = document.createElement("tr");
//把json数据用dom的方式加入表格
tr.innerHTML = '<tr><td>'+rank+'</td>'+'<td>'+nation+'</td>'+'<td>'+fullname+'</td>'+'<td>'+age+'</td>'+'<td>'+pts+'</td>'+'<td>'+ptsBehind+'</td></tr>';
ranktable.appendChild(tr);
}
}
</script>
用css和js实现首页轮播图效果,2s自动切换图片或者点击左箭头右箭头切换图片
window.addEventListener('load',function(){
var left = document.querySelector('.left');
var right = document.querySelector('.right');
var box = document.querySelector('.box');
box.addEventListener('mouseenter',function(){
left.style.display = 'block';
right.style.display = 'block';
})
box.addEventListener('mouseleave',function(){
left.style.display = 'none';
right.style.display = 'none';
})
var pic = document.querySelector('.pic');
var lis = document.querySelector('.lis');
var boxWidth = box.offsetWidth;
for(var i = 0;i<pic.children.length;i++){
var li = document.createElement('li');
lis.appendChild(li);
//设置索引号
li.setAttribute('index',i);
li.addEventListener('click',function(){
//获得索引号
var index = this.getAttribute('index');
num = index;
circle = index;
for(var i = 0;i<lis.children.length;i++){
lis.children[i].className = '';
}
this.className = 'selected';
animate(pic,-index*boxWidth)
})
}
lis.children[0].className = 'selected';
//克隆第一个li
var first = pic.children[0].cloneNode(true);
pic.appendChild(first);
var num = 0;
var circle = 0;
//右侧按钮的功能
right.addEventListener('click',function(){
if(num == pic.children.length-1){
pic.style.left = 0;
num = 0;
}
num++;
animate(pic,-num*boxWidth);
circle++;
if(circle == lis.children.length){
circle = 0;
}
for(var i =0;i<lis.children.length;i++){
lis.children[i].className = '';
}
lis.children[circle].className = 'selected';
})
//左侧按钮功能
left.addEventListener('click',function(){
if(num == 0){
num = pic.children.length-1;
pic.style.left = -num*boxWidth+'px';
}
num--;
animate(pic,-num*boxWidth);
circle--;
if(circle <0){
circle = lis.children.length-1;
}
for(var i =0;i<lis.children.length;i++){
lis.children[i].className = '';
}
lis.children[circle].className = 'selected';
})
var timer = this.setInterval(function(){
right.click();
},2000)
})
function animate(obj,target,callback){
clearInterval(obj.timer)
obj.timer = setInterval(function(){
var step =(target - obj.offsetLeft)/10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if(obj.offsetLeft == target){
clearInterval(obj.timer);
if(callback){
callback();
}
}
obj.style.left = obj.offsetLeft + step +'px';
},30);
}
window.onload = function () {
var box1 = document.querySelector('.box1');
var btn = document.querySelectorAll('button');
btn[0].addEventListener('click',function(){
animate(box1,400,function(){
box1.style.backgroundColor = 'pink';
});
})
btn[1].addEventListener('click',function(){
animate(box1,700,function(){
box1.style.backgroundColor = 'red';
});
})
}
- 通过对图片的不同层次的组合和JavaScript的窗口监听来做成跳水的动画效果
- 通过“z-index”不同的值可以实现上下层次区分,将背景图片置于底层,再叠加跳水的运动员,顶层是水面。
- 添加事件句柄可以获取到窗口下移和上移,再返回指定元素距离顶部、左边的位置并增加值达到跳水的效果。
<script>
var myChart = echarts.init(document.getElementById('world'));
//地图国家名字
let nameMap = {
Afghanistan: '阿富汗',
Singapore: '新加坡',
Angola: '安哥拉',
Albania: '阿尔巴尼亚',
....}
option = {
// 图表主标题
title: {
text: '奖牌地图', // 主标题文本,支持使用 \n 换行
top: 10, // 定位 值: 'top', 'middle', 'bottom' 也可以是具体的值或者百分比
left: 'center', // 值: 'left', 'center', 'right' 同上
textStyle: {
// 文本样式
fontSize: 20,
fontWeight: 600,
color: 'black'
}
},
//鼠标移动显示内容
tooltip: {
trigger: 'item',
formatter: function (params) {
console.log(params)
if (params.name) {
return params.name +'<br/>'+ '总数:'+(isNaN(params.value) ? 0 : parseInt(params.value)) ;
}
}
},
// 视觉映射组件
visualMap: {
type: 'continuous', // continuous 类型为连续型 piecewise 类型为分段型
show: true, // 是否显示 visualMap-continuous 组件 如果设置为 false,不会显示,但是数据映射的功能还存在
// 指定 visualMapContinuous 组件的允许的最小/大值。'min'/'max' 必须用户指定。
// [visualMap.min, visualMax.max] 形成了视觉映射的『定义域』
min:1,
max:13,
text: ['High', 'Low'],
// 文本样式
textStyle: {
fontSize: 14,
color: '#19191A'
},
realtime: false, // 拖拽时,是否实时更新
calculable: true, // 是否显示拖拽用的手柄
// 定义 在选中范围中 的视觉元素
inRange: {
color: ['#16417C','#20D144','#FFEC1D','#FF342F', '#FFAEC9'] // 图元的颜色
}
},
series: [
{
name: '奖牌榜',
type: 'map',
mapType: 'world',
roam: true,
itemStyle: {
areaColor: '#FAFFFF', // 地图区域的颜色 如果设置了visualMap,areaColor属性将不起作用
borderWidth: 0.4, // 描边线宽 为 0 时无描边
borderColor: '#A7ABAB', // 图形的描边颜色 支持的颜色格式同 color,不支持回调函数
borderType: 'solid', // 描边类型,默认为实线,支持 'solid', 'dashed', 'dotted'
emphasis: {
label: {
show: true}}
},
label: {
show: false // 是否显示对应地名
},
data: [... ]
};
myChart.setOption(option);
</script>
跳水动画
<script type="text/javascript">
let bg=document.getElementById("bg");
let pp=document.getElementById("pp");
let water=document.getElementById("water");
let text=document.getElementById("text");
//事件句柄获取元素位子并增加
window.addEventListener('scroll',function(){
var value=window.scrollY;
pp.style.top=value+0.15+'px';
pp.style.left=value+0.15+'px';
})
</script>
互动问答
<script>
function sendMsg(){
//弹窗
var overlay = document.getElementById("overlay");
overlay.style.display = "block";
//答对几题
var cores=0;
var qestions=document.getElementsByClassName("olCss")
//问题循环累计分数
for(var i=0;i<qestions.length;i++)
{
var answer=document.getElementsByName("answer"+(i+1));
for(var j=0;j<answer.length;j++)//判断正误
{ if(answer[j].checked)
{if(answer[j].value==1)cores++;}
}
}
document.getElementById('right').innerHTML=cores;
}
function hidePopup(){
var overlay = document.getElementById("overlay");
overlay.style.display = "none";
}
</script>
在写导航栏的过程中,我们更改了好几个版本,而每一次都需要重新复制粘贴到每一个html文件里,还经常容易漏掉复制到某个文件或者漏掉复制某行。于是我们思考如何实现代码的复用性呢,这种一个一个复制粘贴“笨办法”我相信是一定被前人改进过的。于是我阅读学长学姐们的博客最后收获到网上有一个在线html转js的网站,把导航栏转换为JavaScript文件,然后在每一个需要引用导航栏的地方引用js文件。这样就实现了只需要修改js文件即可将每个页面的导航栏同时修改。节省了很多时间。感谢学长学姐们的经验,也感谢制作在线转换的大佬。
在解析json文件时我非常疑惑为什么我的文件名没有输错,但是缺报错解析不出来呢。询问了同学才知道直接打开会由于跨域无法访问本地文件,而liveserver用来创建一个本地的小型服务器,避开了跨域问题,从而解决了无法读取本地文件的问题。感恩热心的同学!
同时live server插件可以实现在浏览器中浏览网页并且在VS Code保存时,浏览器即可自动刷新,我仿佛打开了新世界的大门,节省了很多我点刷新的力气。
一款非常非常好用的图表插件,覆盖了几乎所有的基本类型图表,甚至可以定制需要的图表的js引入。并且官网中有很多基本的图表实例,有详细代码和演示效果图,对新手很友好,简单便捷。
LLC to LCT
lct非常认真负责,主动安排分工,给我们的协作开了个好头,同时又很细心,对待每一个细节都很认真,比如网页整体排版的调整。在我们协作的过程中,经常主动提出建设性意见,一起优化所制作的网页。
LCT to LLC
因为和LLC同学比较熟所以这次合作比较顺利,和她沟通比较顺畅,有意见不统一的地方,我们也会各自说出自己的想法,求同存异。而且我们水平相近,不会出现一方一味带飞,一方一味躺平的情况,更多是互相分享经验,比如世界地图我学会了之后教她,解析json文件她学会了教我,互相促进共同进步。