AFrame: how to add a touch event listener to an entity - touch

In mobile browser, I want to do something when user touches an image, but I don't know how to use touch listeners. Is there some components that I can use? Or give me some idea how to do it on my own.

A-Frame supports DOM events very similarly to web normal pages. Example:
<a-scene>
<!-- Target -->
<a-box id="target" material="color: green"></a-box>
<!-- Camera + Cursor -->
<a-entity camera>
<a-entity cursor="fuse: true; fuseTimeout: 500"
position="0 0 -1"
geometry="primitive: ring; radiusInner: 0.02; radiusOuter: 0.03"
material="color: black; shader: flat">
</a-entity>
</a-entity>
</a-scene>
And then in JavaScript:
var targetEl = document.querySelector('#target');
targetEl.addEventListener('click', function() {
targetEl.setAttribute('material', {color: 'red'});
});
See A-Frame's cursor component documentation for more details.

I was just searching for the same thing. I found another solution, aframe-mouse-cursor-component.
https://github.com/mayognaise/aframe-mouse-cursor-component

Related

Angular 2: change DOM elements outside the root AppComponent

I have an observable -- loading$ -- that outputs true when I want to show a loading overlay in the UI, and false when it's time to remove that overlay. The visibility is controlled with a CSS class.
When the Observable emits true, I want to add the CSS class to the <body>, and remove it on false.
html
<body class="">
<my-app>Angular app goes here</my-app>
</body>
As you can see, the <body> is outside of my Angular 2 app, so I cannot use property binding to change the class. This is what I currently do:
AppComponent.ts
loading$.subscribe(loading =>{
if(loading) document.querySelector('body').classList.add('loading');
else document.querySelector('body').classList.remove('loading');
});
This works well. The loading class is added/removed when the loading$ observable emits true/false. The problem is that I'd like to run my app in a web worker which means no access to the DOM. Plus, Angular recommends against manipulating the DOM directly.
How can I use Angular APIs to change <body>?
Angular 2, typescript 2, rxjs 5 beta 12
PS: This question looks promising, but the key link is dead. I've also seen a couple of suggestions that worked with Beta releases but are now obsolete (example)
If you want an uninterrupted animation by DOM replacement in the middle of bootstrapping the app then use the following approach.
Put the overlay after my-app element.
<my-app></my-app>
<div id="overlay"></div>
Add #HostBinding to class.ready in main component app.component.ts:
#HostBinding('class.ready') ready: boolean = false;
Change the property when the data is loaded with the initial call (splash is still visible when your screen is not fully rendered).
constructor(private contextService: ContextService) {
someService.initCall().then(r => this.ready = true);
}
Use CSS to hide the loader:
my-app.ready + .overlay {
animation: hideOverlay 1s forwards;
}
#keyframes hideOverlay {
0% {
opacity: 1;
}
100% {
opacity: 0;
visibility: hidden;
}
}
#ktretyak 's solution got things to work for me. Basically, instead of using <body> I put the div that takes the loading class within <my-app>
index.html
<body>
<my-app>
<div id="overlay" class="loading"></div>
</my-app>
</body>
CSS
#overlay {
position:fixed;
top:0;
left:0;
bottom:0;
right:0;
display:none;
}
#overlay.loading {
display:block
}
Thanks to the CSS styles, and the fact that loading is enabled to start, the overlay is shown while the Javascript loads and Angular bootstraps.
Once Angular is loaded though, everything within <my-app> will be replaced with AppComponent template. As I explained in the comments beneath the OP, I need ongoing access to this loading overlay, because I show it during the loading of new routes (as users navigate from one routed component to another). So I had to include the same overlay div in the template
app.component.html
<div id="overlay" [class.loading]="showLoading"></div>
<router-outlet></router-outlet>
Now, when my loading$ observable fires, I change a class property showLoading and Angular takes care of updating the overlay since it is now part of AppComponent
app.component.ts
// set to true to show loading overlay. False to hide
showLoading:boolean = true;
ngOnInit(){
// show/hide overlay depending on value emitted
loading$.subscribe(loading => this.showLoading = loading);
}
Try to do like this:
<my-app>
<div class="your-class-for-loading"></div>
</my-app>
When my-app is ready, div will be automatically removed.

How to get work Infinite scroll depending on div container's scroll position?

I'm looking for a infinite scroll script, but can't find one which really fits my needs. I have found one which would be great, but the problem is that the script works after the User scrolls down using the browser SCROLLBAR. Instead it should load and display more data depending on the div "scroll" position.
How can i do that? It doesn't have to be this script but it should include a mysql query function so I can implement mine easily, because I'm really a newbie in Javascript, jQuery etc. A tutorial would do it also...but can't really find one. All of them are depending on the browser's scroll position.
That's the script I'm using:
github.com/moemoe89/infinite-scroll/blob/master/index.php
I made only one modification:
news_area{ width:400px; height:95px; overflow:auto;}
Thanks in advance!
Instead of $(window).scrollTop() use any container that you would want to get it's scrolling position from, like $('.scrollable').scrollTop().
$('.scrollable').on('scroll', function(){
var $el = $(this);
$('.scrolled').text($(this).scrollTop());
if( $el.innerHeight()+$el.scrollTop() >= this.scrollHeight-5 ){
var d = new Date();
$el.append('more text added on '+d.getHours()+':'+d.getMinutes()+':'+d.getSeconds()+'<br>');
}
});
div {
height: 50px;
border: 1px solid gray;
overflow: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Scrolled from top: <span class="scrolled">0</span></p>
<div class="scrollable">
text<br>
text<br>
text<br>
text<br>
text<br>
text<br>
</div>

Mobile website zoom into images like google maps

I have a mobile website and I like to insert images with an option to zoom by gesture. It should look like you zoom in on google maps, so that the other content has always the same size and only the image is zooming in. Is there any script for this? Or do I have to use iframes?
Greetz
Mik
For the gestures part, you can use a library like hammer.js to handle pinch events. You can find it HERE
For the zoom, you can use css transformation to scale an image (or div) apart from the rest of the page. In my demo below, clicking zoom in and zoom out buttons changes the CSS scale transformation value. In your case, you would handle the pinch events and change the scale accordingly.
NOTE: Updated according to Omar's comment below.
<div id="imgContainer" >
<img id="zoomImage" src="http://www.esa.int/var/esa/storage/images/esa_multimedia/images/2003/10/soho_image_28_october_2003/10098404-2-eng-GB/SOHO_image_28_October_2003_node_full_image.jpg" />
<div>
#imgContainer{
overflow: auto;
height: 400px;
}
$(document).on("click", ".zoomBtn", function(){
var id = $(this).prop("id");
if (id == 'in'){
curScale *= 1.25;
} else {
curScale *= 0.75
}
$("#zoomImage").css({
"transform": "scale(" + curScale + ")"
});
});
Here is a jQM zoom image DEMO
NOTE: If you are using SVG on an SVG canvas, you can scale by changing the viewport size.

Why do the pages blink/flicker after transitions in my jQuery Mobile PhoneGap app on iOS?

I have a jQuery Mobile app that I've converted to an iOS app using PhoneGap. I'm using version 1.1.0 of jQM.
I'm using "fade" transitions between pages (as I read they were less demanding).
When initially running the PhoneGap version of the app in the iPhone Simulator I was getting a flicker/flash after every page transition - as if the page was being displayed, cleared and then redisplay - all with a fraction of a second. Some thing happened when I ran it on the device.
I applied the advice in Sarah-Jane's answer to a similar question.
This fixed the problem in the simulator, but not on the actual device.
Has anyone experienced this problem, and found a solution?
This guy solved the problem - it worked for me:
http://outof.me/fixing-flickers-jumps-of-jquery-mobile-transitions-in-phonegap-apps/
CSS:
body {
/* Setting body margins to 0 to have proper positioning of #container div */
margin: 0;
}
/* #container div with absolute position and 100% width and height so it takes up whole window */
#container {
position: absolute;
width: 100%;
height: 100%;
}
JS:
$(document).one("mobileinit", function () {
// Setting #container div as a jqm pageContainer
$.mobile.pageContainer = $('#container');
// Setting default page transition to slide
$.mobile.defaultPageTransition = 'slide';
});
And wrap all your jQM pages in a single <div id="container">
Fade transition blinks mostly you should change it to slide or some other transition mode.
That might help
<meta name="viewport" content="width=device-width, user-scalable=no" />
use following code
$(document).ready(function()
{
$.mobile.defaultPageTransition = "none"
$.mobile.defaultDialogTransition = 'none';
$.mobile.useFastClick = true;
$.mobile.touchOverflowEnabled = true;
});

Hide iPhone HTML5 video play button

I want to hide the big play button that appears by default on the <video> element
Is it possible?
I don't have any iOS device handy to test, but perhaps try this:
video::-webkit-media-controls {
display:none !important;
}
It seems Apple has changed the shadow-dom again.
In order to hide the play button control you must use the following CSS:
/* This used to work for the parent element of button divs */
/* But it does not work with newer browsers, the below doesn't hide the play button parent div */
*::-webkit-media-controls-panel {
display: none!important;
-webkit-appearance: none;
}
/* Old shadow dom for play button */
*::-webkit-media-controls-play-button {
display: none!important;
-webkit-appearance: none;
}
/* New shadow dom for play button */
/* This one works! */
*::-webkit-media-controls-start-playback-button {
display: none!important;
-webkit-appearance: none;
}
A look at the shadow DOM in Safari iOS tells me that what you want (hidding only the big central play button) is:
video::-webkit-media-controls-start-playback-button {
display: none !important;
}
The answer from Ian hides everything including text tracks (closed captions ...)
Newer iOS versions display such play button when the device is in "Low power mode".
In the video source file you can simply change
controls= "false"
For the Safari CSS, which the native browser on ios, you can also try this hacky trick
.custom-video-controls {
z-index: 2147483647;
}
Here's a link to a details discussion on managing/hiding controls on HTML 5 video
http://css-tricks.com/custom-controls-in-html5-video-full-screen/
UPDATE OCTOBER 2021
All answers are outdated for iOS 13, 14, and 15. It appears because iOS low power mode prevents autoplay on all videos in the browser by default (to save power).
The best way to remove the annoying play button is to remove the autoplay tag on any video element and start playing the video when there is any user interaction.
React example below:
<video ref={playerRef} playsInline >
let playVideo = (event) => {
if (playerRef.current) {
playerRef.current.play()
}
}
Sidenote: the play button is hidden in a shadow dom that I am unable to figure out how to hide with external CSS modifications or even JS. If anyone has any ideas on how to hide a shadow dom element then that would be a better solution.
Based on Ian's answer
video::-webkit-media-controls {
opacity: 0;
}
This will hide all controls. Good for background videos that won't autoplay.
Today #2017 in iOS 10 this works:
.video-background::-webkit-media-controls-panel,
.video-background::-webkit-media-controls-start-playback-button {
display: none !important;
}
For webapps.
Works iOS 10.3 iPhone7 & Safari 10.1 on Mac as well. Thx to previous contributors.
I had also the issue that the element does not contain any "control" attribute at all.
'<style type="text/css">'+
'*::-webkit-media-controls-panel {'+
' display: none!important;'+
' -webkit-appearance: none;'+
' }'+
/* Old shadow dom for play button */
'*::--webkit-media-controls-play-button {'+
'display: none!important;'+
'-webkit-appearance: none;'+
'}'+
/* New shadow dom for play button */
/* This one works */
'*::-webkit-media-controls-start-playback-button {'+
'display: none!important;'+
' -webkit-appearance: none;'+
'}'+
+'</style>'
Try this:
video {
&::-webkit-media-controls {
display:none !important;
}
&::-webkit-media-controls-start-playback-button {
display: none!important;
-webkit-appearance: none;
}
}
Update:
IOS 13.*
video::slotted::-webkit-media-controls-container{
display:none !important;
visibility: hidden!important;
opacity: 0 !important;
-webkit-appearance: none !important;
}
IOS 14
changed selector to
:host::shadow::-webkit-media-controls-container{/* hide the element */}
helpful resource:
html5rocks shadow dom 201
As of 20 Oct 2022,
My solution was to remove autoplay from the video element and use HTMLMediaElement.play() on page load. The promise returned from play() will catch any issues with playing the video, else the video will play as usual. My implementation in React looks like this:
useEffect(() => {
ref &&
ref.current
.play()
.then(() => {})
.catch((err) => {
// Video couldn't play, low power play button showing.
});
}, []);
This should be a relief from having to deal with the inconsistent Shadow DOM properties.
Resources:
https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/play
You can't remove the play button. This video placeholder always appears as the doc says :
iPhone Video PlaceHolder. But maybe you can detect you're on an iphone and display an image with a link to your video instead of the video tag.
<img src="yourposter.png"/>
The video will be launched in a player just as a video tag.
According to this answer, in Google Chrome we can hide the big play button like this:
video::-webkit-media-controls-overlay-play-button {
display: none;
}
That might be useful if you want to hide it on Android as well as on iOS.
video::-webkit-media-controls { display:none !important; }
Didn't work for me on iOS, but
*::-webkit-media-controls-panel {
display: none!important;
-webkit-appearance: none;
}
/* Old shadow dom for play button */
*::--webkit-media-controls-play-button {
display: none!important;
-webkit-appearance: none;
}
/* New shadow dom for play button */
/* This one works */
*::-webkit-media-controls-start-playback-button {
display: none!important;
-webkit-appearance: none;
}
Worked perfect!
Yes you can do this! The trick is to "hide" the video controls, by not adding the "controls" attribute to your video tag. Then you let it be dynamically added a few seconds after the video starts to play, by appending the "controls" property to the tag using Javascript. Simply set the value to "controls" and it will dynamically appear in the DOM... as if you had added the controls to your video tag's HTML. Adjust the timer as needed.
<video id="some-video-id" src="some-video-url" poster="some-thumbnail-url" />
Start the Video
<script type="text/javascript">
var oVideoTag = document.getElementById('some-video-id');
var oLink = document.getElementById('startVideoLink');
if (oLink && oVideoTag) {
oLink.addEventListener('click',function(e) {
oVideoTag.play();
setTimeout(function() {
oVideoTag.controls = 'controls';
},2500);
},false);
}
</script>