No More Posting New Topics!

If you have a question or an issue, please start a thread in our Github Discussions Forum.
This forum is closed for new threads/ topics.

Navigation

    Quasar Framework

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search

    'cordova-plugin-camera' with Quasar

    Help
    5
    8
    3494
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • K
      Kevin last edited by

      Hello,
      I am looking to use the Cordova plugin “cordova-plugin-camera”.
      If I create a project directly under cordova, I have no problem.
      If I use the example of the documentation of quasar framework for this plugin, the photo does not appear after using the camera and I have a message in the console of the ‘remote devices’ of Chrome "Failed to load resource: net :: ERR_INVALID_URL "with the url of my picture.
      Has anyone ever had this problem?
      Thank you for your help.

      0_1548009315832_5c5517e6-b695-436f-b755-9f56808e1b1c-image.png

      1 Reply Last reply Reply Quote 0
      • L
        Lou Rectoret last edited by

        you can access the camera with the html5 API, did you know that? I could share with you some (still dirty) code I’m currently working on:

        <template>
            <section>
                <q-modal v-model="opened">
                    <section class="relative-position overflow-hidden fit">
                        <figure class="no-margin" v-if="!imageUrl">
                            <video ref="video" :src="source" class="fixed-center" :height="camHeight"
                            />
                        </figure>
        
                        <div>
                            <img v-if="bin.images.length > 0" class="rounded-borders border-primary avatar-lg absolute-bottom-right last-pic-avatar"
                                 :src="lastImg"
                            />
        
                            <loading v-if="loadingCamera">
                                Loading...
                            </loading>
        
                            <img v-if="imageUrl" class="window-width" :src="imageUrl" alt="Image taken">
        
                            <!--<div class="fullscreen" v-if="notSupported !== false">-->
                            <!--<h2>This browser does not support the camera.</h2>-->
                            <!--<p>-->
                            <!--Please download <a href="https://www.mozilla.org">Firefox</a> <a href="https://www.google.com/chrome">Chrome</a>-->
                            <!--</p>-->
                            <!--</div>-->
        
                            <cam-btn-group class="no-shadow bg-black flat">
                                <div v-if="imageUrl">
                                    <q-btn @click="onConfirmImage" class="absolute-center" flat color="white" icon="far fa-check-circle" size="xl"
                                    />
                                    <q-page-sticky position="bottom-right" :offset="[10, -54]">
                                        <q-btn @click="onCancelImage" class="q-ml-xl" flat color="white" icon="far fa-times-circle" size="xl"
                                               wait-for-ripple
                                        />
                                    </q-page-sticky>
                                </div>
                                <div v-else>
                                    <q-btn @click="onCapture" class="absolute-center" flat color="white" icon="far fa-dot-circle" size="xl"/>
        
                                    <q-page-sticky position="bottom-right" :offset="[10, -60]">
                                        <q-btn @click="exitCamera" label="Next" wait-for-ripple flat color="white"
                                               icon-right="fas fa-long-arrow-alt-right" size="xl"
                                        />
                                    </q-page-sticky>
                                </div>
                            </cam-btn-group>
                        </div>
                    </section>
                </q-modal>
            </section>
        </template>
        
        <script>
        import { get }     from 'vuex-pathify'
        import messages    from '../../common/messages.json'
        import Loading     from '../VLoading'
        import CamBtnGroup from '../VFooterBtns.vue'
        
        export default {
            name: 'Camera',
            components: {
                Loading,
                CamBtnGroup
            },
            data () {
                return {
                    opened: true,
                    mediaStream: null,
                    imageUrl: null,
                    isDefaultBackCamera: true,
                    camera: null,
                    cameras: [],
                    source: null,
                    loadingCamera: true
                }
            },
            computed: {
                ...get('DeployModule/*'),
                hasBackCamera () {
                    const backCameraDevices = this.cameras.filter(device => {
                        return device.label.indexOf('back') !== -1
                    })
                    return backCameraDevices.length > 1 ? backCameraDevices[0] : false
                },
                camHeight () {
                    return window.innerHeight
                },
                lastImg () {
                    return this.bin.images.slice(-1)
                }
            },
            mounted () {
                if (navigator.mediaDevices === undefined) {
                    navigator.mediaDevices = {}
                }
        
                if (navigator.mediaDevices.getUserMedia === undefined) {
                    navigator.mediaDevices.getUserMedia = this.legacyGetUserMediaSupport()
                }
        
                let constraints = this.isDefaultBackCamera ? 'environment' : 'user'
                constraints = { video: { facingMode: { ideal: constraints } } }
        
                this.testMediaAccess(constraints)
            },
            methods: {
                legacyGetUserMediaSupport () {
                    return constraints => {
                        // First get ahold of the legacy getUserMedia, if present
                        let getUserMedia =
                                    navigator.getUserMedia ||
                                    navigator.webkitGetUserMedia ||
                                    navigator.mozGetUserMedia ||
                                    navigator.msGetUserMedia ||
                                    navigator.oGetUserMedia
        
                        // Some browsers just don't implement it - return a rejected promise with an error
                        // to keep a consistent interface
                        if (!getUserMedia) {
                            return Promise.reject(
                                new Error('getUserMedia is not implemented in this browser')
                            )
                        }
        
                        // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
                        return new Promise(function (resolve, reject) {
                            getUserMedia.call(navigator, constraints, resolve, reject)
                        })
                    }
                },
                testMediaAccess (constraints) {
                    // Check if there's the camera set by isDefaultBackCamera
                    navigator.mediaDevices.getUserMedia(constraints).then(stream => {
                        this.getCameras()
                    }).catch(() => {
                        this.$q.notify(messages.camera.error.backCamera)
                        this.testMediaAccess({ video: true })
                    })
                },
                getCameras () {
                    // GET The cameras && and get the Back Camera
                    navigator.mediaDevices.enumerateDevices().then(deviceInfos => {
                        this.loadingCamera = false
                        deviceInfos.forEach(device => {
                            const constraints = this.hasBackCamera ? 'back' : 'amera' // Camera string could be Capital
        
                            if (device.label.indexOf(constraints) !== -1) {
                                this.camera = device
                            }
        
                            if (device.kind.indexOf('videoinput') !== -1) {
                                this.cameras.push(device)
                            }
                        })
                        this.setCamera(this.camera.deviceId)
                    })
                },
                setCamera (deviceId) {
                    navigator.mediaDevices.getUserMedia({ video: { deviceId: { exact: deviceId } } }).then(mediaStream => {
                        this.mediaStream = mediaStream
                        /** Load the stream to the video tag**/
                        if ('srcObject' in this.$refs.video) {
                            // new browsers api
                            this.$refs.video.srcObject = mediaStream
                            this.$refs.video.onloadedmetadata = () => {
                                this.$refs.video.play()
                            }
                        } else {
                            // old broswers
                            this.mediaStream = window.HTMLMediaElement.srcObject(mediaStream)
                        }
                    }).catch(() => this.$q.notify(messages.camera.error.camera))
                },
                onCapture () {
                    const mediaStreamTrack = this.mediaStream.getVideoTracks()[0]
                    const imageCapture = new window.ImageCapture(mediaStreamTrack)
        
                    return imageCapture.takePhoto().then(blob => {
                        this.imageUrl = URL.createObjectURL(blob)
                    })
                },
                onConfirmImage () {
                    this.bin.images.push(this.imageUrl)
                    this.$store.set('DeployModule/bin@images', this.bin.images)
                    this.imageUrl = null
                    this.setCamera(this.camera.deviceId)
                },
                onCancelImage () {
                    this.imageUrl = null
                    this.setCamera(this.camera.deviceId)
                },
                exitCamera () {
                    let stream = this.$refs.video.srcObject
                    let tracks = stream.getTracks()
        
                    tracks.forEach(track => {
                        // stops the video track
                        track.stop()
                    })
                    this.$refs.video.srcObject = null
                    this.mediaStream = null
        
                    this.$emit('stopped')
        
                    this.opened = false
                }
            }
        }
        </script>
        
        <style lang="stylus" scoped>
            .icon-group .wrapper-icon
                font-size 36px
        
            .inner-icon
                position relative
                font-size 20px
                top 4px
                left -54px
                z-index 99
        
            .last-pic-avatar
                margin 0 60px 70px 0
                z-index 9999999999
        
            .arrow-exit
                position absolute
                left 0
                top 5px
        </style>
        
        
        
        D 1 Reply Last reply Reply Quote 0
        • K
          Kevin last edited by

          Thank you, but I would really like to use this plugin.

          • Here is the cordova code that I use to do my tests which is not a problem:
          <!DOCTYPE html>
          <html>
            <head>
              <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 *; script-src 'self' 'unsafe-inline'; 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"
              />
              <link rel="stylesheet" type="text/css" href="css/index.css" />
              <title>Hello World</title>
            </head>
            <body>
              <div class="page">
                <p><img src="img/logo.png" alt="image" id="photo" /></p>
                <p><button id="btn">Take picture</button></p>
                <p id="msg"></p>
              </div>
              <script type="text/javascript" src="cordova.js"></script>
              <script>
                let app = {
                  init: function() {
                    document
                      .getElementById('btn')
                      .addEventListener('click', app.takephoto);
                  },
                  takephoto: function() {
                    let opts = {
                      quality: 80,
                      destinationType: Camera.DestinationType.FILE_URI,
                      sourceType: Camera.PictureSourceType.CAMERA,
                      mediaType: Camera.MediaType.PICTURE,
                      encodingType: Camera.EncodingType.JPEG,
                      cameraDirection: Camera.Direction.BACK,
                      targetWidth: 300,
                      targetHeight: 400
                    };
                    navigator.camera.getPicture(app.ftw, app.wtf, opts);
                  },
                  ftw: function(imgURI) {
                    console.log(imgURI)
                    document.getElementById('msg').textContent = imgURI;
                    document.getElementById('photo').src = imgURI;
                  },
                  wtf: function(msg) {
                    document.getElementById('msg').textContent = msg;
                  }
                };
                document.addEventListener('deviceready', app.init);
              </script>
            </body>
          </html>
          
          

          0_1548930824363_Screenshot_1548930572.png

          • And now the code under Quasar where the image does not appear.
          <template>
            <div class="page">
              <img
                  :src="photo"
                  alt="photo"
                />
              <button @click="takephoto">Take picture</button>
              <p>{{msg}}</p>
            </div>
          </template>
          
          <script>
          
          export default {
            name: 'hello',
            data () {
              return {
                msg: '',
                photo: 'statics/quasar-logo.png'
              }
            },
            methods: {
              takephoto: function () {
                let opts = {
                  quality: 80,
                  destinationType: Camera.DestinationType.FILE_URI,
                  sourceType: Camera.PictureSourceType.CAMERA,
                  mediaType: Camera.MediaType.PICTURE,
                  encodingType: Camera.EncodingType.JPEG,
                  cameraDirection: Camera.Direction.BACK,
                  targetWidth: 300,
                  targetHeight: 400
                }
                navigator.camera.getPicture(this.ftw, this.wtf, opts)
              },
              ftw: function (imgURI) {
                this.msg = imgURI
                this.photo = imgURI
              },
              wtf: function (msg) {
                this.msg = msg
              }
            }
          }
          </script>
          
          <style>
          </style>
          
          

          0_1548931777015_Screenshot_1548931749.png

          E 2 Replies Last reply Reply Quote 0
          • M
            malmil last edited by

            I use the same plugin for a project and it works perfectly.
            Your code does look very similar to mine. The only difference I’ve spotted is that I’ve declared navigator before camera in the options like so:
            encodingType: navigator.camera.EncodingType.JPEG,
            mediaType: navigator.camera.MediaType.PICTURE,

            Hope this helps

            1 Reply Last reply Reply Quote 0
            • D
              desman @Lou Rectoret last edited by

              @Lou-Rectoret
              Good Morning. The example that you use is very useful to me, only that at this moment it is generating problems to me “… get (‘DeployModule / *’)”, you could help, showing the code of that module. Thank you so much.

              L 1 Reply Last reply Reply Quote 0
              • L
                Lou Rectoret @desman last edited by

                Hey @desman !

                “… get (‘DeployModule / *’)is the way vuex-pathify works for mapping the State less verbose.

                So I’m only storing the image path in the Central State, see this:
                bcd66c51-8652-41ce-b413-6c78da78ffba-imagen.png

                That’s all, I’m using vuex-pathify on top of Vuex.
                Try setting the path on the data property of the component, you should be fine.

                GL

                1 Reply Last reply Reply Quote 0
                • E
                  ellalves @Kevin last edited by

                  @Kevin O meu ta igual ao seu a diferença é que nas options eu pego a imagem com: destinationType: navigator.camera.DestinationType.DATA_URL

                  1 Reply Last reply Reply Quote 0
                  • E
                    ellalves @Kevin last edited by ellalves

                    @Kevin ```
                    Código completo!

                    <template>
                      <q-page class="flex flex-center">
                        <q-btn color="primary" label="Get Picture" @click="captureImage" />
                        <q-img
                          :src="imageSrc"
                          placeholder-src="statics/quasar-logo.png"
                          :alt="'Imagem: ' + imageSrc" id="photo"
                        />
                      </q-page>
                    </template>
                    
                    <script>
                    export default {
                      data () {
                        return {
                          imageSrc: ''
                        }
                      },
                    
                      methods: {
                        captureImage () {
                          navigator.camera.getPicture(
                            data => { // on success
                              this.imageSrc = `data:image/jpeg;base64, ${data}`
                              // document.getElementById('photo').src = data
                              alert(this.imageSrc)
                            },
                            () => { // on fail
                              this.$q.notify('Não foi possível acessar a câmera do dispositivo.')
                            },
                            {
                              // camera options
                              quality: 50,
                              destinationType: navigator.camera.DestinationType.DATA_URL,
                              encodingType: navigator.camera.EncodingType.JPEG,
                              MEDIATYPE: navigator.camera.MediaType.PICTURE,
                              sourceType: navigator.camera.PictureSourceType.CAMERA,
                              mediaType: navigator.camera.MediaType.PICTURE,
                              cameraDirection: navigator.camera.Direction.BACK,
                              targetWidth: 300,
                              targetHeight: 400
                            }
                          )
                        }
                      }
                    }
                    </script>
                    1 Reply Last reply Reply Quote 0
                    • First post
                      Last post