DCloud_Android_ST
DCloud_Android_ST
  • 发布:2015-08-03 17:54
  • 更新:2020-01-13 16:58
  • 阅读:22005

Native.js调用系统裁剪图片、头像裁剪-Android

分类:Native.js

虽然HTML5+规范提供了图像裁剪api,http://html5plus.org/doc/zh_cn/zip.html
但仍有开发者希望可以调用Android的系统api裁剪图片。
下面的代码是Native.js实现此功能,调用相册获取图片后,通过调用系统API进行裁剪 。
该方式是一种可视操作来剪裁的,区别于5+规范中的compressImage,compressImage是无界面操作,但稳定性好!
而调用系统API可视化进行剪裁稳定性较差,有些手机不支持ACTION_PICK方式进行API调用裁剪!
应一些开发者的要求这里贴出代码,有问题直接咨询谢谢。

                var IMAGE_UNSPECIFIED = "image/*";  
                var PHOTOZOOM = 2; // 获取完图片返回key  
                var PHOTOLAT = 1; // 剪裁完毕后返回key  
                var main = plus.android.runtimeMainActivity();  
                var Intent = plus.android.importClass("android.content.Intent");  
                var MediaStore = plus.android.importClass("android.provider.MediaStore");  
                var File = plus.android.importClass("java.io.File");  
                var Uri = plus.android.importClass("android.net.Uri");  
                var intent = new Intent(Intent.ACTION_PICK, null);  
                intent.setDataAndType(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, IMAGE_UNSPECIFIED);  
                main.startActivityForResult(intent, PHOTOZOOM);  
                main.onActivityResult = function(requestCode, resultCode, data) {  
                    var outPutPath = plus.io.convertLocalFileSystemURL("__downloads/5566.jpg");  
                    if (PHOTOZOOM == requestCode) {  
                        var file = new File(outPutPath);  
                        // 输出目录uri  
                        var outPutUri = Uri.fromFile(file);  
                        plus.android.importClass(data);  
                        var uri = data.getData();  
                        var cropIntent = new Intent("com.android.camera.action.CROP");  
                        cropIntent.setDataAndType(uri, IMAGE_UNSPECIFIED);  
                        // 截图完毕后 输出目录  
                        cropIntent.putExtra(MediaStore.EXTRA_OUTPUT, outPutUri);  
                        cropIntent.putExtra("crop", "true");  
                        // aspectX aspectY 是宽高的比例  
                        cropIntent.putExtra("aspectX", 1);  
                        cropIntent.putExtra("aspectY", 1);  
                        // outputX outputY 是裁剪图片宽高  
                        cropIntent.putExtra("outputX", 64);  
                        cropIntent.putExtra("outputY", 64);  
                        cropIntent.putExtra("return-data", true);  
                        main.startActivityForResult(cropIntent, PHOTOLAT);  
                    } else if (requestCode == PHOTOLAT) {  
                        // 判断 剪裁完后的图片输出是否存在  
                        var file = new File(outPutPath);  
                        var a = file.exists();  
                        alert(a);  
                    }  
                };

关于图片压缩的多种方案及对比,可以参考这里http://ask.dcloud.net.cn/article/123

2015-08-03 17:54 2 条评论 负责人:无 分享
已邀请:
天才书生

天才书生

大坑啊,竟然没人发现?

var outPutPath = plus.io.convertLocalFileSystemURL("_www/5566.jpg");
这句要放到onActivityResult最上面,方法体外或在方法体内的第一句,不然第二次回调的时候,根本找不到outPutPath这个变量

wenju

wenju - https://www.mescroll.com -- 精致的下拉刷新和上拉加载组件

来得正是需要的 我来补充几点:

1.如果需要自由裁切,不设置1:1正方形比例,那么可去掉aspectX和aspectY的设置,

2.如果设置的输出尺寸比较大,比如outputX=640 那有的手机返回不了数据,可把return-data设置成false;

  1. 我的项目是要求用户上传产品图,尺寸最少640px,高度不限;那么不能设置1:1比例,而且outputX outputY 是必须设置的,不然保存不了;我是这么做的outputX=640; 而outputY=1280//尽量设置高一点,一般图片不会超过640:1280的这个比例

  2. 避免黑边的出现,还需设置intent.putExtra("scale", true);intent.putExtra("scaleUpIfNeeded", true);

alongSelf

alongSelf

var outPutPath = plus.io.convertLocalFileSystemURL("_www/5566.jpg");
最好换成
var outPutPath = plus.io.convertLocalFileSystemURL("_downloads/image/5566.jpg");

因为打包之后 _www目录是只读的。

stock2

stock2

js 稳定性 速度肯定跟不上的. 类似之前的压缩图片, 小的而且越压越大的. 大的压缩效果 ... 哎.不说了
还好官网出了, 压缩图片 .非常好.
现在希望出个 能拖拉的裁剪的功能. 呵呵

stock2

stock2

测试了,效果很不错. 输出时 var a = file.exists(); alert(a);
为null
我查看了文件,是存在的. 哪里错误了? 复制的代码 谢谢

  • Funk

    outPutPath设置成全局变量就好了

    2015-08-14 12:27

  • stock2

    太感谢了 .按照你的指点,可以了.

    2015-08-17 08:50

  • 炸鸡排超人

    .....你逗我

    2015-09-11 11:18

  • 趴趴熊

    回复 stock2:你是怎么,调好的,我的alert(a)是false

    2015-12-10 16:04

  • stock2

    @117970 根据楼上的outPutPath设置成全局变量 就好了.

    2015-12-10 18:29

  • sheep子涵

    怎么弄啊,设置了全局,还是,调好的,我的alert(a)是false

    2016-08-25 16:45

  • b***@sina.cn

    我的跟你问题一样。设置了全局,也是返回false。请问怎么解决的

    2017-03-22 17:53

wenju

wenju - https://www.mescroll.com -- 精致的下拉刷新和上拉加载组件

修正一下我之前补充的:
如果要自由裁切,不指定比例,
则aspectX,aspectY,outputX outputY都无需设置

如果X设置了则Y必须设置 否则保存不了

  • Funk

    我想问一下 你有做拍照裁剪吗? 这段代码是把相册和裁剪和一块了 我试了几次没把他们分开,表示安卓的东西不是很懂……

    2015-08-18 12:34

  • wenju

    回复 Funk:var uri = data.getData(); 把这个uri换成拍照回来的uri即可

    2015-08-18 14:24

  • wenju

    回复 Funk:Android的裁切代码:


    /**



    • 裁切图片,如果要自由裁切则aspect和output都不需设置

      /

      public static void cropImage(Activity activity, Uri uri, String outPath,

      int outputX, int outputY, int requestCode, int aspectX, int aspectY) {

      String path = UriPathUtil.getPath(activity, uri);

      Uri mUril = UriPathUtil.getImageContentUri(activity, new File(path));

      if (mUril != null) {

      uri = mUril;

      }

      // 裁剪图片意图

      Intent intent = new Intent("com.android.camera.action.CROP");

      intent.setDataAndType(uri, "image/
      ");

      intent.putExtra("crop", "true");

      // 裁剪框的比例

      if (aspectX>0&&aspectY>0) {

      intent.putExtra("aspectX", aspectX);

      intent.putExtra("aspectY", aspectY);

      }

      // 裁剪后输出图片的尺寸大小

      if(outputX>0&&outputY>0){

      intent.putExtra("outputX", outputX);

      intent.putExtra("outputY", outputY);

      }

      // 去黑边

      intent.putExtra("scale", true);

      intent.putExtra("scaleUpIfNeeded", true);

      // 图片格式

      intent.putExtra("outputFormat", "JPEG");

      intent.putExtra("noFaceDetection", true);

      // 裁切大图

      intent.putExtra("return-data", false);

      intent.putExtra(MediaStore.EXTRA_OUTPUT,

      Uri.fromFile(new File(outPath)));

      // 调用系统裁切界面

      activity.startActivityForResult(intent, requestCode);

      }


    /////////////////////裁切成功的回调////////

    @Override

    public void onActivityResult(int requestCode, int resultCode, Intent data) {

    if (resultCode==RESULT_OK&&data!=null) {

    //裁切成功


            }  
    super.onActivityResult(requestCode, resultCode, data);
    }

    2015-08-18 14:27

  • Funk

    万分感谢 我试试~~~

    2015-08-21 09:36

  • Funk

    回复 wenju:直接换uri的问题是它本身是带相册中选择,然后裁剪 所以这样不行 我无法去掉里面的相册选择部分…… 我现在试试你的第二种方法:)

    2015-08-21 14:50

  • Funk

    回复 wenju:我去看了一下intent的说明 再结合你的说明 大概明白怎么做了:)

    2015-08-21 15:07

  • Funk

    回复 wenju: cropImage是通过什么来调用的? 我发现还是没有触发裁剪……555

    2015-08-21 15:30

  • Funk

    回复 wenju:你能帮我看一下吗?http://ask.dcloud.net.cn/question/9560 thx 在此期间 我会继续想的~~~

    2015-08-21 15:45

stock2

stock2

最后补充下代码 如果进入相册后,不点击选择任何图片,返回. 日志会报错.
增加if (data==undefined) 判断后 直接返回,就避免报错了.
var outPutUri = Uri.fromFile(file);
if (data==undefined){mui.toast("您已取消操作");mui.back();return false;}
plus.android.importClass(data);

wenju

wenju - https://www.mescroll.com -- 精致的下拉刷新和上拉加载组件

回复 Funk:拍照回来后在onActivityResult中调用cropImage方法,其中uri=data.getData()就是拍照回来的图片

脉搏

脉搏

IOS可咋整呢,哪位高手弄一下啊.

  • ywg369

    有ios的解决方案么

    2016-04-01 11:10

  • 4***@qq.com

    同问

    2018-03-05 14:31

zhaoyari

zhaoyari

效果怎么样啊,呵呵,求点评

趴趴熊

趴趴熊

在真机调试时没有问题,但是打包后就不能实现了。只能执行到这一步
cropIntent.setDataAndType(uri, IMAGE_UNSPECIFIED);
,后面的就不执行了,无法跳到剪切图像窗口。我把权限全勾上也不行。谁来帮忙看看。

  • alongSelf

    var outPutPath = plus.io.convertLocalFileSystemURL("_www/5566.jpg");

    最好换成

    var outPutPath = plus.io.convertLocalFileSystemURL("_downloads/image/5566.jpg");


    因为打包之后 _www目录是只读的。

    2016-03-03 16:00

  • 笑一阵

    回复 alongSelf:还是不行捏。。。你有试过么 我我这里改了路径打包后还是不行。。。。

    2016-07-06 12:10

slj

slj

为什么只能换一次图片 第二次就不行了

  • stock2

    这个我有经验. 图片更新的链接后面加个参数?ver=日期时间 就可以了

    2015-12-30 09:54

  • 笑一阵

    回复 stock2:head.src=outPutPath+"?ver="+d.getTime(); 请问是这样么 还是不行诶

    2016-06-13 10:33

  • stock2

    前提是,.图片能正常获取到,只是不刷新,被缓存导致. 通过日期每次不一样,就更新.

    2017-03-23 11:43

老王

老王

能不能再来个 IOS 版本的

ywg369

ywg369

IOS的如何实现此效果呢

学长

学长

参照的是上面的实例,截取完毕后返回的requestCode码也是1(表明图像是裁剪完毕了)但是根目录下并没有保存有5566.jpg的图片。我是用的debug模式来调试的,是什么原因呢

笑一阵

笑一阵

这段代码是怎么调用的。。小白请教。。

1***@163.com

1***@163.com

为啥调用后,选择相册图片后,又一次打开了相册

4***@qq.com

4***@qq.com

可有一个完整的demo,求demo

9***@qq.com

9***@qq.com

java.lang.NullPointerException: Attempt to invoke virtual method 'char[] java.lang.String.toCharArray()' on a null object reference;at new java.io.File

z***@gmail.com

z***@gmail.com

为什么选择完照片后会一直不断地调用裁剪 一直调用

cxian

cxian -

mark

w***@qq.com

w***@qq.com

保存时发生错误,保存失败

4***@qq.com

4***@qq.com

各位老铁有没有demo啊!

f***@foxmail.com

f***@foxmail.com

APP在真机调试是可以获取到裁剪的路径,但是打包之后就报错说图片路径不存在,这是怎么回事

该问题目前已经被锁定, 无法添加新回复