问题
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