注:此文所用的angular版本为 1.6

一、运行效果图
二、需求
1. 点击选项时,背景(即选中状态),并且自动切换到下一题
2. 切换到下一题时,顶部进度随之改变
3. 选中时要把对应的分值记录下来(因为要根据分值算出最后的测评结果)
4. 通过向右滑动可以查看前面做过的题目
5. 当前题目没选,无法切换到下一题
6. 当选中最后一道题目时,切换到测评结果页
三、具体实现
题目json数据,总共10道题,这里为了节省篇幅,就只贴出3道了。 (Score是分数, OrderNo是答案序号)
{ "Questions":
[
{
"Question":"您的年龄范围:",
"AnswerList":[
{"Text":"30岁以下","Score":5,"OrderNo":0},
{"Text":"30-39岁","Score":4,"OrderNo":1},
{"Text":"40-49岁","Score":3,"OrderNo":2},
{"Text":"50-59岁","Score":2,"OrderNo":3},
{"Text":"60岁以上","Score":1,"OrderNo":4}]
},
{
"Question":"您的婚姻状况为:",
"AnswerList":[
{"Text":"未婚","Score":5,"OrderNo":1},
{"Text":"已婚","Score":4,"OrderNo":2},
{"Text":"单身有婚史","Score":3,"OrderNo":3},
{"Text":"丧偶","Score":2,"OrderNo":4},
{"Text":"不详","Score":1,"OrderNo":5}]
},
{
"Question":"您的收入需要用来供养其他人(如父母或子女)吗?",
"AnswerList":[
{"Text":"不需供养其他人","Score":5,"OrderNo":1},
{"Text":"供养1人","Score":4,"OrderNo":2},
{"Text":"供养2人","Score":3,"OrderNo":3},
{"Text":"供养3人","Score":2,"OrderNo":4},
{"Text":"供养4人或以上","Score":1,"OrderNo":5}]
}
]
}
Html代码
<div class="wrapper" ng-controller="RiskTestController as vm">
<div class="process-box">
<ul>
<li class="page-icon"><span class="icon icon-txt">1</span></li>
<li class="page-icon"><span class="icon icon-txt">2</span></li>
<li class="page-icon"><span class="icon icon-txt">3</span></li>
<li class="page-icon"><span class="icon icon-txt">4</span></li>
<li class="page-icon"><span class="icon icon-txt">5</span></li>
<li class="page-icon"><span class="icon icon-txt">6</span></li>
<li class="page-icon"><span class="icon icon-txt">7</span></li>
<li class="page-icon"><span class="icon icon-txt">8</span></li>
<li class="page-icon"><span class="icon icon-txt">9</span></li>
<li class="page-icon"><span class="icon icon-txt">10</span></li>
</ul>
<div class="page-info">
已完成 {{vm.count}}/10
</div>
</div>
<ul class="list-box" id="listBox">
<li class="list-item" ng-repeat="question in vm.questionList track by $index" ng-class="{'first-li': $index == 0}">
<div class="question-box">
<div class="question">{{$index + 1}}. {{question.Question}}</div>
<ul class="answer">
<li class="answer-item"
ng-repeat="answer in question.AnswerList track by $index"
ng-click="vm.OnClickAnswer(answer, $parent.$index)"
ng-class="{'selected': answer.Selected}">
{{vm.letter[$index]}}. {{answer.Text}}
</li>
</ul>
</div>
</li>
</ul>
<div ng-show="vm.showResult">
<span>{{vm.point}}</span>
</div>
</div>
核心CSS样式代码
.wrapper{
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.process-box{
width: 17.25rem;
height: 2.5rem;
line-height: 2.5rem;
background-color: #FFF;
margin: 1.5rem auto;
border-radius: 0.2rem;
}
.page-icon{
float: left;
font-size: 0.4rem;
color: #FFE7C9;
width: 1.32rem;
text-align: center;
}
.page-info{
font-size: 0.65rem;
color: #F3A84D;
}
.question-box{
width: 17.25rem;
background-color: #FFF;
margin-left: 0.75rem;
border-radius: 0.2rem;
}
.question{
font-size: 0.8rem;
color: #43689F;
padding: 1.1rem 0 0.8rem 0.75rem;
}
.answer-item{
font-size: 0.75rem;
color: #80A1D0;
border-top: 1px solid #EEE;
padding: 1.1rem 0 1.1rem 1.0rem;
}
.icon-txt{
background-color: orange;
border-radius: 0.5rem;
display: block;
width: 0.8rem;
height: 0.8rem;
line-height: 0.8rem;
margin: 0.95rem auto;
}
.icon-txt-active{
background-color: #FFE7C9;
border-radius: 0.3rem;
display: block;
width: 0.3rem;
height: 0.3rem;
line-height: 2.0rem;
color: #FFF;
margin: 1.25rem auto;
}
.list-item {
width: 100%;
position: absolute;
transform: translate3d(100%,0,0);
transition: transform 0.5s;
}
.first-li {
transform: translate3d(0,0,0);
}
.selected {
background-color: orange;
}
控制器代码(Controller)
(function (agr) {
//模块 - app
var app = agr.module('app', []);
//控制器 - 风险测评
app.controller('RiskTestController', ['$scope', '$http', RiskTestController]);
function RiskTestController($scope, $http) {
var vm = this;
vm.letter = ['A', 'B', 'C', 'D', 'E']; //答案编号
vm.questionList = []; //题目
vm.point = 0; //得分
vm.showResult = false; //是否显示结果页
//加载数据
$http({
method: 'GET',
url: '/Service/RiskTest',
}).then(function (resp) {
vm.questionList = resp.data.Questions;
}, function (resp) {
console.log("ERROR", resp);
});
var lis = document.querySelectorAll(".list-item"), //题目列表
count = 0, //做了多少道题
index = 0, //当前第几题
BIG = 9; //最大索引值,因为总共10道题,所以是9(常量)
//选择答案
vm.OnClickAnswer = function (answer, $parentIndex) {
var icons = document.querySelectorAll(".icon"),
curr = $parentIndex; //当前题目索引
next = $parentIndex + 1; //下一题索引
nextQuestion = vm.questionList[next]; //下一道题
//当前问题的答案列表
var answerList = vm.questionList[$parentIndex].AnswerList;
//为每个答案对象添加属性 Selected, 默认值为false
for (var i = 0, len = answerList.length; i < len; i++) {
answerList[i].Selected = false;
}
//将选中的答案设置为true (从而应用样式.selected 将背景色设置)
answer.Selected = true;
//判断是否为最后一道题
if ($parentIndex < BIG) { //不是最后一题
//改变顶部进度样式
icons[curr].classList.remove("icon-txt");
icons[curr].classList.add("icon-txt-active");
//切换到下一题
lis[curr].style.webkitTransform = 'Translate3d(-100%,0,0)';
nextQuestion && (lis[next].style.webkitTransform = 'Translate3d(0,0,0)');
} else { //是最后一题
//改变顶部进度样式
icons[curr].classList.remove("icon-txt");
icons[curr].classList.add("icon-txt-active");
//计算分数
vm.point = CalcPoint();
//显示测评结果
vm.showResult = true;
}
//做了多少题
count = CalcCount();
//因为选中答案会自动切换到下一题,所以索引更新为next
index = next;
}
//计算分数
var CalcPoint = function () {
var point = 0;
for (var i = 0, lenq = vm.questionList.length; i < lenq; i++) {
for (var k = 0, lena = vm.questionList[i].AnswerList.length; k < lena; k++) {
if (vm.questionList[i].AnswerList[k].Selected) {
point += vm.questionList[i].AnswerList[k].Score;
}
}
}
return point;
}
//计算当前做了多少道题
var CalcCount = function(){
var count = 0;
for (var i = 0, lenq = vm.questionList.length; i < lenq; i++) {
for (var k = 0, lena = vm.questionList[i].AnswerList.length; k < lena; k++) {
if (vm.questionList[i].AnswerList[k].Selected) {
count++;
}
}
}
return count;
}
/** 触屏滑动效果处理 == 开始 == **/
var offsetX = 0, //手指滑动偏移量
startX, //滑动开始时的X轴坐标点
startTime; //手指滑动开始时间
//触屏开始
var startHandler = function (evt) {
//每次触屏时将偏移量重置为0
offsetX = 0;
//记录X坐标
startX = evt.touches[0].pageX;
//取得时间戳
startTime = new Date() * 1;
};
//触屏滑动
var moveHandler = function (evt) {
//阻止默认事件
evt.preventDefault();
//记录手指滑动的偏移量
offsetX = evt.touches[0].pageX - startX;
var curr = index,
prev = index - 1,
next = index + 1,
prevQuestion = vm.questionList[prev],
nextQuestion = vm.questionList[next],
width = window.innerWidth;
//手指滑动时题卡跟着手指滑动(向右滑:[偏移量大于0,即正数,并且不是第一道题])
if (offsetX > 0 && index > 0) {
lis[curr].style.webkitTransform = 'Translate3d(' + offsetX + 'px, 0, 0)';
prevQuestion && (lis[prev].style.webkitTransform = 'Translate3d(' + (offsetX - width) + 'px, 0, 0)');
}
//手指滑动时题卡跟着手指滑动(向左滑:[偏移量小于0,即负数,并且不是最后一题])
if (offsetX < 0 && index < count) {
lis[curr].style.webkitTransform = 'Translate3d(' + offsetX + 'px, 0, 0)';
nextQuestion && (lis[next].style.webkitTransform = 'Translate3d(' + (offsetX + width) + 'px, 0, 0)');
}
};
//触屏结束
var endHandler = function (evt) {
var boundary = window.innerWidth / 5, //当手指滑动的偏移量为屏幕的5分之一时才进行切换
quickBoundary = 60, //当手指快速滑动时,偏移量为60即可
endTime = new Date() * 1; //获取结束时间戳
//判断是否为快速滑动
if (endTime - startTime > 1000) {
//判断是向左滑还是向右滑
if (offsetX > 0) {
//判断是否达到切换偏移量
if (offsetX >= boundary) {
MoveToRight();
} else {
ResetMoveRight();
}
} else{
if (offsetX < -boundary) {
MoveToLeft();
} else {
ResetMoveLeft();
}
}
} else {
if (offsetX > 0) {
if (offsetX >= quickBoundary) {
MoveToRight();
} else {
ResetMoveRight();
}
} else {
if (offsetX < -quickBoundary) {
MoveToLeft();
} else {
ResetMoveLeft();
}
}
}
};
//向右滑动事件
var MoveToRight = function () {
var curr = index,
prev = index -1,
prevQuestion = vm.questionList[prev];
if (curr > 0) {
lis[curr].style.webkitTransform = 'Translate3d(100%, 0, 0)';
prevQuestion && (lis[prev].style.webkitTransform = 'Translate3d(0, 0, 0)');
index--;
}
}
//右滑重置(当滑动距离没达到切换偏移量时,题卡回到原点)
var ResetMoveRight = function () {
var curr = index,
prev = index -1,
prevQuestion = vm.questionList[prev];
lis[curr].style.webkitTransform = 'Translate3d(0, 0, 0)';
prevQuestion && (lis[prev].style.webkitTransform = 'Translate3d(-100%, 0, 0)');
}
//向左滑动事件
var MoveToLeft = function () {
var curr = index,
next = index + 1,
nextQuestion = vm.questionList[next];
if (curr < count) {
lis[curr].style.webkitTransform = 'Translate3d(-100%, 0, 0)';
nextQuestion && (lis[next].style.webkitTransform = 'Translate3d(0, 0, 0)');
index++;
}
}
//左滑重置(当滑动距离没达到切换偏移量时,题卡回到原点)
var ResetMoveLeft = function () {
var curr = index,
next = index + 1,
nextQuestion = vm.questionList[next];
lis[curr].style.webkitTransform = 'Translate3d(0, 0, 0)';
nextQuestion && (lis[next].style.webkitTransform = 'Translate3d(100%, 0, 0)');
}
//滑动事件
var outer = document.getElementById("listBox");
outer.addEventListener('touchstart', startHandler);
outer.addEventListener('touchmove', moveHandler);
outer.addEventListener('touchend', endHandler);
/** 触屏滑动效果处理 == 结束 == **/
}
})(angular);
# angularjs实现在线测评
# 下一
# 偏移量
# 切换到
# 您的
# 判断是否
# 分值
# 量为
# 做过
# 或以上
# 不需
# 设置为
# 时要
# 时才
# 贴出
# 此文
# 时将
# 值为
# 可以查看
# 第一道
# 背景色
相关文章:
青岛网站设计制作公司,查询青岛招聘信息的网站有哪些?
头像制作网站在线观看,除了站酷,还有哪些比较好的设计网站?
如何快速搭建安全的FTP站点?
简单实现Android验证码
如何用VPS主机快速搭建个人网站?
定制建站如何定义?其核心优势是什么?
用v-html解决Vue.js渲染中html标签不被解析的问题
专业网站制作企业网站,如何制作一个企业网站,建设网站的基本步骤有哪些?
,sp开头的版面叫什么?
如何高效完成自助建站业务培训?
Thinkphp 中 distinct 的用法解析
PHP正则匹配日期和时间(时间戳转换)的实例代码
建站之星在线版空间:自助建站+智能模板一键生成方案
建站之星备案是否影响网站上线时间?
javascript中的try catch异常捕获机制用法分析
c++怎么编写动态链接库dll_c++ __declspec(dllexport)导出与调用【方法】
已有域名如何免费搭建网站?
如何用狗爹虚拟主机快速搭建网站?
如何在宝塔面板中创建新站点?
宝塔新建站点为何无法访问?如何排查?
小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建
如何快速完成中国万网建站详细流程?
高性能网站服务器配置指南:安全稳定与高效建站核心方案
建站之星上传入口如何快速找到?
如何通过.red域名打造高辨识度品牌网站?
无锡营销型网站制作公司,无锡网选车牌流程?
简易网站制作视频教程,使用记事本编写一个简单的网页html文件?
建站与域名管理如何高效结合?
建站之星伪静态规则如何设置?
购物网站制作公司有哪些,哪个购物网站比较好?
如何在阿里云完成域名注册与建站?
简单实现Android文件上传
h5在线制作网站电脑版下载,h5网页制作软件?
建站之星24小时客服电话如何获取?
,有什么在线背英语单词效率比较高的网站?
太原网站制作公司有哪些,网约车营运证查询官网?
如何在阿里云虚拟主机上快速搭建个人网站?
如何在阿里云ECS服务器部署织梦CMS网站?
php能控制zigbee模块吗_php通过串口与cc2530 zigbee通信【介绍】
实例解析angularjs的filter过滤器
香港网站服务器数量如何影响SEO优化效果?
如何用已有域名快速搭建网站?
建站之星客服服务时间及联系方式如何?
头像制作网站在线制作软件,dw网页背景图像怎么设置?
网站制作的步骤包括,正确网址格式怎么写?
江苏网站制作公司有哪些,江苏书法考级官方网站?
专业商城网站制作公司有哪些,pi商城官网是哪个?
c# Task.Yield 的作用是什么 它和Task.Delay(1)有区别吗
盘锦网站制作公司,盘锦大洼有多少5G网站?
如何用PHP快速搭建CMS系统?
*请认真填写需求信息,我们会在24小时内与您取得联系。