vue+Cordova调用相机服务并实现裁剪功能

本文介绍了如何使用Vue和Cordova创建项目,并集成相机插件进行图片拍摄和裁剪操作。首先,建立了Vue项目和Cordova项目,接着在Cordova中添加相机插件并进行测试。在Vue项目中,通过修改index.html和添加index.js来调用相机,并实现了文件转换以适应后端需求。同时,提到了项目中用到的mui、cropperjs和less等技术。
摘要由CSDN通过智能技术生成

vue cordova 

一、建立vue项目和cordova项目

网上很多教程可自行查找-步骤略过

二、cordova

  1. 进入cordova项目添加相机插件
  2. watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3ODE5NjY4,size_16,color_FFFFFF,t_70

 

cordova plugin add cordova-plugin-camera

    3.列出所有已安装的cordova插件 

20200521163530624.png

cordova plugin ls

 以上是在cordova项目添加相机插件

三、测试

以下是测试阶段-----------------------------调用相机是否好使

也可不在vue项目里我的github地址可自行下载查看-建议直接下载

先到cordova项目里面把www文件夹删掉

把下载的www文件夹复制到cordova项目打包测试

打包步骤-这里是打包安卓-

cordova build android

测试是否可正常调用 下载地址

https://github.com/zhou175/cordova_sw.git

如不好使,建议在重新下载一次-cordova相机插件

以下是代码

1.进入index.html页面

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3ODE5NjY4,size_16,color_FFFFFF,t_70

经测试,不用在cordova项目的www文件夹里的index.html去复制meta标签,我去掉也能正常调用

<!DOCTYPE html>
<!--
    Licensed to the Apache Software Foundation (ASF) under one
    or more contributor license agreements.  See the NOTICE file
    distributed with this work for additional information
    regarding copyright ownership.  The ASF licenses this file
    to you under the Apache License, Version 2.0 (the
    "License"); you may not use this file except in compliance
    with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing,
    software distributed under the License is distributed on an
    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     KIND, either express or implied.  See the License for the
    specific language governing permissions and limitations
    under the License.
-->
<html>

<head>
    <!--
        Customize this policy to fit your own app's needs. For more guidance, see:
            https://github.com/apache/cordova-plugin-whitelist/blob/master/README.md#content-security-policy
        Some notes:
            * gap: is required only on iOS (when using UIWebView) and is needed for JS->native communication
            * https://ssl.gstatic.com is required only on Android and is needed for TalkBack to function properly
            * Disables use of inline scripts in order to mitigate risk of XSS vulnerabilities. To change this:
                * Enable inline JS: add 'unsafe-inline' to default-src
        -->
    <meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
    <meta name="format-detection" content="telephone=no">
    <meta name="msapplication-tap-highlight" content="no">
    <meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width">
    <title>Hello World</title>
    <style>
        .block {
            width: 100%;
            padding: 10px;
        }
        
        #img {
            height: 220px;
        }
    </style>
</head>

<body>
    <div class="app">
        <div class="block">
            <button id="openCamera">按钮</button>
        </div>
        <div class="block">
            <img id="img" />
        </div>
        <div class="block">
            <span id="text"></span>
        </div>
    </div>
    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript" src="js/index.js"></script>
</body>

</html>

添加代码在index.html里面注意这个地方我添加了个index.js代码复制如下

index.js复制如下

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
var app = {
    // Application Constructor
    initialize: function() {
        document.addEventListener('deviceready', this.onDeviceReady.bind(this), false);
    },

    // deviceready Event Handler
    //
    // Bind any cordova events here. Common events are:
    // 'pause', 'resume', etc.
    onDeviceReady: function() {
        this.receivedEvent('deviceready');
    },

    // 获取id的函数
    $: function(id) {
        return document.getElementById(id);
    },

    // Update DOM on a Received Event
    receivedEvent: function() {
        var cameraButton = this.$('openCamera');
        var _this = this; // this表示当前对象,_this表示cameraButton对象
        cameraButton.onclick = function() {
            // 打开图片库
            navigator.camera.getPicture(onSuccess, onFail, {
                quality: 50, // 相片质量是50
                sourceType: Camera.PictureSourceType.CAMERA, // 设置从摄像头拍照获取
                destinationType: Camera.DestinationType.FILE_URI // 以文件路径返回
            });

            function onSuccess(imageURI) {
                //成功
                // var image = _this.$('img');
                // var text = _this.$('text');
                // image.src = imageURI;
                // text.innerHTML = imageURI.substr(imageURI.lastIndexOf('/') + 1);
            }

            function onFail(message) {
                alert('Failed because: ' + message);
            }
        }
    }
};
app.initialize();

 

 四、进入vue项目

index.html

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3ODE5NjY4,size_16,color_FFFFFF,t_70

上述里面的index.js文件把receivedEvent里面的全都注释掉

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzM3ODE5NjY4,size_16,color_FFFFFF,t_70

由于我vue项目里面用到了mui  cropperjs less等可自行下载引用

以下代码直接拿来用

<template>
  <div id="demo">
    <!-- 遮罩层 -->
    <div class="container" v-show="panel">
      <div class="jahas">
        <img id="image" :src="url" alt="Picture">
      </div>
      <button type="button" id="button" @click="crop">确定</button>
    </div>
    <div>
        <mt-header title="设置头像">
            <div slot="left" class="back" @click="$router.back(-1)"></div>
            <mt-button icon="more" slot="right" @click="actionSheet"></mt-button>
        </mt-header>
        <div class="main">
            <img class="main_oimg" id="myImage" ref="imgimg" :src="imgUrl" v-show="isUpload">
            <img class="main_oimg" v-if="oimgurl!=''" :src="oimgurl" v-show="!isUpload" />
            <img class="main_oimg" v-else src="../../assets/my-i.png"  v-show="!isUpload" />
        </div>
        <mt-actionsheet
            :actions= "data"
            v-model="sheetVisible">
        </mt-actionsheet>
    </div>
  </div>
</template>

js片段  由于后端只接受file文件  转换file文件也一并如下

<script>
    import Cropper from 'cropperjs'
    import $ from 'jquery'
    import axios from 'axios'
    import {Toast} from 'mint-ui';
    export default {
        components: {
        },
        data () {
            return {
                data: [{    
                    name: '拍照',
                    method: this.camera // 调用camera中的函数
                }, {    
                    name: '从照片中选择',
                    method: this.getLibrary // 调用getLibrary中的函数  
                }],
                sheetVisible: false,
                isUpload: false,
                imgUrl: '',
                oimgurl:"#",
                urls:"", //路径地址
                imgFile: [],
                loading:'',
                headerImage:'',
                picValue:'',
                cropper:'',
                croppable:false,
                panel:false,
                url:''
            }
        },
        mounted () {

            //初始化这个裁剪框
            var self = this;
            var image = document.getElementById('image');
            this.cropper = new Cropper(image, {
                aspectRatio: 1,
                viewMode: 1,
                background:false,
                zoomable:false,
                ready: function () {
                    self.croppable = true;
                }
            });
        },
        methods: {
            actionSheet: function() {   // 打开action sheet
                this.sheetVisible = true;  
            },
            camera() {
                // console.log("打开相级") 
                var that = this;
                navigator.camera.getPicture(that.onSuccess, that.onFail, {
                    quality: 50, // 相片质量是50
                    sourceType: Camera.PictureSourceType.CAMERA, // 设置从摄像头拍照获取
                    // destinationType: Camera.DestinationType.FILE_URI, // 以文件路径返回
                    destinationType:0
                });
			},
            getLibrary: function() {   
            //    console.log("打开相册") 
                var that = this;
                navigator.camera.getPicture(that.onSuccess, that.onFail, {
                    quality: 50, // 相片质量是50
                    sourceType: Camera.PictureSourceType.PHOTOLIBRARY, // 设置从图库拍照获取
                    // destinationType: Camera.DestinationType.FILE_URI, //
                    destinationType:0
                });
            },
            //转格式
            dataURLtoFile: function (dataurl, filename) {
                var arr = dataurl.split(',')
                var mime = arr[0].match(/:(.*?);/)[1]
                var bstr = window.atob(arr[1])
                var n = bstr.length
                var u8arr = new Uint8Array(n)
                while (n--) {
                    u8arr[n] = bstr.charCodeAt(n)
                }
                var blob = new Blob([u8arr], {type: mime})
                blob.lastModifiedDate = new Date()
                blob.name = filename
                return blob
            },
            //调用成功之后
            onSuccess:function (imageURI) {
                var that = this;
                // that.isUpload = true;
                // that.imgUrl ='data:image/jpeg;base64,'+imageURI;
                var newurl='data:image/jpeg;base64,'+imageURI;
                var file = that.dataURLtoFile('data:image/jpeg;base64,' + imageURI, 'test.jpeg')
                let ueseid = JSON.parse(window.localStorage.getItem("userinfo")).id;
                var typews=imageURI.substr(imageURI.lastIndexOf('/') + 1)
                let files = new File([file], file.name, {type: 'test.jpeg', lastModified: Date.now()});
                that.panel = true;
                that.picValue = files;
                that.url = that.getObjectURL(that.picValue);
                //每次替换图片要重新得到新的url
                if(that.cropper){
                    that.cropper.replace(that.url);
                }
                that.panel = true;
            },
            onFail:function (message) {
                Toast('取消');
            },
            getObjectURL (file) {
                var url = null ;
                if (window.createObjectURL!=undefined) { // basic
                    url = window.createObjectURL(file) ;
                } else if (window.URL!=undefined) { // mozilla(firefox)
                    url = window.URL.createObjectURL(file) ;
                } else if (window.webkitURL!=undefined) { // webkit or chrome
                    url = window.webkitURL.createObjectURL(file) ;
                }
                return url ;
            },
            crop () {
                this.panel = false;
                var croppedCanvas;
                var roundedCanvas;
                if (!this.croppable) {
                    return;
                }
                // Crop
                croppedCanvas = this.cropper.getCroppedCanvas();
                console.log(this.cropper)
                // Round
                roundedCanvas = this.getRoundedCanvas(croppedCanvas);
                this.oimgurl = roundedCanvas.toDataURL();
                this.postImg(this.oimgurl)
            },
            getRoundedCanvas (sourceCanvas) {
                var canvas = document.createElement('canvas');
                var context = canvas.getContext('2d');
                var width = sourceCanvas.width;
                var height = sourceCanvas.height;
                canvas.width = width;
                canvas.height = height;
                context.imageSmoothingEnabled = true;
                context.drawImage(sourceCanvas, 0, 0, width, height);
                context.globalCompositeOperation = 'destination-in';
                context.beginPath();
                context.arc(width / 2, height / 2, Math.min(width, height) / 2, 0, 2 * Math.PI, true);
                context.fill();
                return canvas;
            },
            //裁剪完成之后
            postImg (texts) {
                var that=this;
                that.isUpload = true;
                that.imgUrl =texts;
                var file = that.dataURLtoFile(texts, 'hh.png')
                let ueseid = JSON.parse(window.localStorage.getItem("userinfo")).id;
                // var typews=imageURI.substr(imageURI.lastIndexOf('/') + 1)
                let files = new File([file], file.name, {type: 'hh.png', lastModified: Date.now()});
                //这边写图片的上传
                var fd = new FormData();
                fd.append("file", files);

                $.ajax({
                    url: that.urls,
                    type: 'POST',
                    cache: false,
                    data: fd,
                    processData: false,// 告诉jQuery不要去处理发送的数据
                    contentType: false,// 告诉jQuery不要去设置Content-Type请求头
                    dataType: "json",
                    success: function (data) {
                        if(data.msg=='修改内容成功!'){
                            Toast('修改成功');
                        }else{
                            Toast('修改失败');
                        }
                    }
                });
            }

        }
    }
</script>

css片段

<style lang="less">
*{
 margin: 0;
 padding: 0;
}
 .back {
        position: absolute;
        top: 0.2rem;
        left: 0.2rem;
        width: 0.44rem;
        height: 0.44rem;
        background: url("../../assets/n.png") no-repeat center center;
        background-size: 100% 100%;
    }
    .input_show {
        opacity: 0;
        display: none;
    }
    .mint-header {
        height: 0.88rem;
        font-size: 0.36rem;
        font-weight: 500;
        color: #FFFFFF;
        line-height: 0.88rem;
        font-weight: bold;
        text-align: center;
        box-shadow: 0 0.02rem 0.07rem 0.01rem rgba(9, 35, 77, 0.1);
        background: #0076FF;
    }
    .main {
        position: absolute;
        width: 100%;
        height: calc(~"100% - 0.88rem");
        background-color: #010101;
        display: flex;
        -webkit-box-pack: center;
        -ms-flex-pack: center;
        justify-content: center;
        -webkit-box-align: center;
        -ms-flex-align: center;
        align-items: center;

    }
    .main_oimg {
        width: 80%;
            // height:80%;
    }
.jahas{
    overflow:auto;
    height:100%;
}
#demo #button {
 position: absolute;
 right: 10px;
 top: 10px;
 width: 80px;
 height: 40px;
 border:none;
 border-radius: 5px;
 background:white;
}
#demo .show {
 width: 100px;
 height: 100px;
 overflow: hidden;
 position: relative;
 border-radius: 50%;
 border: 1px solid #d5d5d5;
}
#demo .picture {
 width: 100%;
 height: 100%;
 overflow: hidden;
 background-position: center center;
 background-repeat: no-repeat;
 background-size: cover;
}
#demo .container {
  z-index: 99;
  position: fixed;
  padding-top: 60px;
  left: 0;
  top: 0;
  right: 0;
  bottom: 0;
  background:rgba(0,0,0,1);
}
#demo #image {
 max-width: 90%;
}
.cropper-view-box,.cropper-face {
 border-radius: 50%;
}
/*!
 * Cropper.js v1.0.0-rc
 * https://github.com/fengyuanchen/cropperjs
 *
 * Copyright (c) 2017 Fengyuan Chen
 * Released under the MIT license
 *
 * Date: 2017-03-25T12:02:21.062Z
 */
.cropper-container {
 font-size: 0;
 line-height: 0;
 position: relative;
 -webkit-user-select: none;
 -moz-user-select: none;
 -ms-user-select: none;
 user-select: none;
 direction: ltr;
 -ms-touch-action: none;
 touch-action: none
}
.cropper-container img {
 /* Avoid margin top issue (Occur only when margin-top <= -height) */
 display: block;
 min-width: 0 !important;
 max-width: none !important;
 min-height: 0 !important;
 max-height: none !important;
 width:90%;
 height: 100%;
 image-orientation: 0deg
}
.cropper-wrap-box,
.cropper-canvas,
.cropper-drag-box,
.cropper-crop-box,
.cropper-modal {
 position: absolute;
 top: 0;
 right: 0;
 bottom: 0;
 left: 0;
}
.cropper-wrap-box {
 overflow: hidden;
}
.cropper-drag-box {
 opacity: 0;
 background-color: #fff;
}
.cropper-modal {
 opacity: .5;
 background-color: #000;
}
.cropper-view-box {
 display: block;
 overflow: hidden;
 width: 100%;
 height: 100%;
 outline: 1px solid #39f;
 outline-color: rgba(51, 153, 255, 0.75);
}
.cropper-dashed {
 position: absolute;
 display: block;
 opacity: .5;
 border: 0 dashed #eee
}
.cropper-dashed.dashed-h {
 top: 33.33333%;
 left: 0;
 width: 100%;
 height: 33.33333%;
 border-top-width: 1px;
 border-bottom-width: 1px
}
.cropper-dashed.dashed-v {
 top: 0;
 left: 33.33333%;
 width: 33.33333%;
 height: 100%;
 border-right-width: 1px;
 border-left-width: 1px
}
.cropper-center {
 position: absolute;
 top: 50%;
 left: 50%;
 display: block;
 width: 0;
 height: 0;
 opacity: .75
}
.cropper-center:before,
 .cropper-center:after {
 position: absolute;
 display: block;
 content: ' ';
 background-color: #eee
}
.cropper-center:before {
 top: 0;
 left: -3px;
 width: 7px;
 height: 1px
}
.cropper-center:after {
 top: -3px;
 left: 0;
 width: 1px;
 height: 7px
}
.cropper-face,
.cropper-line,
.cropper-point {
 position: absolute;
 display: block;
 width: 100%;
 height: 100%;
 opacity: .1;
}
.cropper-face {
 top: 0;
 left: 0;
 background-color: #fff;
}
.cropper-line {
 background-color: #39f
}
.cropper-line.line-e {
 top: 0;
 right: -3px;
 width: 5px;
 cursor: e-resize
}
.cropper-line.line-n {
 top: -3px;
 left: 0;
 height: 5px;
 cursor: n-resize
}
.cropper-line.line-w {
 top: 0;
 left: -3px;
 width: 5px;
 cursor: w-resize
}
.cropper-line.line-s {
 bottom: -3px;
 left: 0;
 height: 5px;
 cursor: s-resize
}
.cropper-point {
 width: 5px;
 height: 5px;
 opacity: .75;
 background-color: #39f
}
.cropper-point.point-e {
 top: 50%;
 right: -3px;
 margin-top: -3px;
 cursor: e-resize
}
.cropper-point.point-n {
 top: -3px;
 left: 50%;
 margin-left: -3px;
 cursor: n-resize
}
.cropper-point.point-w {
 top: 50%;
 left: -3px;
 margin-top: -3px;
 cursor: w-resize
}
.cropper-point.point-s {
 bottom: -3px;
 left: 50%;
 margin-left: -3px;
 cursor: s-resize
}
.cropper-point.point-ne {
 top: -3px;
 right: -3px;
 cursor: ne-resize
}
.cropper-point.point-nw {
 top: -3px;
 left: -3px;
 cursor: nw-resize
}
.cropper-point.point-sw {
 bottom: -3px;
 left: -3px;
 cursor: sw-resize
}
.cropper-point.point-se {
 right: -3px;
 bottom: -3px;
 width: 20px;
 height: 20px;
 cursor: se-resize;
 opacity: 1
}
@media (min-width: 768px) {
 .cropper-point.point-se {
  width: 15px;
  height: 15px
 }
}
@media (min-width: 992px) {
 .cropper-point.point-se {
  width: 10px;
  height: 10px
 }
}
@media (min-width: 1200px) {
 .cropper-point.point-se {
  width: 5px;
  height: 5px;
  opacity: .75
 }
}
    .cropper-point.point-se:before {
        position: absolute;
        right: -50%;
        bottom: -50%;
        display: block;
        width: 200%;
        height: 200%;
        content: ' ';
        opacity: 0;
        background-color: #39f
    }
    .cropper-invisible {
        opacity: 0;
    }
    .cropper-bg {
        background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMzTjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC');
    }
    .cropper-hide {
        position: absolute;
        display: block;
        width: 0;
        height: 0;
    }
    .cropper-hidden {
        display: none !important;
    }
    .cropper-move {
        cursor: move;
    }
    .cropper-crop {
        cursor: crosshair;
    }
    .cropper-disabled .cropper-drag-box,
    .cropper-disabled .cropper-face,
    .cropper-disabled .cropper-line,
    .cropper-disabled .cropper-point {
        cursor: not-allowed;
    }

</style>

完成

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值