【移动端】实现相册的上传和缩放裁剪

简介: 做项目时,在移动端,需要实现用户相册图片的上传,并对图片进行缩放裁剪的功能。下面说一下实现流程。

前言

做项目时,在移动端,需要实现用户相册图片的上传,并对图片进行缩放裁剪的功能。下面说一下实现流程。

在这里插入图片描述

图片上传

HTML5 支持从 input[type=file] 元素中直接获取文件信息,也可以读取文件内容。我们用下面代码就可以实现:

  <label for="input" class="btn btn-danger" id="">
           <span>选择图片</span>
           <input type="file" id="input" class="sr-only">
  </label>

读取文件,并生成 Image 元素

这一步就需要用到 FileReader 了,这个类是专门用来读取本地文件的。纯文本或者二进制都可以读取,但是本地文件必须是经过用户允许才能读取,也就是说用户要在input[type=file]中选择了这个文件,你才能读取到它。

通过 FileReader 我们可以将图片文件转化成 DataURL,就是以 data:image/png;base64, 开头的一种URL,然后可以直接放在 image.src 里,这样本地图片就显示出来了。

<script>
 var crop = function () {
        var $image = $('#photo');
        var $target = $('#result');
        $image.cropper('getCroppedCanvas', {
            width: 300, // 裁剪后的长宽
            height: 300
        }).toBlob(function (blob) {
            // 裁剪后将图片放到指定标签
            $target.attr('src', URL.createObjectURL(blob));
        });
    }
 </script>

Image 就是在 html 里的 <img> 标签,所以可以直接插入到文档流里。

获取裁剪坐标

这一步没啥好说的,实现的方法也很多,这里需要使用缩放功能,所以使用纵横比的方式:

<script>
 var options = {
            aspectRatio: 1, // 纵横比
            viewMode: 2,
            preview: '.img-preview' // 预览图的class名
        };
</script>

裁剪图片

裁剪图片使用 cropper插件

<script>
var crop = function () {
    var $image = $('#photo');
    var $target = $('#result');
    $image.cropper('getCroppedCanvas', {
        width: 300, // 裁剪后的长宽
        height: 300
    }).toBlob(function (blob) {
        // 裁剪后将图片放到指定标签
        $target.attr('src', URL.createObjectURL(blob));
    });
}
</script>

图片上传

通过ajax 即可上传给后台

完整代码

CSS

<head>
    <meta charset="UTF-8">
    <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
    <title>移动端图片上传</title>
    <link href="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.css" rel="stylesheet">
    <link href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">

    <style>
        .row {
            margin-bottom: 5px;
        }

        #photo {
            max-width: 100%;
        }

        .img-preview {
            width: 100px;
            height: 100px;
            overflow: hidden;

        }

        button {
            margin-top: 10px;
        }

        #result {
            width: 150px;
            height: 150px;
        }
    </style>
</head>

Body

<body>
<div class="container">
    <div class="row">
        <div class="col-sm-12 text-center">
            <label for="input" class="btn btn-danger" id="">
                <span>选择图片</span>
                <input type="file" id="input" class="sr-only">
            </label>
        </div>
    </div>
    <div class="row">
        <div class="col-sm-6 col-sm-offset-2">
            <img src="" id="photo">
        </div>
        <div class="col-sm-2">
            <div>
                <p>
                    预览(100*100):
                </p>
                <div class="img-preview">
                </div>
            </div>
            <button class="btn btn-primary" onclick="crop()">裁剪图片</button>
            <div>
                <br/>
                <p>
                    结果:
                </p>
                <img src="" alt="裁剪结果" id="result">
            </div>
        </div>
    </div>
</div>

</body>

JS

<!-- Scripts -->
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/cropper/3.1.3/cropper.min.js"></script>
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script>
    // 修改自官方demo的js
    var initCropper = function (img, input) {
        var $image = img;
        var options = {
            aspectRatio: 1, // 纵横比
            viewMode: 2,
            preview: '.img-preview' // 预览图的class名
        };
        $image.cropper(options);
        var $inputImage = input;
        var uploadedImageURL;
        if (URL) {
            // 给input添加监听
            $inputImage.change(function () {
                var files = this.files;
                var file;
                if (!$image.data('cropper')) {
                    return;
                }
                if (files && files.length) {
                    file = files[0];
                    // 判断是否是图像文件
                    if (/^image\/\w+$/.test(file.type)) {
                        // 如果URL已存在就先释放
                        if (uploadedImageURL) {
                            URL.revokeObjectURL(uploadedImageURL);
                        }
                        uploadedImageURL = URL.createObjectURL(file);
                        // 销毁cropper后更改src属性再重新创建cropper
                        $image.cropper('destroy').attr('src', uploadedImageURL).cropper(options);
                        $inputImage.val('');
                    } else {
                        window.alert('请选择一个图像文件!');
                    }
                }
            });
        } else {
            $inputImage.prop('disabled', true).addClass('disabled');
        }
    }
    var crop = function () {
        var $image = $('#photo');
        var $target = $('#result');
        $image.cropper('getCroppedCanvas', {
            width: 300, // 裁剪后的长宽
            height: 300
        }).toBlob(function (blob) {
            // 裁剪后将图片放到指定标签
            $target.attr('src', URL.createObjectURL(blob));
        });
    }
    $(function () {
        initCropper($('#photo'), $('#input'));
    });
</script>
相关文章
|
10月前
|
关系型数据库 Linux PHP
开源站群服务器方案:构建高效流量矩阵的全攻略
正在寻找高性价比、可控性强且功能强大的站群解决方案?小编将深度解析开源站群服务器方案,从核心优势、主流工具选型到部署实践,助您构建稳定、高效的站群流量体系。
|
10月前
|
安全 Linux 网络安全
Metasploit Framework 6.4.88 (macOS, Linux, Windows) - 开源渗透测试框架
Metasploit Framework 6.4.88 (macOS, Linux, Windows) - 开源渗透测试框架
702 0
|
缓存 前端开发 JavaScript
前端开发的必修课:如何让你的网页在弱网环境下依然流畅运行?
【10月更文挑战第30天】随着移动互联网的普及,弱网环境下的网页性能优化变得尤为重要。本文详细介绍了如何通过了解网络状况、优化资源加载、减少HTTP请求、调整弱网参数和代码优化等方法,提升网页在弱网环境下的加载速度和流畅性,从而改善用户体验。
965 4
质数
【10月更文挑战第22天】质数。
962 67
|
JavaScript
Vue2使用v-model封装ElementUI日期组件(实现开始时间和结束时间的校验,禁选)
本文介绍了如何在Vue2中使用v-model封装ElementUI日期组件,并实现开始时间和结束时间的校验,包括禁选当前时间之后的时间。文章提供了详细的组件代码和页面使用示例,并解释了如何通过props传递参数以及如何监听和处理日期选择的变化。
740 2
|
人工智能 自然语言处理 搜索推荐
小米实测:Deepseek——你的私人旅游攻略定制专家!
大家好,我是小米,一个31岁的技术爱好者。今天分享如何用Deepseek规划完美旅行。Deepseek能快速整合信息、提供个性化推荐,省时省力,并支持实时问答。从目的地选择到行程规划,再到预订机票住宿和旅行中的实时帮助,它都能提供强大支持。希望今天的分享能帮到你,期待你用Deepseek规划出属于自己的精彩旅程!如果你觉得有用,欢迎点赞、转发并关注我的微信公众号“软件求生”,获取更多技术干货。
1256 8
|
负载均衡 应用服务中间件 Nacos
最全解决:微服务之间调用出现Load balancer does not have available server for client
最全解决:微服务之间调用出现Load balancer does not have available server for client
4162 1
最全解决:微服务之间调用出现Load balancer does not have available server for client
|
数据可视化 数据库
通义灵码个人版新功能最佳实践测评
作为一名软件开发工程师,我使用通义灵码个人版的@workspace和@terminal功能,快速熟悉新的电商项目代码并实现新功能,效率提升了约30%。通过自动识别项目结构、代码分析、智能注释和自动补全等功能,大幅减少了查找资料和调试的时间,使开发流程更加顺畅,专注于业务逻辑实现。
546 1
|
JSON 小程序 JavaScript
微信小程序-vant-weapp日期选择器的使用(年月日时分)
微信小程序-vant-weapp日期选择器的使用(年月日时分)
752 0