接上期《前端应用 - 实现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);
});
需要完整代码的可以留言私信索取。