uni-app Native.js调用系统裁剪图片、头像裁剪-Android
uni-app Native.js调用系统裁剪图片、头像裁剪-Android
虽然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
大坑啊,竟然没人发现?
var outPutPath = plus.io.convertLocalFileSystemURL("_www/5566.jpg");
这句要放到onActivityResult最上面,方法体外或在方法体内的第一句,不然第二次回调的时候,根本找不到outPutPath这个变量
来得正是需要的 我来补充几点:
1.如果需要自由裁切,不设置1:1正方形比例,那么可去掉aspectX和aspectY的设置,
2.如果设置的输出尺寸比较大,比如outputX=640 那有的手机返回不了数据,可把return-data设置成false;
我的项目是要求用户上传产品图,尺寸最少640px,高度不限;那么不能设置1:1比例,而且outputX outputY 是必须设置的,不然保存不了;我是这么做的outputX=640; 而outputY=1280//尽量设置高一点,一般图片不会超过640:1280的这个比例
避免黑边的出现,还需设置intent.putExtra(“scale”, true);intent.putExtra(“scaleUpIfNeeded”, true);
非常好的补充,感谢
var outPutPath = plus.io.convertLocalFileSystemURL("_www/5566.jpg");
最好换成
var outPutPath = plus.io.convertLocalFileSystemURL("_downloads/image/5566.jpg");
因为打包之后 _www目录是只读的。
js 稳定性 速度肯定跟不上的. 类似之前的压缩图片, 小的而且越压越大的. 大的压缩效果 … 哎.不说了
还好官网出了, 压缩图片 .非常好.
现在希望出个 能拖拉的裁剪的功能. 呵呵
测试了,效果很不错. 输出时 var a = file.exists(); alert(a);
为null
我查看了文件,是存在的. 哪里错误了? 复制的代码 谢谢
outPutPath设置成全局变量就好了
太感谢了 .按照你的指点,可以了.
…你逗我
回复 stock2:你是怎么,调好的,我的alert(a)是false
@117970 根据楼上的outPutPath设置成全局变量 就好了.
怎么弄啊,设置了全局,还是,调好的,我的alert(a)是false
我的跟你问题一样。设置了全局,也是返回false。请问怎么解决的
修正一下我之前补充的:
如果要自由裁切,不指定比例,
则aspectX,aspectY,outputX outputY都无需设置
如果X设置了则Y必须设置 否则保存不了
我想问一下 你有做拍照裁剪吗? 这段代码是把相册和裁剪和一块了 我试了几次没把他们分开,表示安卓的东西不是很懂……
回复 Funk:var uri = data.getData(); 把这个uri换成拍照回来的uri即可
回复 Funk:Android的裁切代码:
/////////////////////裁切成功的回调//////// @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode==RESULT_OK&&data!=null) { //裁切成功
万分感谢 我试试~~~
回复 wenju:直接换uri的问题是它本身是带相册中选择,然后裁剪 所以这样不行 我无法去掉里面的相册选择部分…… 我现在试试你的第二种方法:)
回复 wenju:我去看了一下intent的说明 再结合你的说明 大概明白怎么做了:)
回复 wenju: cropImage是通过什么来调用的? 我发现还是没有触发裁剪……555
回复 wenju:你能帮我看一下吗?http://ask.dcloud.net.cn/question/9560 thx 在此期间 我会继续想的~~~
最后补充下代码 如果进入相册后,不点击选择任何图片,返回. 日志会报错.
增加if (data==undefined) 判断后 直接返回,就避免报错了.
var outPutUri = Uri.fromFile(file);
if (data==undefined){mui.toast(“您已取消操作”);mui.back();return false;}
plus.android.importClass(data);
回复 Funk:拍照回来后在onActivityResult中调用cropImage方法,其中uri=data.getData()就是拍照回来的图片
有ios的解决方案么
同问
效果怎么样啊,呵呵,求点评
在真机调试时没有问题,但是打包后就不能实现了。只能执行到这一步
cropIntent.setDataAndType(uri, IMAGE_UNSPECIFIED);
,后面的就不执行了,无法跳到剪切图像窗口。我把权限全勾上也不行。谁来帮忙看看。
var outPutPath = plus.io.convertLocalFileSystemURL("_www/5566.jpg"); 最好换成 var outPutPath = plus.io.convertLocalFileSystemURL("_downloads/image/5566.jpg");
因为打包之后 _www目录是只读的。
回复 alongSelf:还是不行捏。。。你有试过么 我我这里改了路径打包后还是不行。。。。
这个我有经验. 图片更新的链接后面加个参数?ver=日期时间 就可以了
回复 stock2:head.src=outPutPath+"?ver="+d.getTime(); 请问是这样么 还是不行诶
前提是,.图片能正常获取到,只是不刷新,被缓存导致. 通过日期每次不一样,就更新.
能不能再来个 IOS 版本的
有ios处理方式么
同问
IOS的如何实现此效果呢
同问
参照的是上面的实例,截取完毕后返回的requestCode码也是1(表明图像是裁剪完毕了)但是根目录下并没有保存有5566.jpg的图片。我是用的debug模式来调试的,是什么原因呢
我的也是没保存
这段代码是怎么调用的。。小白请教。。
同求
为啥调用后,选择相册图片后,又一次打开了相册
可有一个完整的demo,求demo
java.lang.NullPointerException: Attempt to invoke virtual method ‘char[] java.lang.String.toCharArray()’ on a null object reference;at new java.io.File
mark
保存时发生错误,保存失败
应该是outPutPath参数指向的文件夹不存在导致的,我刚也遇到这个问题
回复 c***@hotmail.com: 有没有demo啊
各位老铁有没有demo啊!
APP在真机调试是可以获取到裁剪的路径,但是打包之后就报错说图片路径不存在,这是怎么回事
在uni-app中,使用Native.js调用Android系统的图片裁剪功能,可以通过调用Android的原生API来实现。以下是一个简单的示例代码,展示如何通过Native.js在Android平台上裁剪图片。
首先,确保你的uni-app项目已经启用了Native.js支持。然后,你可以使用以下代码:
- 在
pages/index/index.vue
中编写页面代码:
<template>
<view>
<button @click="chooseAndCropImage">选择并裁剪图片</button>
<image v-if="croppedImagePath" :src="croppedImagePath" style="width: 100px; height: 100px;"></image>
</view>
</template>
<script>
export default {
data() {
return {
croppedImagePath: ''
};
},
methods: {
chooseAndCropImage() {
// 调用Native.js方法
plus.android.importClass('android.provider.MediaStore');
const intent = new plus.android.intent.Intent(plus.android.invoke(MediaStore, 'ACTION_IMAGE_CAPTURE'));
// 设置裁剪参数(这里需要自定义裁剪Activity或调用系统裁剪功能,以下仅为示例)
// 注意:实际裁剪逻辑可能需要使用第三方库或自定义Activity实现
// 这里假设有一个裁剪Activity的Intent Filter匹配这个Action
intent.setAction('com.example.CROP_IMAGE');
intent.putExtra('outputX', 100);
intent.putExtra('outputY', 100);
intent.putExtra('aspectX', 1);
intent.putExtra('aspectY', 1);
intent.putExtra('scale', true);
intent.putExtra('return-data', true);
plus.android.runtimeMainActivity().startActivityForResult(intent, 1, (requestCode, resultCode, data) => {
if (resultCode === plus.android.constants.Activity.RESULT_OK && data) {
const extras = data.getExtras();
const croppedBitmap = extras.get('data');
// 将Bitmap转换为文件路径(这里省略具体实现,需自行处理)
// this.croppedImagePath = ...;
}
});
}
}
};
</script>
注意:
- 上面的代码示例中,
intent.setAction('com.example.CROP_IMAGE');
是一个假设的Action,实际中你需要有一个匹配的Activity来处理这个Intent,或者调用系统提供的裁剪功能(这通常需要更复杂的处理,包括保存临时文件、调用裁剪Activity等)。 extras.get('data')
获取的是裁剪后的Bitmap对象,你需要将其转换为文件路径才能在uni-app中显示。这部分逻辑没有包含在示例中,因为涉及Bitmap到文件路径的转换,通常需要借助Android的存储API。- 由于Android系统裁剪功能的多样性和复杂性,实际项目中可能需要更详细的处理,包括处理不同Android版本的兼容性、处理权限问题等。
希望这个示例能帮助你理解如何在uni-app中使用Native.js调用Android系统的图片裁剪功能。