How to trigger multiple videos with ar.js

别等时光非礼了梦想. 提交于 2021-01-28 07:55:32

问题


FINAL UPDATE 9/13/2019 11:50pm : This code works with several custom markers, however the markers cannot be too similar. My previous custom markers were all stars with mild differences, and I think this was tripping it up somehow. But with newer, more unique markers, it works.

For some reason, though, this did not affect the result when using the "separate components" method.


Updated: 9/13/2019 : The below code works with hiro and kanji preset markers and one custom marker. However, when I add multiple custom markers, the videos freeze on the extra markers. I would like each marker to trigger unique videos (some videos will be re-used in several markers). In my current code, I just have them all triggering both videos. *How can I get this code to work with multiple custom markers?

<!-- A-FRAME -->
<script src="https://aframe.io/releases/0.9.2/aframe.min.js"></script>
<script 
src="https://cdn.rawgit.com/jeromeetienne/AR.js/1.6.0/aframe/build/aframe- 
ar.js"></script> 
<script src="https://cdn.rawgit.com/donmccurdy/aframe- 
extras/v4.1.2/dist/aframe-extras.min.js"></script> 
<script src="https://rawgit.com/mayognaise/aframe-gif- 
shader/master/dist/aframe-gif-shader.min.js"></script> 

<!-- jQuery library -->
<script 
 src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"> 
</script> 

<!-- Latest compiled and minified CSS -->
<script 
src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"> 
</script> 

<!-- vidhandler component -->
<script>
AFRAME.registerComponent('vidhandler', {
schema: {
  target: {type: 'string'}
},
init: function() {
    this.videoNodes = document.querySelectorAll(this.data.target)
},
tick: function() {
    if (this.el.object3D.visible == true) {
        if (!this.toggle) {
            this.toggle = true;
            for (let i = 0; i < this.videoNodes.length; i++) {
                this.videoNodes[i].play();
            } 
        }
    } else {
        if (this.toggle) {
          for (let i = 0; i < this.videoNodes.length; i++) {
            this.videoNodes[i].pause();
          }
          this.toggle = false;
        }
    }
}
});
</script>

<!-- assets for vidhandler -->
<a-assets >
    <video crossOrigin="Anonymous" Id="vid" 
loop="true"src="assets\textures\alpha.webm">
    </video>
    <video crossOrigin="Anonymous" Id="videonew" loop="true" src="assets\textures\VideoNew.mp4">
    </video>     
</a-assets>

 <!-- marker1: hollywood star 1 -->
 <a-marker  vidhandler="target: #vid, #videonew" type='pattern' url='https://raw.githubusercontent.com/merowell/custom-markers-with-video/master/aframe/examples/assets/hollywood-stars/patt/pattern-hollywood-star1.patt'>
    <!-- add transparent video (.webm) -->
    <a-plane  position='0 .3 0' width='3' height='2' rotation="-90 0 0" material='transparent:true;alphaTest:0;src:#vid'></a-plane>

    <!-- add non transparent video (.mp4) -->
    <a-plane  position='0 .2 0' width='1.5' height='1.5' rotation="-90 0 0" material='src:#videonew'></a-plane>
</a-marker>


<!-- marker2: hollywood star 2 -->
<a-marker  vidhandler="target: #vid, #videonew" type='pattern' url='https://raw.githubusercontent.com/merowell/custom-markers-with-video/master/aframe/examples/assets/hollywood-stars/patt/pattern-hollywood-star2.patt'>
     <!-- add transparent video (.webm) -->
    <a-plane  position='0 .3 0' width='3' height='2' rotation="-90 0 0" material='transparent:true;alphaTest:0;src:#vid'></a-plane>

    <!-- add non transparent video (.mp4) -->
    <a-plane  position='0 .2 0' width='1.5' height='1.5' rotation="-90 0 0" material='src:#videonew'></a-plane>
</a-marker>

Updated 9-12-19 : how to play separate videos with separate markers, with option to re-use certain videos? With the following code, the videos display as a static image:

<!-- vidhandler component -->
<script>
AFRAME.registerComponent('vidHandler', {
// define a variable in which we will keep the video element
schema: {
 targets: {type: "string"}
},
 init: function() {
    this.toggle = false;
    this.vidNodes = document.querySelectorAll(this.data.targets);
    for (let i = 0; i < this.vidNodes.length; i++) {
          this.vidNodes[i].pause();
    }
},
tick: function() {
    if (this.el.object3D.visible == true) {
        if (!this.toggle) {
            this.toggle = true;
            for (let i = 0; i < this.vidNodes.length; i++) {
              this.vidNodes[i].play();
            }
        }
    } else {
        this.toggle = false;
        for (let i = 0; i < this.vidNodes.length; i++) {
          this.vidNodes[i].pause();
        }
    }
}
});
</script>

Original question:

Please forgive me as I am very new to this....

I'm using ar.js with aframe to create a webAR experience. I'm using two different markers to trigger two different videos.

How do I make the Aframe.register component trigger both of my videos separately? The two videos are listed as assets, with the following IDs: #vid #videonew

the expected results are for the two markers to display a unique video that loops, whether both markers are shown to the webcam, or if it's just one of the markers. But the actual result is the videos only play if both markers are shown to the webcam. Otherwise, individually, the videos display as a static image.

<!-- Video Player -->
<script>
AFRAME.registerComponent('vidhandler', {
init: function() {
    this.toggle = false;
    this.vidNodes = document.querySelectorAll("#vid, #videonew");
    for (let i = 0; i < this.vidNodes.length; i++) {
          this.vidNodes[i].pause();
    }
},
tick: function() {
    if (this.el.object3D.visible == true) {
        if (!this.toggle) {
            this.toggle = true;
            for (let i = 0; i < this.vidNodes.length; i++) {
              this.vidNodes[i].play();
            }
        }
    } else {
        this.toggle = false;
        for (let i = 0; i < this.vidNodes.length; i++) {
          this.vidNodes[i].pause();
        }
    }
}
});
</script>

<a-assets >
    <video crossOrigin="Anonymous" preload="auto"  Id="vid" loop="true"   webkit-playsinline playsinline controls>
       <source  type="video/webm"  src="assets\textures\alpha.webm">
       <h3>Error : Your browser does not support.</h3>
      <!-- FOR NOTMAL VIDEO YOU CAN USE MP4 or WEBM BUT FOR ALPHA VIDEO YOU NEED TO USE .WEBM FORMAT-->
    </video>

     <video crossOrigin="Anonymous" preload="auto"  Id="videonew" loop="true"   webkit-playsinline playsinline controls>
       <source  type="video/webm"  src="assets\textures\VideoNew.mp4">
       <h3>Error : Your browser does not support.</h3>
      <!-- FOR NOTMAL VIDEO YOU CAN USE MP4 or WEBM BUT FOR ALPHA VIDEO YOU NEED TO USE .WEBM FORMAT-->
    </video>
</a-assets>

回答1:


1. One marker triggers two videos

document.querySelectorAll(selector) returns a container (NodeList) with the matching elements. To call .play() on each video, you need to iterate through the container and call it on each element.


Each this.vid.play(), and this.vid.pause() needs to be replaced with:

for (let i = 0; i < this.vid.length; i++) {
    this.vid[i].play() // or this.vid[i].pause()
}

Also it wouldn't hurt to rename it to this.videoNodes :)


Check out in this glitch how you can do triggering two videos with aframe, and ar.js

2. Two markers, each with a unique video

No need to duplicate the component for each marker, you only need a modification which will allow providing the video to the component. That way you can use the same component, for different video elements. We can achieve that with the components schema.

js - using the element from the schema

AFRAME.registerComponent('vidHandler', {
  // define a variable in which we will keep the video element
  schema: {
     video: {type: 'selector'},
  },
  init: function() {
     // use the video from the schema
     this.video = this.data.video
     this.video.pause()
  },
  tick: function() {
    if (this.el.object3D.visible == true) {
      if (!this.toggle) {
        this.toggle = true;
        this.video.play()
      }
     } else {
      this.toggle = false;
      this.video.pause()
    }
  }
})

HTML - providing the element to the component

<a-assets>
   <video id="one">
   <video id="two">
</a-assets>
<a-marker preset="hiro" vidhandler="video: #one">
    <a-box material='src: #one'></a-box>
</a-marker>
<a-marker preset="kanji" vidhandler="video: #two">
    <a-box material='src: #two'></a-box>
</a-marker>   

3. Two markers trigger any number of videos

By now we are providing a selector to the component, but we can also provide a string to feed the document.querySelectorAll() method:

// <a-marker videohandler="videos: #one, #two">
// videohandler insides:
schema: {
  videos: {type: 'string'}
},
init: function() {
    this.videoNodes = document.querySelectorAll(this.data.target)
},
// the rest like in the first case

Although there are some issues here.

  • Make sure you pause the video only once the marker is lost. Otherwise one component will pause the video on each tick.
  • If you want to play the video from the beginning on another marker, you'd need to cache the timestamp once the marker is lost.

Working glitch here.




回答2:


@Piotr answered this question and provided a great example with this glitch: https://glitch.com/edit/#!/stack-57863016?path=arjs.html:3:0

Thank you! Also, where I was failing, was I wasn't including 'vidhandler' in the a-marker section.




回答3:


Finally! I got it--- In order to get separate videos to play with separate markers, I needed to create a second component. Each marker needs a unique component handler, at least, this is how I got it working.



来源:https://stackoverflow.com/questions/57863016/how-to-trigger-multiple-videos-with-ar-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!