Jcrop实现图片裁剪

功能需求 “在上传照片的时候能进行裁剪”

Jcrop是一个jQuery插件,它能为你的WEB应用程序快速简单地提供图片裁剪的功能。Jcrop官网,以下是Jcrop的一些特性:

  • 对所有图片均unobtrusively(无侵入的,保持DOM简洁)
  • 支持宽高比例锁定
  • 支持 minSize / maxSize设置
  • 支持改变选区或移 动选区时的回调(Callback)
  • 支持用键盘微调选区
  • 通过API创建互 动,比如动画效果
  • 支持CSS样式

Jcrop使用

引入插件

<script type="text/javascript" src="js/jquery-3.2.1.min.js"></script>  
<script type="text/javascript" src="js/jquery.Jcrop.js"></script>  

引入Jcrop的CSS样式

<link rel="stylesheet" href="css/jquery.Jcrop.css">  

例如想要实现如下效果,效果图:

html:基本结构

 <%-- 裁剪图片布局 --%>  
 <div class="jcrop_warpper">
    <div id="crop_image">  
        <div id="crop_image_top">  
            <h4>编辑图片</h4>  
        </div>  
        <div id="crop_image_content">  
            <img src="" alt="" id="JcropImage">  
            <!-- 预览 -->  
            <div id="preview-pane">  
                <div class="preview-container">  
                    <img src="" alt="" id="JcropPreviewImage">  
                </div>  
            </div>  
        </div>  
        <div id="crop_image_bottom">  
            <input class="btn" type="button" value="取消">  
            <input id="submitBtn" class="btn cut" type="button" value="确定">  
        </div>  
    </div>  
 </div>    

    <!-- 上传图片表单 -->  
    <form id="uploadForm" action="">  
        <div id="uploadImage">  
            ![](images/test.jpg)  
            <a href="javascript:;" class="addImage">  
                <span>上传图片</span>  
                <input id="imgFile" type="file" name="imgFile">  
            </a>  
        </div>  
    </form>  

js:当点击上传图片时,弹出图片选择框,选择图片之后会替换掉裁剪框内容。这里利用change方法,监听imgFile改变事件。

var width;  // 裁剪框的宽度
var height; // 裁剪框的高度  
var x;      // 裁剪框的起点x  
var y;      // 裁剪框的起点y
var jcrop_api;
var xsize = $('#preview-pane .preview-container').width();  // 获取预览窗格相关信息
var ysize = $('#preview-pane .preview-container').height();
var $pimg = $('#preview-pane .preview-container img');
var $preview = $('#preview-pane');
var boundx;
var boundy;

$('#imgFile').change(function(event) {
    // 根据这个 <input> 获取文件的 HTML5 js对象  
    var files = event.target.files, file;
    if (files && files.length > 0) {
        // 获取目前上传的文件 
        file = files[0];
        // Judge file type
        var fileName = file.name;
        var fileType = fileName.substr(fileName.lastIndexOf(".")).toUpperCase();
        if (fileType != ".BMP" && fileType != ".PNG" && fileType != ".JPG" && fileType != ".JPEG") {
            alert("please select image!");
            return false;
        }
        // 获取window的 URL工具  
        var URL = window.URL || window.webkitURL;
        // 通过 file生成目标 url  
        var imgURL = URL.createObjectURL(file);

        if (jcrop_api) {
            jcrop_api.destroy();
        }

        $('#JcropImage').attr('src', imgURL);
        $('#JcropPreviewImage').attr('src', imgURL);

        $('#JcropImage').Jcrop({
            setSelect: [ 0, 0, 2000, 2000 ],
            allowResize: true,
            allowSelect: false,
            onChange : updatePreview,
            onSelect : updatePreview,
            aspectRatio : xsize / ysize,
            boxWidth: 348,
            boxHeight: 324
        }, function() {
            // 使用API来获得真实的图像大小
            var bounds = this.getBounds();
            boundx = bounds[0];
            boundy = bounds[1];
            jcrop_api = this;
            // 预览进入jcrop容器css定位 
            $preview.appendTo(jcrop_api.ui.holder);
            updatePreview();
        });
    }
});

function updatePreview(c) {
    var jcropImage = $('#JcropImage').attr('src');
    var jcropPreviewImage = $('#JcropPreviewImage').attr('src');
    if (jcropImage != jcropPreviewImage) {
        $('#JcropPreviewImage').attr('src', jcropImage);
        $('#JcropPreviewImage').css('width', xsize);
        $('#JcropPreviewImage').css('height', '');
    }

    if (c != undefined){
        if (parseInt(c.w) > 0) {
            var rx = xsize / c.w;
            var ry = ysize / c.h;
            $pimg.css({
                width : Math.round(rx * boundx) + 'px',
                height : Math.round(ry * boundy) + 'px',
                marginLeft : '-' + Math.round(rx * c.x) + 'px',
                marginTop : '-' + Math.round(ry * c.y) + 'px'
            });
        }
        x = Math.round(c.x);
        y = Math.round(c.y);
        width = Math.round(c.w);
        height = Math.round(c.h);
    }
};

$('.cut').off('click').on('click', function() {
    var formData = new FormData();
    formData.append(nameSpace + 'file', $('#imgFile')[0].files[0]);
    formData.append(nameSpace + 'startX', x);
    formData.append(nameSpace + 'startY', y);
    formData.append(nameSpace + 'width', width);
    formData.append(nameSpace + 'height', height);
    formData.append(nameSpace + 'realW', Math.round(boundx));
    formData.append(nameSpace + 'realH', Math.round(boundy));
    $.ajax({
        // send ajax request
    })
});

 

.dialog-mask {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    left: 0;
    overflow: hidden;
    outline: 0;
    -webkit-overflow-scrolling: touch;
    background-color: rgb(0, 0, 0);
    filter: alpha(opacity=60);
    background-color: rgba(0, 0, 0, 0.6);
    z-index: 1001;
    width: 150%;
    display: none;
}

.jcrop_warpper {
    width: 148%;
    height: 148%;
    position: fixed;
    z-index: 1002;
    left: 14%;
    top: 18%;
    padding: 0% 77% 0% 0%;
    display: none;
}

#crop_image {
    float: left;
    width: 100%;
    background-color: #333;
    user-select: none;
    border: 1px solid #DEDEDE;
    -webkit-border-radius: 6px;
    -moz-border-radius: 6px;
    border-radius: 6px;
    -webkit-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
    box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
    display: none;
}

#crop_image_top,#crop_image_bottom {
    float: left;
    width: 100%;
    padding: 2%;
    background-color: white;
}

#crop_image_bottom {
    text-align: right;
}

#crop_image_bottom input {
    height: 30px;
    padding: 5px 15px;
    border-radius: 3px;
    border: none;
    margin-left: 20px;
    outline: none;
}

#submitBtn {
    color: white;
    cursor: pointer;
}

#crop_image_top h4 {
    margin: 0;
    padding: 0;
    font-weight: normal;
}

#crop_image_content {
    float: left;
    position: relative;
    text-align: center;
    width: 100%;
    margin: 3%;
    min-height: 200px;
    max-height: 400px;
}

.jcrop-holder {
    left: 23px;
}

.jcrop-holder #preview-pane {
    display: block;
    position: absolute;
    z-index: 2000;
    top: 0px;
    left: 475px;
    padding: 6px;
    border: 1px rgba(0, 0, 0, .4) solid;
    background-color: white;
    -webkit-border-radius: 6px;
    -moz-border-radius: 6px;
    border-radius: 6px;
    -webkit-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
    -moz-box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
    box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
}

/* The Javascript code will set the aspect ratio of the crop
   area based on the size of the thumbnail preview,
   specified here */
#preview-pane .preview-container {
    width: 348px;
    height: 162px;
    overflow: hidden;
}

#JcropPreviewImage {
    width: 348px;
}

后台:

public void cutImageAndImport(ResourceRequest request, ResourceResponse response) {
    //获取前台参数
    int x = *******;
    int y = *******;
    int width = *******;
    int height = *******;
    int realW = *******;
    int realH = *******;
    //将file对象转换成流
    InputStream in = uploadPortletRequest.getFileAsStream(Constants.FILE);

    //存储路径处理
    String fileName = this.postProcessFileNameBeforeSave(origionFileName);
    String filePath = httpServletRequest.getSession().getServletContext().getRealPath(Constants.UPLOAD_PATH);
    String imagePath = filePath + StringPool.FORWARD_SLASH + fileName;
    File file =new File(filePath);
    if (!file.exists() && !file.isDirectory()) {
        file.mkdir();
    }
    File imageFile = new File(filePath, fileName);
    //Cut image
    Boolean cutResult = OperateImageUtil.cutImage(imagePath, in, x, y, width, height, realW, realH);
}

//图片裁剪类
public class OperateImageUtil {
    public static Boolean cutImage(String imagePath, InputStream in, int x, int y, int width, int height, int realW, int realH) {
        Boolean result = Boolean.TRUE;
        try {
            BufferedImage bi = ImageIO.read(in);

            // Get image zoom out ratio, and calculate real cut size
            // 解决使用Jcrop剪切图片因图片太大导致精准度丢失的解决办法
            Double fileX = bi.getWidth() / (double) realW;
            Double fileY = bi.getHeight() / (double) realH;
            int newX =(int) (x * fileX);
            int newY =(int) (y * fileY);
            int newW =(int) (width * fileX);
            int newH =(int) (height * fileY);

            int srcWidth = bi.getWidth();
            int srcHeight = bi.getHeight();

            if (srcWidth > 0 && srcHeight > 0) {
                Image image = bi.getScaledInstance(srcWidth, srcHeight, Image.SCALE_DEFAULT);
                ImageFilter cropFilter = new CropImageFilter(newX, newY, newW, newH);
                Image img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter));
                BufferedImage tag = new BufferedImage(newW, newH, BufferedImage.TYPE_INT_RGB);
                Graphics g = tag.getGraphics();
                g.drawImage(img, 0, 0, newW, newH, null);
                g.dispose();
                ImageIO.write(tag, Constants.PNG, new File(imagePath));
            }
        } catch (Exception e) {
            result = Boolean.FALSE;
        }

        return result;
    }
}

//如果要下载裁剪后的图片
public void downloadImage(ResourceRequest request, ResourceResponse response) {
    // Step1: Gets parameters.
    String fileName = ParamUtil.getString(request, "fileName", StringPool.BLANK);

    HttpServletRequest httpServletRequest = PortalUtil.getOriginalServletRequest(PortalUtil.getHttpServletRequest(request));
    HttpServletResponse httpServletResponse = PortalUtil.getHttpServletResponse(response);
    //设置http response header "Content-Disposition" 为 attachment,浏览器会自动下载文件
    httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + fileName);
    String filePath = httpServletRequest.getSession().getServletContext().getRealPath("/upload");
    String imagePath = filePath + "/" + fileName;
    File file = new File(imagePath);

    // 使用Outputstream返回文件流
    byte[] buff = new byte[1024];
    BufferedInputStream bis = null;
    OutputStream os = null;
    try {
        os = httpServletResponse.getOutputStream();
        bis = new BufferedInputStream(new FileInputStream(file));
        int i = 0;
        while ((i = bis.read(buff)) != -1) {
            os.write(buff, 0, i);
            os.flush();
        }
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            bis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值