html5实现对试题图片批改效果,类似盖章效果

因项目功能需要,最近几天开始研究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;  
}  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章