2020福州大学软件工程实践结对编程作业二
这个作业属于哪个课程 | 福州大学软件工程 |
---|---|
这个作业要求在哪里 | 结对编程作业二要求 |
这个作业的目标 | 熟练使用github以及了解web页面的编码与设计 |
学号 | 031802538 031802520 |
目录
一、结对信息
团队成员
成员姓名 | 成员学号 | 博客地址 |
---|---|---|
林鸿 | 031802520 | 我的博客 |
余立 | 031802538 | 队友博客 |
github仓库地址
二、具体分工
- 在初期,双方一同查阅相关资料,了解需要学习的知识内容和其应用方式,讨论明确分工
- 余立:主要负责HTML+CSS代码编写设置网页的样式同时了解部分Javascript来设计家族树的样式,同时编写博客
- 林鸿:主要负责学习Javascript代码来进行家族树的框架构建,处理作业中的如鼠标缩放等操作,复审网页样式
- 在截止前,双方一同讨论如何进行有效的单元测试,搜索相关资料,并初步尝试
三、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 40 |
Estimate | 估计这个任务需要多少时间 | 10 | 15 |
Development | 开发 | 360 | 540 |
Analysis | 需求分析 (包括学习新技术) | 20 | 30 |
Design Spec | 生成设计文档 | 60 | 80 |
Design Review | 设计复审 | 40 | 40 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 10 |
Design | 具体设计 | 60 | 45 |
Coding | 具体编码 | 360 | 480 |
Code Review | 代码复审 | 20 | 30 |
Test | 测试(自我测试,修改代码,提交修改) | 30 | 60 |
Reporting | 报告 | 60 | 70 |
Test Report | 测试报告 | 10 | 10 |
Size Measurement | 计算工作量 | 20 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 30 | 30 |
合计 | 1160 | 1500 |
四、解题思路描述与设计实现说明
解题思路
1、首先通过搜索资料了解html+css的设计方式,构建相应的web页面
2、设计好html中的文本框输入数据给js代码处理,以及相应按钮功能
3、编写核心js代码,通过split函数与关键字分割文本数据,分组存储
4、原定以\n\n分割,但由于技能树和工作历程的双换行,再结合学术家族树必有导师,定以导师分割
5、根据相应的符号关键字处理数据,构造相应的家族树模型
6、分函数模块化处理树,设计点击效果以及树的动态更新
7、审查相应的功能同时美化树的样式
代码解释
- 数据结构的初始定义
var treeData = [{
"name": "",
"parent": "",
"children": [{
"name": "",
"parent": "",
"children": [{
"name": "",
"parent": ""
}, {
"name": "",
"parent": "",
"children": [{
"name": "",
parent: ""
}]
}, {
"name": "",
"parent": ""
}, {
"name": "",
"parent": ""
}]
}, {
"name": "",
"parent": "",
"children": [{
"name": "",
"parent": ""
}, {
"name": "",
"parent": ""
}, ]
}, {
"name": "",
"parent": ""
}, ]
}];
- 对于文本框中输入数据,先以“导师:”分割处理成块, 再对块中数据以“\n”处理成树
function getdata() {
var text = $("#text").val(); //获取id为text的textarea的全部内容
var text1 = text.split("导师:");//针对多组数据输入的情况,以"导师:"为关键字进行分组,调用split函数进行分割
for (var k = 1; k < text1.length; k++) { //text1.length用于得到分组的数量
var arry = text1[k].split("\n");//针对每一组数据,以“\n"为关键字进行分组,得到每条导师和学生的信息
var teacher = {
name: '',
children: []
}
teacher.name=arry[0];
var w=0;
for (var ii = 1; ii < arry.length; ii++) {
if(arry[ii].length<3) continue;
var newarr = arry[ii].split(":");//以“:”为关键字进行分组,可得到身份标签和身份信息
var type = [];
var type1 = [];
var a1 = newarr[0]; //获取身份标签,保存在a1
type1.name = a1;
var a2 = newarr[1];//获取身份信息,保存在a2
var a3 = a2.split("、");//针对每组身份信息,以“、”为关键字进行切分,得到每个人的名字信息
w++;
for (var j = 0; j < a3.length; j++) { //a3.length用于得到每条身份信息里名字的数量
var student = {
name: '',
children: []
}
student.name = a3[j];
type.push(student);
}
if(a1.length<=3){ //如果这一行开头是姓名
for(var fff=0;fff<teacher.children.length;fff++){
for(var fc=0;fc<teacher.children[fff].children.length;fc++){
if(teacher.children[fff].children[fc].name==a1){//根据a1查找树中匹配的姓名
for (var j = 0; j < a3.length; j++)
teacher.children[fff].children[fc].children.push(type[j]);//找到后在其后添加信息
}
}
}
continue;
}
type1.children = type;
teacher.children.push(type1);
}
treeData[k] = [];
treeData[k] = teacher;
maketree(k,w);
}
}
- 对于已经处理好的数据树,进行遍历,处理出一颗师门树,同时设计好点击的动态缩放效果
function maketree(k,w) {
var margin = {
top: 20,
right: 120,
bottom: 20,
left: 220,
},
width = 1200- margin.right - margin.left ;
height = w*200 ;
var i = 0,
duration = 750, //过渡延迟时间
root;
var tree = d3.layout.tree() //创建一个树布局
.size([height, width]);
var diagonal = d3.svg.diagonal()
.projection(function(d) {
return [d.y, d.x];
}); //创建新的斜线生成器
//声明与定义画布属性
var svg = d3.select("body").append("svg")
.attr("width", width + margin.right + margin.left)
.attr("height", height + margin.top + margin.bottom)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
root = treeData[k]; //treeData为上边定义的节点属性
root.x0 = height / 2;
root.y0 = 0;
update(root,w);
function update(source,w) {
// 计算新树图的布局
var nodes = tree.nodes(root).reverse(),
links = tree.links(nodes);
// 设置y坐标点,每层占180px
nodes.forEach(function(d) {
d.y = d.depth * 250;
});
// 每个node对应一个group
var node = svg.selectAll("g.node")
.data(nodes, function(d) {
return d.id || (d.id = ++i);
}); //data():绑定一个数组到选择集上,数组的各项值分别与选择集的各元素绑定
// 新增节点数据集,设置位置
var nodeEnter = node.enter().append("g")
.attr("class", "node") //attr设置html属性,style设置css属性
.attr("transform", function(d) {
return "translate(" + source.y0 + "," + source.x0 + ")";
})
.on("click", click);
//添加连接点---此处设置的是圆圈过渡时候的效果(颜色)
nodeEnter.append("rect")
.attr("x", -23)
.attr("y", -10)
.attr("width", 70)
.attr("height", 20)
.attr("rx", 10)
.style("fill", "#6AAFD1"); //d 代表数据,也就是与某元素绑定的数据。
nodeEnter.append("text")
.attr("x", function(d) {
return d.children || d._children ? 13 : 13;
})
.attr("dy", "5")
.attr("text-anchor", "middle")
.text(function(d) {
return d.name;
})
.style("fill", "white")
.style("fill-opacity", 1);
// 将节点过渡到一个新的位置-----主要是针对节点过渡过程中的过渡效果
//node就是保留的数据集,为原来数据的图形添加过渡动画。首先是整个组的位置
var nodeUpdate = node.transition() //开始一个动画过渡
.duration(duration) //过渡延迟时间,此处主要设置的是圆圈节点随斜线的过渡延迟
.attr("transform", function(d) {
return "translate(" + d.y + "," + d.x + ")";
});
nodeUpdate.select("rect")
.attr("x", -46)
.attr("y", -16)
.attr("width", 120)
.attr("height", 30)
.attr("rx", 10)
.style("fill", "#6AAFD1");
nodeUpdate.select("text")
.attr("text-anchor", "middle")
.style("fill-opacity", 1);
// 过渡现有的节点到父母的新位置。
//最后处理消失的数据,添加消失动画
var nodeExit = node.exit().transition()
.duration(duration)
.attr("transform", function(d) {
return "translate(" + source.y + "," + source.x + ")";
})
.remove();
nodeExit.select("circle")
.attr("r", 1e-6);
nodeExit.select("text")
.attr("text-anchor", "middle")
.style("fill-opacity", 1e-6);
// 线操作相关
//再处理连线集合
var link = svg.selectAll("path.link")
.data(links, function(d) {
return d.target.id;
});
//添加新的连线
link.enter().insert("path", "g")
.attr("class", "link")
.attr("d", function(d) {
var o = {
x: source.x0,
y: source.y0
};
return diagonal({
source: o,
target: o
}); //diagonal - 生成一个二维贝塞尔连接器, 用于节点连接图.
})
.attr('marker-end', 'url(#arrow)');
// 将斜线过渡到新的位置
//保留的连线添加过渡动画
link.transition()
.duration(duration)
.attr("d", diagonal);
// 过渡现有的斜线到父母的新位置。
//消失的连线添加过渡动画
link.exit().transition()
.duration(duration)
.attr("d", function(d) {
var o = {
x: source.x,
y: source.y
};
return diagonal({
source: o,
target: o
});
})
.remove();
// 将旧的斜线过渡效果隐藏
nodes.forEach(function(d) {
d.x0 = d.x;
d.y0 = d.y;
});
}
//定义一个将某节点折叠的函数
// 切换子节点事件
function click(d) {
if (d.children) {
d._children = d.children;
d.children = null;
} else {
d.children = d._children;
d._children = null;
}
update(d);
}
}
具体效果
- 根据输入要求的示例输出,静态展示
- 根据点击缩放要求,动态展示
五、附加特点设计与展示
- 界面背景美化,色调统一
1、覆盖一张纯蓝色的风景图,没有过多要素,简洁雅观
2、为了师门树更好地显示,将背景图虚化
3、给html中body样式添加居中效果,所有div居中显示
4、添加outline:none语句删除了html中点击后生成的黑框,让界面更优美,以下为原先点击效果
5、添加符合主题的小树图标,美化界面
部分CSS样式代码
body {
margin: 0px;
padding: 0px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
font-family: "Microsoft YaHei";
}
.bg{
background: url('img/background.jpg');
background-size: cover;
position: fixed;
top: -20px;
left: -20px;
right: -20px;
bottom: -20px;
-webkit-filter: blur(5px);
filter: blur(5px);
z-index: -1;
}
.mask {
width: 100px;
height: 100px;
margin-top:15px;
background-image: url('img/tree.png');
background-size: cover;
border-radius: 15px;
}
.button {
background-color:rgb(126, 214, 248);
color:#ffffff;
float:left;
width: 120px;
padding: 6px;
border-radius: 20px;
font-size: 18px;
outline:none;
}
- 增加重置功能按钮
由于web页面生成原因,如果在生成家族树后再次生成,树将生成在原树下面。为此,添加重置功能按钮清除旧的家族树
<button class="button2" value=重置 onclick="location.reload()">重置</button>
- 根据节点数量动态设置学术家族树的高度设置,避免因数据过多造成的重叠
六、目录说明和使用说明
目录说明
- img文件夹存放相关图标和背景图
- js文件夹存放下载的js函数库,以便调用
- style文件即web页面的样式设计,由html文件调用
- tree文件即最终的web文件,调用以上内容
使用说明
1、在github上下载(code→Download ZIP)至电脑并解压成文件夹
2、在解压出的文件夹中找到tree.html,右键点击打开方式选择Google Chrome打开
3、在输入框中输入相应的测试数据,如:
导师:张三
2016级博士生:天一、王二、吴五
2015级硕士生:李四、王五、许六
2016级硕士生:刘一、李二、李三
2017级本科生:刘六、琪七、司四
刘六:JAVA、数学建模
李二:字节跳动、京东云
4、本次作业中默认多颗树并存,新树生成于旧树之下,若清空请点击重置
七、单元测试
1.测试工具:Mocha
测试工具的学习网站:http://www.ruanyifeng.com/blog/2015/12/a-mocha-tutorial-of-examples.html
2.对输入文本进行数据处理函数的测试:
八、Github的代码签入记录截图
九、遇到的代码模块异常或结对困难及解决方法
1、
- 问题:在对技能树或项目经历进行名字匹配以及添加节点出现了问题
- 尝试:调试代码时没有报错,但是生成学术家族树按键按下去没反应,在循环里加了个alert("XX”)进行debug
- 解决:实质上是在最初的html中尚未添加link语句调用库
- 收获:多种语言应相互协调,不单向处理
2、
- 问题:对于没有技能树和功项目经历时按照“\n\n"进行分割可行,添加上就得换个关键字处理
- 尝试:根据就用输入要求思考如何处理
- 解决:选择“导师:”进行分割,必然处理出相应的根节点
- 收获:在最初编写代码时应想好如何处理,而不是在后期调整
3、
- 问题:对于HTML+CSS部分页面设计的浮动状态运用混乱,设计难以调整
- 尝试:在慕课网进行系统的学习,了解其使用
- 解决:通过在css中配置相应的参数调整位置
- 收获:更加深入了解CSS的处理
4、
- Javascript对于中英文符号处理有差别,要认真处理
十、评价你的队友
余立
值得学习的地方:
- 善于运用互联网资料,在博客园、CSDN查找大量相关资料
- 自学经验丰富,提供多个学习平台网站
- 对于工作任务处理细致,考虑周到,规划合理
需要改进的地方:
- 对工作没有积极性,时常拖延
- 交流讨论时,时常转向生活话题
林鸿
值得学习的地方:
- 学习效率高,能快速了解代码内容
- 工作心态良好,稳扎稳打
需要改进的地方:
- 只有分配工作后快速完成,不会自行规划
- 不善于查找资料,缺乏自主性