虚位以待(AD)
虚位以待(AD)
首页 > 网页特效 > Jquery > Angularjs 实现移动端在线测评效果(推荐)

Angularjs 实现移动端在线测评效果(推荐)
类别:Jquery   作者:码皇   来源:互联网   点击:

这篇文章主要介绍了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);


相关热词搜索: angularjs实现在线测评