前端应用 - 实现连线习题兼容移动端进阶版

 接上期《前端应用 - 实现100以内加减法的连线习题兼容移动端》优化并加入多范围及检查功能

1.指定出题范围

2.检查作业并指出错题,只作弹窗提示,如想更好效果可以自行修改为错题高亮显示。

前端应用 - 实现连线习题兼容移动端进阶版

html代码:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width,user-scalable=no, initial-scale=1">
    <title>连线习题 - 加减法快速口算</title>
    <link rel="stylesheet" href="./static/css/app.css">
</head>
<body>
<div class="demo1">
    <div class="toolsImageBtn">      
        <input type="button" val="10"   value="10以内"  class="btn initCalc">
        <input type="button" val="20"   value="20以内"  class="btn initCalc">
        <input type="button" val="50"   value="50以内"  class="btn initCalc">
        <input type="button" val="100"  value="100以内" class="btn initCalc">
    </div>
    <div class="show clearfix">
        <div class="showleft" first="0">
            <!--左侧 内容根据需要调整-->
        </div>
        <div class="showright" first="0">
            <!--右侧-->                                       
        </div>
        <canvas class="canvas"></canvas>
        <!--连线画布-->
        <canvas class="backcanvas"></canvas>
        <!--提示线画布-->

    </div>
    <div class="toolsImageBtn">
        <input type="button" title="重做"  value="重做" class="btn resetCanvasBtn">        
        <input type="button" title="回退"  value="回退" class="btn goBackBtn">
        <input type="button" title="检查"  value="检查" class="btn submit">
    </div>
</div>
<audio src="https://img.tukuppt.com/newpreview_music/00/16/68/5ea67a049c28883715.mp3" id="nizhenbang" hidden="hidden"></audio>
<audio src="https://img.tukuppt.com/newpreview_music/00/04/73/5c85cebf7c62b21694.mp3" id="yihan" hidden="hidden"></audio>
</body>
</html>
<script src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script src="./static/js/app.js"></script>

js主程序

$(function() {
    var OACalc = {
        initialised: false,
        version    : 1.0,
        init: function (a = null,b = null,c = null) {
            var that = this;
            that.maxRdm = a?Math.round(a)+1:101;
            that.operatorArr = c?c:['+', '-'];
            that.tData = {tm:[],da:[]};
            var b = b?b:5;
            var count = 0;
            while(count < b){
                var tmp = that.create();
                if(tmp) count++;
            }
            that.tData.tm.sort(function(){ return 0.5 - Math.random()}); //打乱数组排序 - 算式
            that.tData.da.sort(function(){ return 0.5 - Math.random()}); //打乱数组排序 - 答案
            return that.tData;
        },
        getRandom: function () {
            return Math.floor(Math.random()*this.maxRdm);
        },
        getOperator: function () {
            var arr = this.operatorArr;
            return arr[Math.floor(Math.random()*arr.length)];
        },
        validate: function (num1, op, num2) {
            if (op === '÷' && num2 === 0) return false;
            if (num1%num2 != 0) return false;
            if (op === '-' && num1 < num2) return false;
            return true;
        },
        create: function () {
            var that = this;
            var num1 = that.getRandom();
            var num2 = that.getRandom();
            var op   = that.getOperator();
            var opTemp = op;
            if (op === '×') opTemp = '*';
            if (op === '÷') opTemp = '/';
            var answer = eval(num1 + (opTemp) + num2);
             
            if(!that.validate(num1, op, num2)) return;
            var str = num1 + " " + op + " " + num2 + " =";
            that.tData.tm.push(str);
            that.tData.da.push(answer);
            return true;
        },
    };
    
    var OAIndex = {
        initialised: false,
        version    : 1.0,
        touchstart : "touchstart",
        touchmove  : "touchmove",
        touchend   : "touchend",
        init: function (box,num) {
            if (!this.initialised) {this.initialised = true;}else{return;}
            if (this.isPC()) {
                this.touchstart = "mousedown";
                this.touchmove  = "mousemove";
                this.touchend   = "mouseup";
            }
            this.box       = box;
            this.linewidth = 2;
            this.linestyle = "#ff5500"; //连线绘制--线宽,线色
            //canvas 赋值
            this.canvasTag     = null;  //获取canvas 实际连线标签
            this.backcanvasTag = null;  //获取canvas 模拟连线标签
            this.context       = null;  //画板 实际连线
            this.backcanvas    = null;  //画板 模拟连线      
            //连线数据
            this.groupstate = false; //按下事件状态,标记按下后的移动,抬起参考
            this.mx         = [];    //连线坐标
            this.my         = [];
            this.ms         = [];
            this.temp       = {};    //存贮按下的对象
            this.pair       = 0 ;    //配对属性
            this.pairl      = [];
            this.pairr      = [];
            //存储虚拟连线起始坐标
            this.mid_startx = null;
            this.mid_starty = null;
            this.mid_endx   = null;
            this.mid_endy   = null;
            this.context    = null; //canvas追加2d画图
            //存放遍历坐标
            this.lastX      = null;
            this.lastY      = null;
            this.loadData(num);
            this.loadTouchFun(this.box);
        },
        isPC: function () {
            var ua = navigator.userAgent.toLowerCase();
            if(/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini|ZTE/.test(navigator.userAgent)) || ua.match(/MicroMessenger/i) == "micromessenger"){
                return false;
            }else{
                return true;
            }
        },
        loadData: function (m) {
            // var tData = {
            //     tm:['4+5','5+9','9-7','6-2'],
            //     da:['2','9','4','14'],
            // };
            var num = 100;
            if (m) {num = m;}
            var tData = OACalc.init(num,5,['+','-']);
            var leftHtml = '',rightHtml = '';
            $.each(tData.tm, function(k, v) {
                leftHtml += '<span class="showitem" group="gpl"  sel="0" check="0" pair="'+k+'">'+
                            '<p>'+v+'</p>'+
                            '</span> ';
            });
            $.each(tData.da, function(k, v) {
                rightHtml += '<span class="showitem" group="gpr"  sel="0" check="0" pair="'+k+'">'+
                            '<p>'+v+'</p>'+
                            '</span> ';
            });
            $('.showleft').html(leftHtml);    
            $('.showright').html(rightHtml);
        },
        strockline: function () {
            var that = this;
            var box  = that.box;
            that.context.clearRect(0, 0, box.find(".show").width(), box.find(".show").height()); //整个画布清除
            that.context.save();
            that.context.beginPath();
            that.context.lineWidth = that.linewidth;
            for (var i = 0; i < that.ms.length; i++) { //遍历绘制
                lastX = that.mx[i];
                lastY = that.my[i];
                if (that.ms[i] == 0) {
                    that.context.moveTo(lastX, lastY);
                } else {
                    that.context.lineTo(lastX, lastY);
                }
            }
            that.context.strokeStyle = that.linestyle;
            that.context.stroke();
            that.context.restore();
        },                      
        clearline: function () {
            var that = this;
            var box  = that.box;
            that.context.clearRect(0, 0, box.find(".show").width(), box.find(".show").height());
            that.mx = []; //数据清除
            that.my = [];
            that.ms = [];
            that.pairl = [];
            that.pairr = [];
            that.pair = 0;
            box.find(".showleft").children("span").each(function(index, element) {
                $(this).removeClass("addstyle");
                $(this).attr("sel", "0");
                $(this).attr("check", "0");
                            
            });
            box.find(".showleft").attr('first', 0);
            box.find(".showright").children("span").each(function(index, element) {
                $(this).removeClass("addstyle");
                $(this).attr("sel", "0");
                $(this).attr("check", "0");
            });
            box.find(".showright").attr('first', 0);
        },                       
        backstrockline: function () {
            var that = this;
            var box  = that.box;
            that.backcanvas.clearRect(0, 0, box.find(".show").width(), box.find(".show").height());
            that.backcanvas.save();
            that.backcanvas.beginPath();
            that.backcanvas.lineWidth = that.linewidth;
            that.backcanvas.moveTo(that.mid_startx, that.mid_starty);
            that.backcanvas.lineTo(that.mid_endx, that.mid_endy);
            that.backcanvas.strokeStyle = that.linestyle;
            that.backcanvas.stroke();
            that.backcanvas.restore();
        },                      
        clearbackline: function () {
            var that = this;
            var box  = that.box;
            that.backcanvas.clearRect(0, 0, box.find(".show").width(), box.find(".show").height());
            that.mid_startx = null;
            that.mid_starty = null;
            that.mid_endx   = null;
            that.mid_endy   = null;
        },       
        goBack: function () {
            var that = this;
            var box  = that.box;
            var linenlastIndex = that.ms.join("").substr(0, that.ms.length - 1).lastIndexOf("0");
            if (linenlastIndex == 0) {
                that.clearline();
            } else {
                that.mx = that.mx.slice(0, linenlastIndex); //记录值
                that.my = that.my.slice(0, linenlastIndex); //坐标
                that.ms = that.ms.slice(0, linenlastIndex);
                that.context.clearRect(0, 0, box.find(".show").width(), box.find(".show").height());
                that.context.save();
                that.context.beginPath();
                that.context.lineWidth = that.linewidth;
                for (var i = 0; i < that.ms.length; i++) {
                    lastX = that.mx[i];
                    lastY = that.my[i];
                    if (that.ms[i] == 0) {
                        that.context.moveTo(lastX, lastY);
                    } else {
                        that.context.lineTo(lastX, lastY);
                    }
                }
                that.context.strokeStyle = that.linestyle;
                that.context.stroke();
                that.context.restore();
                var pairindex = that.pairl.length - 1;
                box.find(".showleft").children("span").each(function(index, element) {
                    if ($(this).attr("pair") == that.pairl[pairindex]) {
                        $(this).removeClass("addstyle");
                        $(this).attr("sel", "0");
                        $(this).attr("check", "0");
                    };
                });
                box.find(".showleft").attr('first', 0);
                box.find(".showright").children("span").each(function(index, element) {
                    if ($(this).attr("pair") == that.pairr[pairindex]) {
                        $(this).removeClass("addstyle");
                        $(this).attr("sel", "0");
                        $(this).attr("check", "0");
                    };
                });
                box.find(".showright").attr('first', 0);
                that.pair -= 1;
                that.pairl = that.pairl.slice(0, pairindex);
                that.pairr = that.pairr.slice(0, pairindex);
            };
        },                             
        loadTouchFun: function (box) {
            var that = this;
            //初始化赋值 列表内容
            box.find(".showleft").children("span").each(function(index, element) {
                $(this).attr({
                    group: "gpl",
                    left: $(this).position().left + $(this).outerWidth(),
                    top:  $(this).position().top + $(this).outerHeight() / 2,
                    sel:  "0",
                    check: "0"
                });
            });
            box.find(".showright").children("span").each(function(index, element) {
                $(this).attr({
                    group: "gpr",
                    left: $(this).position().left,
                    top: $(this).position().top + $(this).outerHeight() / 2,
                    sel: "0",
                    check: "0"
                });
            });
            box.find(".showleft").attr('first', 0); //初始赋值 列表内容容器
            box.find(".showright").attr('first', 0);
            //canvas 赋值
            that.canvasTag = box.find(".canvas")[0]; //获取canvas  实际连线标签
            that.canvasTag.width = box.find(".show").width(); //canvas宽度等于div容器宽度
            that.canvasTag.height = box.find(".show").height();
            
            that.backcanvasTag = box.find(".backcanvas")[0]; //获取canvas 模拟连线标签
            that.backcanvasTag.width = box.find(".show").width();
            that.backcanvasTag.height = box.find(".show").height();

            //事件处理---按下
            box.children(".show").children().children("span").on(that.touchstart, function(event) {
                that.groupstate = true;
                if ($(this).attr("check") == 1) {
                    $(this).attr("sel", "1").parent().attr("first", "1");
                    that.temp = $(this);
                } else {
                    $(this).attr("sel", "1").addClass("addstyle").parent().attr("first", "1");
                    that.temp = $(this);
                };
                that.mid_startx = $(this).attr("left");
                that.mid_starty = $(this).attr("top");
                event.preventDefault();
            });
            
            $(document).on(that.touchmove, function(event) {
                // 判断默认行为是否可以被禁用
                if (event.cancelable) {
                    // 判断默认行为是否已经被禁用
                    if (!event.defaultPrevented) {
                        if (that.isPC()) {
                            var $target = $(event.target);
                            var pageX = event.pageX;
                            var pageY = event.pageY;
                        }else{
                            var pageX = event.originalEvent.touches[0].pageX & event.originalEvent.changedTouches[0].pageX & event.originalEvent.targetTouches[0].pageX;
                            var pageY = event.originalEvent.touches[0].pageY & event.originalEvent.changedTouches[0].pageY & event.originalEvent.targetTouches[0].pageY
                            /**
                            *获取存储当前Dom位置的对象
                            **/
                            var myLocation = event.originalEvent.changedTouches[0];
                            /**
                            *取clientX及clientY并传入elementFromPoint获取当前手指触摸的Dom,大功告成,现在此Dom可以任你摆布了
                            **/
                            var realTarget = document.elementFromPoint(myLocation.clientX, myLocation.clientY);
                            var $target = $(realTarget);
                        }
                        
                        if (that.groupstate) {
                            that.mid_endx = pageX - box.find(".show").offset().left;
                            that.mid_endy = pageY - box.find(".show").offset().top;
                            var targettrue = null;

                            if ($target.is("span") && $target.closest(".show").parent().attr("class") == box.attr("class")) {
                                targettrue = $target;
                            } else if ($target.closest(".showitem").is("span") && $target.closest(".show").parent().attr("class") == box.attr("class")) {
                                targettrue = $target.closest(".showitem");
                            } else {
                                targettrue = null;
                            };

                            if (targettrue) {
                                if (targettrue.parent().attr("first") == 0) {
                                    if (targettrue.attr("check") == 0) {
                                        targettrue.addClass("addstyle").attr("sel", "1").siblings("span[check=0]").removeClass("addstyle").attr("sel", "0");
                                    }
                                } else {
                                    if (targettrue.attr("check") == 0) {
                                        targettrue.addClass("addstyle").attr("sel", "1").siblings("span[check=0]").removeClass("addstyle").attr("sel", "0");
                                        that.mid_startx = targettrue.attr("left");
                                        that.mid_starty = targettrue.attr("top");
                                    }
                                };
                            } else {

                                if (box.find(".showleft").attr("first") == 0) {
                                    box.find(".showleft").children("span").each(function(index, element) {
                                        if ($(this).attr('check') == 0) {
                                            $(this).attr("sel", "0").removeClass("addstyle");
                                        };
                                    });
                                };
                                if (box.find(".showright").attr("first") == 0) {
                                    box.find(".showright").children("span").each(function(index, element) {
                                        if ($(this).attr('check') == 0) {
                                            $(this).attr("sel", "0").removeClass("addstyle");
                                        };
                                    });
                                };

                            };
                            that.backstrockline();
                        };
                        event.preventDefault();
                    }
                }
            });

            $(document).on(that.touchend, function(event) {
                // 判断默认行为是否可以被禁用
                if (event.cancelable) {
                    // 判断默认行为是否已经被禁用
                    if (!event.defaultPrevented) {
                        if (that.isPC()) {
                            var $target    = $(event.target);
                        }else{
                            var myLocation = event.originalEvent.changedTouches[0];
                            var realTarget = document.elementFromPoint(myLocation.clientX, myLocation.clientY);
                            var $target    = $(realTarget);
                        }
                        if (that.groupstate) {
                            var targettrue;
                            if ($target.is("span") && $target.closest(".show").parent().attr("class") == box.attr("class")) {
                                targettrue = $target;
                            } else if ($target.closest(".showitem").is("span") && $target.closest(".show").parent().attr("class") == box.attr("class")) {
                                targettrue = $target.closest(".showitem");
                            } else {
                                targettrue = null;
                            };

                            if (targettrue) {
                                if (targettrue.parent().attr("first") == 0) {
                                    if (targettrue.attr("check") == 0) {
                                        if (that.temp.attr('check') == 1) {
                                            box.find(".showleft").children("span").each(function(index, element) {
                                                if ($(this).attr('sel') == 1) {
                                                    if ($(this).attr('check') == 0) {
                                                        $(this).attr("sel", "0").removeClass("addstyle");
                                                    } else {
                                                        $(this).attr("sel", "0").addClass("addstyle");
                                                    };
                                                }
                                            });
                                            box.find(".showleft").attr('first', 0);
                                            box.find(".showright").children("span").each(function(index, element) {
                                                if ($(this).attr('sel') == 1) {
                                                    if ($(this).attr('check') == 0) {
                                                        $(this).attr("sel", "0").removeClass("addstyle");
                                                    } else {
                                                        $(this).attr("sel", "0").addClass("addstyle");
                                                    };
                                                }
                                            });
                                            box.find(".showright").attr('first', 0);
                                        } else {
                                            box.find(".showleft").children("span").each(function(index, element) {
                                                if ($(this).attr('sel') == 1) {
                                                    that.mx.push($(this).attr('left'));
                                                    that.my.push($(this).attr('top'));
                                                    that.ms.push(0);
                                                    $(this).attr("check", "1");
                                                    $(this).attr("sel", "0");
                                                    that.pairl.push($(this).attr("pair"));
                                                }
                                            });
                                            box.find(".showright").children("span").each(function(index, element) {
                                                if ($(this).attr('sel') == 1) {
                                                    that.mx.push($(this).attr('left'));
                                                    that.my.push($(this).attr('top'));
                                                    that.ms.push(1);
                                                    $(this).attr("check", "1");
                                                    $(this).attr("sel", "0");
                                                    that.pairr.push($(this).attr("pair"));
                                                }
                                            });
                                            that.pair += 1;
                                            box.find(".showleft").attr('first', 0);
                                            box.find(".showright").attr('first', 0);
                                            that.strockline();
                                        };
                                    } else {
                                        box.find(".showleft").children("span").each(function(index, element) {
                                            if ($(this).attr('sel') == 1) {
                                                if ($(this).attr('check') == 0) {
                                                    $(this).attr("sel", "0").removeClass("addstyle");
                                                } else {
                                                    $(this).attr("sel", "0").addClass("addstyle");
                                                };
                                            }
                                        });
                                        box.find(".showleft").attr('first', 0);
                                        box.find(".showright").children("span").each(function(index, element) {
                                            if ($(this).attr('sel') == 1) {
                                                if ($(this).attr('check') == 0) {
                                                    $(this).attr("sel", "0").removeClass("addstyle");
                                                } else {
                                                    $(this).attr("sel", "0").addClass("addstyle");
                                                };
                                            }
                                        });
                                        box.find(".showright").attr('first', 0);
                                    };
                                } else {
                                    box.find(".showleft").children("span").each(function(index, element) {
                                        if ($(this).attr('check') == 0) {
                                            if ($(this).attr('sel') == 1) {
                                                $(this).attr("sel", "0").removeClass("addstyle");
                                            };
                                        } else {
                                            if ($(this).attr('sel') == 1) {
                                                $(this).attr("sel", "0").addClass("addstyle");
                                            };
                                        };
                                    });
                                    box.find(".showleft").attr('first', 0);
                                    box.find(".showright").children("span").each(function(index, element) {
                                        if ($(this).attr('check') == 0) {
                                            if ($(this).attr('sel') == 1) {
                                                $(this).attr("sel", "0").removeClass("addstyle");
                                            };
                                        } else {
                                            if ($(this).attr('sel') == 1) {
                                                $(this).attr("sel", "0").addClass("addstyle");
                                            };
                                        };
                                    });
                                    box.find(".showright").attr('first', 0);
                                };
                            } else {
                                box.find(".showleft").children("span").each(function(index, element) {
                                    if ($(this).attr('check') == 0) {
                                        if ($(this).attr('sel') == 1) {
                                            $(this).attr("sel", "0").removeClass("addstyle");
                                        };
                                    };
                                });
                                box.find(".showleft").attr('first', 0);
                                box.find(".showright").children("span").each(function(index, element) {
                                    if ($(this).attr('check') == 0) {
                                        if ($(this).attr('sel') == 1) {
                                            $(this).attr("sel", "0").removeClass("addstyle");
                                        };
                                    };
                                });
                                box.find(".showright").attr('first', 0);
                            };
                            that.clearbackline();
                            that.groupstate = false;
                        };
                        event.preventDefault();
                    }
                }
            });

            // canvas 追加2d画布
            that.context = that.canvasTag.getContext('2d'); //canvas追加2d画图
            // init 2d画布 虚拟绘制
            that.backcanvas = that.backcanvasTag.getContext('2d');

            //下载
            box.find(".downloadImageBtn").bind(that.touchend, function () {
                var myCanvas = box.find(".canvas")[0];
                var image = myCanvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
                window.location.href = image; //地址变为canvas图片路径,下载
            });

            //重置
            box.find(".resetCanvasBtn").bind(that.touchend, function () {
                that.clearline();
            });  

            //回退
            box.find(".goBackBtn").bind(that.touchend, function () {
                that.goBack();
            });
            //下一题 检查
            box.find(".submit").bind(that.touchend, function () {
                var msg = [];
                if(that.pairl.length == 0){return;}
                $.each(that.pairl, function(k, v) {
                    var lVal = $('.showleft span[pair="'+v+'"]').find('p').text();
                    var rVal = $('.showright span[pair="'+that.pairr[k]+'"]').find('p').text();
                    var lAnswer = eval(lVal.replace("=",""));
                    if(lAnswer != Number(rVal)){
                        msg.push("题目 "+lVal+rVal+" 做错了!");
                    }
                });
                if(msg.length>0){
                    document.getElementById("yihan").play();
                    alert(msg.join("\n"))
                }else{
                    document.getElementById("nizhenbang").play();
                    alert("全做对了,你真棒!")                   
                }
            });
            box.find(".initCalc").bind(that.touchend, function () {
                var num = $(this).attr('val');
                that.clearline();
                that.initialised = false;
                setTimeout(function() {
                    that.init($(".demo1"),num);
                }, 500);
            });                        
        }
    }
    setTimeout(function() {
        OAIndex.init($(".demo1"));
    }, 500);
});

需要完整代码的可以留言私信索取。

 

 

上一篇:input上传图片并预览


下一篇:JavaScript小数点后保留 X 位