因项目功能需要,最近几天开始研究html5,实现对上传的试题图片进行批改对错,批改完保存批改后的图片功能。主要涉及到html5 canvas画布和js的相关知识点。
参考:http://www.xwcms.net/js/qttx/26316.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('img:"' + obj[i].img + '", top:"' + obj[i].top + '", left:"' + obj[i].left + '"');
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(nvar 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='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 = $("").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("");
}
},
//添加签章
add: function () {
handle.btnAddToggle();
var sign = $("").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 = $("").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;
}