因項目功能需要,最近幾天開始研究html5,實現對上傳的試題圖片進行批改對錯,批改完保存批改後的圖片功能。主要涉及到html5 canvas畫布和js的相關知識點。
參考:http://www.xwcms.net/js/qttx/26316.html 作者寫的功能,修改後能保存蓋章後的圖片。
(圖片略醜,不要嫌棄)
效果圖:
點擊保存後在下面顯示的效果圖:
頁面代碼:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>測試</title>
<link href="css/zsign.css" rel="stylesheet" type="text/css" />
<script src="js/jquery-2.2.1.min.js" type="text/javascript"></script>
<script src="js/zsign.js" type="text/javascript"></script>
</head>
<body>
<div id="test" style="position: relative; width: 80%; height: 500px; border: 1px solid red;
margin: 100px auto">
<img src="img/shiti.png" />
</div>
<div id="imgBox" style="width:1000px;height:800px;"> </div>
<ul id="msg"></ul>
<script>
var data = []; //吧試題圖片和批改圖片存儲
var a = $("#test").zSign({
img: 'img/true.png',
wrongImg: 'img/false.png',
isPercentage: true,
callBack: function(obj) {
var dataobj2={};
dataobj2["img"] = "img/shiti.png";
dataobj2["top"] = 0;
dataobj2["left"] = 0;
data.push(dataobj2);
//存儲批改的圖片及位置
var html = [];
for (var i = 0; i < obj.length; i++) {
html.push('<li>img:"' + obj[i].img + '", top:"' + obj[i].top + '", left:"' + obj[i].left + '"</li>');
var imgurl = obj[i].img.match(/\([^\)]+\)/g)[0];
imgurl = imgurl.substring(2, imgurl.length - 2);
var left = obj[i].left.substring(0, obj[i].left.length - 2);
var top = obj[i].top.substring(0, obj[i].top.length - 2);
var dataobj={};
dataobj["img"] = imgurl;
dataobj["top"] = parseFloat(top);
dataobj["left"] = parseFloat(left);
data.push(dataobj);
}
showImg();
$('#msg').html(html.join(''));
}
});
//合成最後的批改圖片
function showImg(){
var base64=[];
var Mycanvas=document.createElement("canvas"),
ct=Mycanvas.getContext("2d"),
len=data.length;
Mycanvas.width=600;
Mycanvas.height=400;
ct.rect(0,0,Mycanvas.width,Mycanvas.height);
ct.fillStyle='#fff';
ct.fill();
function draw(n){
if(n<len){
var img=new Image;
img.crossOrigin = 'Anonymous'; //解決跨域
img.src=data[n].img;
img.onload=function(){
ct.drawImage(img,data[n].left,data[n].top);
draw(n+1);
}
}
else{
base64.push(Mycanvas.toDataURL("image/png"));
document.getElementById("imgBox").innerHTML='<img src="'+base64[0]+'">';
saveAsLocalImage (Mycanvas);
}
}
draw(0)
}
//吧圖片下載本地
function saveAsLocalImage (canvas) {
var image = canvas.toDataURL("image/png").replace("image/png", "image/octet-stream");
window.location.href=image;
}
</script>
</body>
</html>
2、其中需要編寫的css樣式文件:
.zsign .panel
{
position: absolute;
top:20px;
right:50px;
}
.zsign .btn
{
display: inline-block;
padding: 4px 10px 4px;
margin-bottom: 0;
font-size: 15px;
line-height: 18px;
color: #333;
text-align: center;
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
vertical-align: middle;
background-color: whiteSmoke;
background-image: -webkit-gradient(linear, 0 0, 0 100%, from(white), to(#E6E6E6));
background-repeat: repeat-x;
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
border: 1px solid #CCC;
border-bottom-color: #B3B3B3;
-webkit-border-radius: 4px;
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
cursor: pointer;
-webkit-user-select: none;
}
.zsign .btn:hover
{
color: #333;
text-decoration: none;
background-color: #E6E6E6;
background-position: 0 -15px;
-webkit-transition: background-position 0.1s linear;
}
.zsign .btn[disabled]
{
cursor: default;
background-image: none;
background-color: #E6E6E6;
opacity: 0.65;
filter: alpha(opacity=65);
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
}
.zsign .btn.add
{
margin-right:8px;
}
.zsign .btn.wrong
{
margin-right:8px;
}
.zsign .cursor
{
cursor: none;
}
.zsign .show
{
display: block;
}
.zsign .hide
{
display: none;
}
.zsign .sign
{
position: absolute;
top:20px;
left:20px;
cursor: move;
border: 1px dashed #ccc;
background-size: contain;
background-position: center;
background-repeat: no-repeat;
}
.zsign .sign.ok
{
cursor: default;
border-color:transparent;
}
.zsign .sign .btn
{
padding: 2px 6px;
font-size: 11px;
line-height: 14px;
position: absolute;
}
.zsign .sign .btn.del
{
bottom: 4px;
right: 4px;
}
.zsign .sign .btn.ok
{
bottom: 4px;
right: 50px;
}
3、對對號和錯號圖片的移動、保存按鈕的返回等功能js的編寫
$.fn.zSign = function (options) {
var _s = $.extend({
img: '', //圖片地址
wrongImg:'',
width: 100, //簽章圖片大小
height: 100,
btnPanel: true, //是否開啓按鈕面板,若按鈕面板不滿足需求可以關閉後通過返回的handle對象直接調用方法
callBack: null, //保存按鈕回調函數
list: null, //初始化簽章,參數格式參照callBack回調函數返回的數據格式
isPercentage: false //返回結果中的left、top是否以百分比顯示,若夫容器是自適應佈局推薦
}, options || {});
var _parent = $(this).addClass('zsign'), _pw = _parent.width(), _ph = _parent.height();
var range = {
minX: 8,
minY: 8,
maxX: _pw - _s.width - 2, //扣去2個邊框1px
maxY: _ph - _s.height - 2
};
//按鈕面板
var _btnPanel = $("<div class='panel' ><button class='btn add' >對</button><button class='btn wrong' >錯</button><button class='btn save'>保 存</button></div>").appendTo(_parent);
_btnPanel.css('display', _s.btnPanel ? 'block' : 'none');
//添加
var _add = $('.add', _btnPanel).click(function (e) {
handle.add();
});
//批錯
var _wrong= $('.wrong', _btnPanel).click(function (e) {
handle.wrong();
});
//保存
$('.save', _btnPanel).click(function () {
handle.save();
});
if (_s.list) {
handle.init(_s.list);
}
var handle = {
list: [],
//初始化簽章
init: function (list) {
handle.list = [];
$('.sign', _parent).remove();
for (var i = 0; i < list.length; i++) {
var item = list[i];
_parent.append("<div class='sign ok' style='height:" + _s.height + "px;width:" + _s.width + "px;background-image:" + item.img + ";top:" + item.top + ";left:" + item.left + "'></div>");
}
},
//添加簽章
add: function () {
handle.btnAddToggle();
var sign = $("<div class='sign' style='height:" + _s.height + "px;width:" + _s.width + "px;background-image:url(" + _s.img + ");'><button class='btn ok' >確定</button><button class='btn del' >刪除</button></div>").appendTo(_parent);
$('.ok', sign).click(function () {
//確定
handle.sign(sign);
});
$('.del', sign).click(function () {
//刪除
handle.del(sign);
});
handle.move(sign);
},
//添加錯號
wrong: function () {
handle.btnAddToggle();
var sign = $("<div class='sign' style='height:" + _s.height + "px;width:" + _s.width + "px;background-image:url(" + _s.wrongImg + ");'><button class='btn ok' >確定</button><button class='btn del' >刪除</button></div>").appendTo(_parent);
$('.ok', sign).click(function () {
handle.sign(sign);
});
$('.del', sign).click(function () {
handle.del(sign);
});
handle.move(sign);
},
//確定
sign: function (obj) {
obj.addClass('ok').off('mousedown').find('.btn').css('display', 'none');
handle.btnAddToggle();
handle.list.push({ img: obj.css('background-image') + "", top: obj.css('top'), left: obj.css('left')});
},
//刪除
del: function (obj) {
obj.remove();
handle.btnAddToggle();
},
//移動
move: function (obj) {
//綁定移動事件
obj.on('mousedown', function (e) {
obj.data('x', e.clientX);
obj.data('y', e.clientY);
var position = obj.position();
$(document).on('mousemove', function (e1) {
var x = e1.clientX - obj.data('x') + position.left;
var y = e1.clientY - obj.data('y') + position.top;
x = x < range.minX ? range.minX : x;
x = x > range.maxX ? range.maxX : x;
y = y < range.minY ? range.minY : y;
y = y > range.maxY ? range.maxY : y;
obj.css({ left: x, top: y });
}).on('mouseup', function () {
$(this).off('mousemove').off('mouseup');
});
});
},
//保存
save: function () {
var r = true;
if ($('.sign:not(.ok)', _parent).length != 0) {
if (!confirm("未點擊確認的簽章將被移除,確定保存嗎?")) {
r = false;
}
}
if (r) {
//刪除未確定位置的簽章
$('.sign:not(.ok)', _parent).remove();
_btnPanel.remove();
if (_s.callBack) {
if (_s.isPercentage) {
for (var i = 0; i < handle.list.length; i++) {
var item = handle.list[i];
/*item.top = parseInt(item.top) / _ph * 100 + '%';
item.left = parseInt(item.left) / _pw * 100 + '%'; */
}
} else {
tmp = handle.list;
}
_s.callBack.call(this, handle.list);
}
}
},
//蓋章按鈕的狀態切換
btnAddToggle: function () {
var disabled = _add.attr('disabled');
if (disabled) {
//判斷是否有未確定的簽章,若有則不切換
if ($('.sign:not(.ok)', _parent).length == 0) {
_add.removeAttr('disabled');
}
} else {
_add.attr('disabled', 'disabled');
}
},
//返回參數列表,可以在外部直接修改
s: _s,
//簽章移動範圍
range: range
}
return handle;
}