文档章节

【转载】基于JavaScript在线头像图片编辑前端后台实现

hosser
 hosser
发布于 2015/01/26 11:09
字数 1006
阅读 47
收藏 0

基于JavaScript在线头像图片编辑前端后台实现技术

maybe yes 发表于2014-12-12 10:58

原文链接 : http://blog.lmlphp.com/archives/32  来自 : LMLPHP后院

前端使用Jcrop实现预览和获取图片大小,选定位置等信息。关于Jcrop,项目地址在GITHUB上,它基于MIT开源协议。本人看了下项目的源代码,感觉作者蛮认真的。Jcrop做到了兼容IE系列和其他主流浏览器,非常稳定,让开发者不再为前端方面花费太多精力。加上本人不太喜欢Flash实现,纯JavaScript实现的功能效率会更高。由于时间比较仓促,代码没有过多的优化,有点乱,下面公布前端实现和服务端处理图片部分代码。

前端实现方式如下:

<link rel="stylesheet" href=".../jcrop/tapmodo-Jcrop-1902fbc/css/jquery.Jcrop.css">
<script src=".../jcrop/tapmodo-Jcrop-1902fbc/js/jquery.min.js"></script>
<script src=".../jcrop/tapmodo-Jcrop-1902fbc/js/jquery.Jcrop.js"></script>
<style>
#preview-pane{
    background-color: white;
    border: 1px solid rgba(0, 0, 0, 0.4);
    border-radius: 6px;
    box-shadow: 1px 1px 5px 2px rgba(0, 0, 0, 0.2);
    display: none;
    padding: 6px;
    position: absolute;
    right: -160px;
    top: 0;
    z-index: 2000;
}
#preview-pane .preview-container {
    height: 100px;
    overflow: hidden;
    width: 100px;
}
.cropdiv{
    background: none repeat scroll 0 0 #fff;
    border: 1px solid #ccc;
    border-radius: 5px;
    box-shadow: 0 20px 20px rgba(0, 0, 0, 0.3);
    height: auto;
    left: 200px;
    opacity: 0.9;
    position: absolute;
    top: 230px;
    width: 600px;
    z-index: 100;
    padding:10px;
}

.cropdiv .preinfo{
    float: right;
    left: 500px;
    position: absolute;
    top: 160px;
}
.cropdiv .title{
    font-size:14px;
    font-weight:bold;
    margin-bottom:10px;
}
.cropdiv .save{
    text-align:center;
}
.cropdiv .save a{
    background-color: #ff832b;
    border-radius: 4px;
    color: #fff;
    display: inline-block;
    height: 30px;
    padding:2px 5px;
    font-size:16px;
    margin:5px;
}
</style>
<script>
var startcrop = function( imgsrc ) {
    var jcrop_api, boundx, boundy, posinfo,
    imgsrc_rand = imgsrc + '?' + Math.round(Math.random() * 10000);

    // Grab some information about the preview pane    
    var $preview_html = 
        '<div id="preview-pane">'
            +'<div class="preview-container">'
            +'<img src="" class="jcrop-preview" alt="Preview">'
            +'</div>'
        +'</div>';
    
    $(document.body).append($preview_html);
    var $preview = $('#preview-pane'),
    $pcnt = $('#preview-pane .preview-container'),
    $pimg = $('#preview-pane .preview-container img'),

    xsize = $pcnt.width(),
    ysize = $pcnt.height();
    $pimg.attr('src',imgsrc_rand);
    
    var cropimgdiv = $('<div/>').addClass('cropdiv').css({"opacity":.9})
    .append(function(){
        return $('<div/>').append("<span>编辑头像</span>").addClass('title');;
    })
    .append( function(){
        return $('<img/>').attr( {"src":imgsrc + '?' + Math.round(Math.random() * 10000)
            ,"id":"cropimg"}) 
    })
    .append(function(){
        return $('<div/>').append( $("<a/>").html("保存头像").click(function(){
            $.ajax({
                type:'POST',
                url: 'handle crop url',
                dataType:'json',
                data:{ 'posinfo':posinfo, "boundx":boundx, "boundy":boundy },
                success:function( data ) {
                    // do something on success
                    cropimgdiv.remove();
                    $preview.remove();
                }
            });
        }) ).addClass('save');
    })
    .appendTo(document.body);
    
    if ($("#cropimg").get(0).naturalWidth > 400) {
        $("#cropimg").attr({"width":400});
        JcropRun();
    } else { // IE6/7/8
        var image = new Image()
        image.src = imgsrc_rand;
        image.onload = function(){
            if( image.width > 400){
                $("#cropimg").attr({"width":400});
            }
            JcropRun();
        };
    } 

    function showCoords(c)
    {
        /* variables can be accessed here as
        // c.x, c.y, c.x2, c.y2, c.w, c.h*/
        posinfo = c;
        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'
            });
        }
    };
    
    var JcropRun = function(){
        $('#cropimg').Jcrop({
            onSelect:    showCoords,
            bgColor:     'black',
            bgOpacity:   .4,
            setSelect:   [ 100, 100, 0, 0 ],
            minSize:   [ 100, 100 ],
            aspectRatio: xsize / ysize
        },function(){
            // Use the API to get the real image size
            var bounds = this.getBounds();
            boundx = bounds[0];
            boundy = bounds[1];
            // Store the API in the jcrop_api variable
            jcrop_api = this;
            $preview.css({"display":"block"});
            // Move the preview into the jcrop container for css positioning
            $preview.appendTo(jcrop_api.ui.holder);
        });
    }
};
</script>

imagecropper方法在网上找的,写的比较差,以后有时间会整理下代码。后台图片处理方式如下:

<?php 

function imagecropper($source_path, $target_width, $target_height)
{
    $source_info   = getimagesize($source_path);
    $source_width  = $source_info[0];
    $source_height = $source_info[1];
    $source_mime   = $source_info['mime'];
    $source_ratio  = $source_height / $source_width;
    $target_ratio  = $target_height / $target_width;

    // 源图过高
    if ($source_ratio > $target_ratio)
    {
        $cropped_width  = $source_width;
        $cropped_height = $source_width * $target_ratio;
        $source_x = 0;
        $source_y = ($source_height - $cropped_height) / 2;
    }
    // 源图过宽
    elseif ($source_ratio < $target_ratio)
    {
        $cropped_width  = $source_height / $target_ratio;
        $cropped_height = $source_height;
        $source_x = ($source_width - $cropped_width) / 2;
        $source_y = 0;
    }
    // 源图适中
    else
    {
        $cropped_width  = $source_width;
        $cropped_height = $source_height;
        $source_x = 0;
        $source_y = 0;
    }

    switch ($source_mime)
    {
        case 'image/gif':
            $source_image = imagecreatefromgif($source_path);
            break;

        case 'image/jpeg':
            $source_image = imagecreatefromjpeg($source_path);
            break;

        case 'image/png':
            $source_image = imagecreatefrompng($source_path);
            break;

        default:
            return false;
            break;
    }

    $target_image  = imagecreatetruecolor($target_width, $target_height);
    $cropped_image = imagecreatetruecolor($cropped_width, $cropped_height);

    // 裁剪
    imagecopy($cropped_image, $source_image, 0, 0, $source_x, $source_y, $cropped_width, $cropped_height);
    // 缩放
    imagecopyresampled($target_image, $cropped_image, 0, 0, 0, 0, $target_width, $target_height, $cropped_width, $cropped_height);

    /* header('Content-Type: image/jpeg'); */
    ob_start();
    imagejpeg( $target_image );
    return ob_get_clean();
    /* imagedestroy($source_image);
    imagedestroy($target_image);
    imagedestroy($cropped_image);
    exit; */
}

$boundx = $_POST['boundx'];
$boundy = $_POST['boundy'];
$posinfo = $_POST['posinfo'];

$realimg = '用户上传后的原图地址';
$resizeimg = imagecropper($realimg, $boundx, $boundy);
file_put_contents($realimg, $resizeimg);
/* 上面完成了图片的大小压缩,下面将图片进行裁剪 */
$source_info   = getimagesize($realimg);
$source_mime   = $source_info['mime'];
switch ($source_mime)
{
    case 'image/gif':
        $source_image = imagecreatefromgif($realimg);
        break;

    case 'image/jpeg':
        $source_image = imagecreatefromjpeg($realimg);
        break;

    case 'image/png':
        $source_image = imagecreatefrompng($realimg);
        break;

    default:
        return false;
        break;
}
$target_image  = imagecreatetruecolor($posinfo['w'], $posinfo['h']);
$cropped_image = imagecreatetruecolor($posinfo['w'], $posinfo['h']);
imagecopy( $cropped_image, $source_image, 0, 0, $posinfo['x'], $posinfo['y'], $posinfo['w'], $posinfo['h'] );
imagecopyresampled($target_image, $cropped_image, 0, 0, 0, 0, $posinfo['w'], $posinfo['h'], $posinfo['w'], $posinfo['h']);
ob_start();
switch( $source_mime ){
    case 'image/gif':
        imagegif( $target_image );
        break;
    case 'image/jpeg':
        imagejpeg( $target_image );
        break;
    case 'image/png':
        imagepng( $target_image );
        break;
    default:
        return false;
}

file_put_contents($realimg, ob_get_clean() );

附上运行截图:

JavaScript头像图片编辑运行图-LMLPHP后院

JavaScript头像图片编辑运行图-LMLPHP后院

阅(38)评(0)查看评论


本文转载自:http://blog.lmlphp.com/archives/32

hosser
粉丝 194
博文 78
码字总数 4614
作品 3
徐汇
私信 提问
关于OsChina头像上传问题的前端一点小优化建议

oschina也是我经常逛的技术网站,一直欣赏中。无意间看到头像上传这块,打开头像上传页面,直接点击上传就直接去请求服务器, 不管有没有选择图片,虽然说后端处理的很好,但是我觉得前端加点...

quyf
2014/01/04
250
2
吐槽下公司的WEB前端

1、不需要懂数据库,业务逻辑什么的,不想事! 给我的页面,各种逻辑错误,完全不正确,漏洞百出,突然蹦出来给编辑页,入口在哪都没有。 各种HTML标签不一样,导致根本无法循环数据,搞笑。...

开源中国首席段子手
2016/05/01
1K
2
StartBBS V1.1.1 发布,开源轻量社区系统

StartBBS(起点开源社区系统)是一个基于CI MVC框架开发的PHP新型社区系统,她轻量小巧, 简单易用,强大高效的开源论坛系统。又简称”SB(烧饼bbs)” 此次亮点:增加组户组及权限, 增加版主,...

startbbs
2013/08/25
1K
5
JS杂谈系列-常用开发工具介绍

一、分类比较齐全的js效果下载地址 1.jq插件库(各类jq插件,收费下载,大家可以想个办法免费的) 地址: http://www.jq22.com/ 2.开源中国插件分类 地址:http://www.oschina.net/project/...

透笔度
2015/08/21
0
0
10个程序员最喜欢的 HTML和CSS 等在线代码编辑器

一般软件开发中必备的一样工具就是代码编辑器。传统的代码编辑器一般都是以软件安装包的形式安装到电脑里面,代码编辑保存后一般也是通过ftp或者svn等工具提交到服务器的(当然,像.NET开发中...

欲思
2014/09/03
938
0

没有更多内容

加载失败,请刷新页面

加载更多

数据库

数据库架构 数据库架构可以分为存储文件系统和程序实例两大块,而程序实例根据不同的功能又可以分为如下小模块。 1550644570798 索引模块 常见的问题有: 为什么要使用索引 什么样的信息能成...

一只小青蛙
今天
5
0
PHP常用经典算法实现

<? //-------------------- // 基本数据结构算法 //-------------------- //二分查找(数组里查找某个元素) function bin_sch($array, $low, $high, $k){ if ( $low <= $high){ $mid = int......

半缘修道半缘君丶
昨天
5
0
GIL 已经被杀死了么?

本文原创并首发于公众号【Python猫】,未经授权,请勿转载。 原文地址:https://mp.weixin.qq.com/s/8KvQemz0SWq2hw-2aBPv2Q 花下猫语: Python 中最广为人诟病的一点,大概就是它的 GIL 了。...

豌豆花下猫
昨天
5
0
git commit message form

commit message一般包括3部分:Header、Body、Footer。 <type>(<scope>):<subject>blank line<body>blank line<footer> header是必需的,body、footer可以省略。 header中type、subject......

ninjaFrog
昨天
5
0
聊聊Elasticsearch的CircuitBreakerService

序 本文主要研究一下Elasticsearch的CircuitBreakerService CircuitBreakerService elasticsearch-7.0.1/server/src/main/java/org/elasticsearch/indices/breaker/CircuitBreakerService.ja......

go4it
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部