当前位置:首页 > 日记 > 正文

Angularjs 实现移动端在线测评效果 | 推荐

Angularjs 实现移动端在线测评效果 | 推荐

注:此文所用的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);


相关文章

JavaScript中Hoisting详解  | 变量

JavaScript中Hoisting详解 | 变量

函数声明,提升,变量提升,详解,电脑软件,本文主要给大家介绍了关于JavaScript中Hoisting(变量提升与函数声明提升)的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧。如何将 函数声明 / 变量 “移动” 到作用域的顶部…

ppt2010怎样制作艺术字水印

ppt2010怎样制作艺术字水印

方法,水印,艺术字,电脑软件,  ppt2010如何用艺术字做水印呢?这时我们需要用到母板的功能,具体怎么做,对于不常用对于不常用ppt的朋友或许有点难度,下面小编来告诉你ppt2010用艺术字做水印的方法吧。ppt2010用艺术字做水印的方法在&ldquo;视…

php大小写转换函数 | strtolower、

php大小写转换函数 | strtolower、

大小写,转换函数,电脑软件,php,strtoupper,1,将字符串转换成小写strtolower函数: 该函数将传入的字符串参数所有的字符都转换成小写,并以小定形式放回这个字符串。例子:<?php $str = "I want To FLY"; $str = strtolower($str); echo $st…

jQuery 实现鼠标画框并对框内数据

jQuery 实现鼠标画框并对框内数据

数据,实例代码,鼠标,并对,电脑软件,jquery库:jquery -1.10.2.min.js,jQuery UI - v1.12.1。jQuery 代码不多说了,之间上代码。不懂的地方看注释。<script type="text/javascript"> //鼠标按下时的X Y坐标 var mouseDownX; var mouseDownY; /…

WebService传XML 简单实例

WebService传XML 简单实例

简单实例,电脑软件,WebService,XML,WebService传XML 简单实例传送 [WebMethod]public XmlDataDocument GetSiteAData(string AssignName) { XmlDataDocument xd = new XmlDataDocument(); DataSet ds = BusinessWork.BusinessWor…

Windows7 IIS+ASP http500内部服务

Windows7 IIS+ASP http500内部服务

显示,错误,服务器,本来面目,电脑软件,在WINDOWS 7上安装了IIS7.5,调试ASP程序时出现http500内部服务器错误:首先,打开IE选项设置&mdash;高级&mdash;把&ldquo;显示友好http错误信息&rdquo;,可以看到如下错误提示:解决办法是打开将错误送到浏览器…

详谈jQuery unbind 删除绑定事件 /

详谈jQuery unbind 删除绑定事件 /

标签,删除,绑定事件,方法,移除,jQuery unbind 删除绑定事件unbind([type],[data]) 是 bind()的反向操作,从每一个匹配的元素中删除绑定的事件。如果没有参数,则删除所有绑定的事件。你可以将你用bind()注册的自定义事件取消绑定。如果提供了…

给Ajax返回的HTML标签动态添加样式

给Ajax返回的HTML标签动态添加样式

标签,方法,动态添加,样式,电脑软件,今天在做项目时,在页面中用ajax返回了另一个页面,突然发现返回页面中的表格把页面给顶了出去,经过一番研究,终于解决了。先准备好要返回内容的容器<div class="container"> </div>预定义一个样式,以便返回的…

Word2013怎样对表格更换样式颜色

Word2013怎样对表格更换样式颜色

样式,表格,颜色,电脑软件,  Word2013表格初始默认的样式看起来感觉没什么特色,如果想为了提高表格的质量,我们可以更换样式颜色。以下是小编为您带来的关于Word2013表格更换样式颜色,希望对您有所帮助。Word2013表格更换样式颜色具体做法:1、…

thinkPHP框架中执行原生SQL语句的

thinkPHP框架中执行原生SQL语句的

框架,执行,语句,原生,方法,本文实例讲述了thinkPHP框架中执行原生SQL语句的方法。分享给大家供大家参考,具体如下:怎样在thinkphp里面执行原生的sql语句?$Model = new Model();//或者 $Model = D(); 或者 $Model = M();$sql = "select * from…

JS实现小球的弹性碰撞效果

JS实现小球的弹性碰撞效果

弹性碰撞,小球,效果,电脑软件,JS,一、HTML代码(body部分) <body> <!--只需要做一个大div包裹几个小div即可,你想要几个小球碰撞就在内部做几个div即可,这里我们做了6个小球--> <div id="main"> <div></div> <div></div> <di…

.NET附件上传大小限制控制

.NET附件上传大小限制控制

控制,上传,附件,大小,电脑软件,今天在公司的服务器上搭建了一个Dvbbs.Net 1.1,协助管理公司一些办公文件,由于要上传的文件大小部分较大(超过几十兆),所以今天的大部分时间是研究怎么破除上传的限制问题。知道23点以后才基本上解决。现将问题处…