Javascript + CSS: Converting from absolute positioned elements to CSS Transforms (left, top, width, height to translateX, translateY, scale) - webkit

I'd like to convert a Javascript carousel to work smoothly on the iOS devices iPad and iPhone, and Android devices which use webkit that is able to take advantage of hardware acceleration of CSS transforms.
Is there already a library or some snippets of code that would allow position and size setting?
I found jquery.animate-enhanced which may be close but it requires animations, and also does feature detection - I want to do something simpler, it looks significantly more complex than that.
There are several complexities I suspect the solution needs to address:
-Simple reuse of code to use either top / left CSS attributes or CSS transforms with translation (and any recalculation needed to convert them)
-Using the scale transform instead of setting width and height
Setup steps like:
-Setting -webkit-transform-style to preserve-3d
-Setting -webkit-transform-origin if needed (and what to?)

I see Zepto in the tags, so it seems like you've considered it and it didn't work? Zepto does use CSS3 for its animations.
I would try something like this as a first guess. You'll need to do your feature detection outside of the 'animateLeft' method because the animation apis are different between jquery and zepto.
Maybe something like this (psuedocode):
isTouchy = Modernizr.touch
var slideRight = function() {
if (isTouchy) {
Zepto('#carosel').animate(...)
} else {
jQuery('#carosel').slideRight() //sorry, don't know the api
}
}
http://zeptojs.com/#animate
http://modernizr.com/

Related

getUserMedia (Selfie) Full Screen on Mobile

I've the following constraints which are working perfectly fine over Chrome in Desktop (simulating mobile resolution)
const constraints = {
audio: false,
video: {
width: screen.width,
height: screen.height
}
};
navigator.mediaDevices.getUserMedia(constraints).then(stream => {})
However when actually trying this on iPhone / Safari the camera doesn't respects this at all and gets super small or distorted - removing the width / height from the constraints makes it better ratio but not full screen at all, just centralized.
I've also tried with min / max constraints without lucky.
Is there any way to get this working on iPhones?
I have built a few AR Websites which are mobile first. When you request a resolution the web browser sees if the resolution exists, and if it doesn't it then decides if it should emulate the feed for you. Not all browsers do emulation (even though it is part of the spec). This is why it may work in some browsers and not others. Safari won't emulate the resolution you are asking for with the camera you have picked (I presume the front).
You can read more about this here (different problem, but provides a deeper explaination): Why the difference in native camera resolution -vs- getUserMedia on iPad / iOS?
Solution
The way I tackled this is:
Without canvas
Ask for a 720p feed, fallback to 480p feed if 720 gives an over-constrained error. This will work cross-browser.
Have a div element which is 100% width and height, fills the screen, and sets overlay to hidden.
Place the video element connected to the MediaStream inside, make it 100% height of the container. The parent div overlay hidden will in effect crop the sides. There will be no feed distortion.
With canvas
Do not show the video element, use a canvas as the video view. Make the canvas the same size as your screen or the same aspect ratio and use CSS to make it fill the screen (latter is more performant).
Calculate the top, left, width and height variables to draw the video in the canvas (make sure your calculation centers the video). Make sure you do a cover calculation vs fill. The aim is to crop the parts of the video which do not need to be shown (I.e. like the descriptions of various methods in https://css-tricks.com/almanac/properties/o/object-fit) . Example on how to draw video into a canvas here: http://html5doctor.com/video-canvas-magic/
This will give you the same effect of what you are looking for. Production examples of something similar.
https://www.maxfactor.com/vmua/
https://demo.holitionbeauty.com/
P.s. when I get time I can code an example, short on hours this week.
There are a couple of quirks on mobile gUM() you need to know about.
First, if the device is in portrait orientation things work weirdly. You need to swap the width and height. So, let's say you're on a 480x640 device (do those even exist? who cares? it's an example). To get the appropriate size video you need
const constraints = {
audio: false,
video: {
width: screen.height,
height: screen.width
}
};
I can't figure out exactly why it's like this. But it is. On iOS and Android devices.
Second, it's hard to get the cameras to deliver exactly the same resolution as the device screen size. I tweak the width and height to make them divisible by eight and I get a decent result.
Third, I figure the sizes I need by putting a <video ...> tag in my little web app with CSS that makes it fill the browser screen, then querying its size with
const rect = videoElement.getBoundingClientRect()
const width = rect.width > rect.height ? rect.width : rect.height
const height = rect.width > rect.height ? rect.height : rect.width
This makes the mobile browser do the work of figuring out what size you actually need, and adapts nicely to the browser's various toolbars.

React Native best practice for positioning, favor percentages and calculations over flex?

Coming from a web background it would be considered bad practice to (or not possible) to absolutely position elements and calculate their position in a layout based on the window dimensions. In react-native, we have access to the dimensions of the view port through the React.Dimensions.
For example: let {height, width} = Dimensions.get('window')
I can now use that to center a 100px element by setting it so:
left: (width/2) - 50
I much prefer this to using more traditional css techniques. Is there a reason why this shouldn't be done? In a browser the viewport could change if the user resizes the window, but on mobile the viewport size will be static.
In my opinion, favor the declarative and dynamic solution when possible (flex over number calculations). But it's a mix of both eventually for a lot of apps.
This blog post compares some layout methods in react native and could help you with better understanding when to use what.

Bootstrap addons not working properly on different resolutions

It looks like there is a bug in Bootstrap. If you change resolution, for example with ctrl + (+/-) in your browser the addons are not properly adjusted. It looks like this:
Notice the wrong sizes of addons.
Is there a simple way to fix this?
No, there is no simple way (and quite possibly no way period) to fix problems related to the type of zooming that you're referring to (as opposed to the viewport-width-based zooming that you get when using the pinch gesture on touch-based devices).
Per Bootstrap's documentation:
Page zooming inevitably presents rendering artifacts in some components, both in Bootstrap and the rest of the web. [... these issues] often have no direct solution other than hacky workarounds.
Zooming in and out is not changing the resolution at all its zooming and is completely different from changing the view port's aspect ratio and dimensions.
Give the input area a fixed width like input {width:100px}

how to add parallax to a Scrollview?

I want to use famo.us standard Scrollview but have a background image which is scrolling at a different speed to give a parallax effect.
Rather than setting up timers and getPosition stuff, i was wondering if there's a way to hook into an event stream, or somehow pipe the Scrollviews position into a transformation that's applied to another object? For example use the modifier within the scrollview and a modifier chain and then apply that to another imageSurface?
The examples are a bit thin here so would appreciate any pointers.
To answer your question, the way to pipe scroll events is to use the sync property of scrollview to get updates on scroll.
That is..
scrollview.sync.on('start',function(e){ // Do Something });
scrollview.sync.on('update',function(e){ // Do Something });
scrollview.sync.on('end',function(e){ // Do Something });
However for rendering objects in sync and ensuring precision on such, I have found the Engine prerender function to be wonderful.
So I would do something like this.
Engine.on('prerender',function(){
// Divide by scalar to get effect
var parallaxEffect = 2.0
var bgPos = -contentScrollview.getPosition() / parallaxEffect;
imageView.state.setTransform(Transform.translate(0,bgPos,0)));
})
Hope these pointers help!
This is a bit of a lazy answer, but let me link you to one of the famous demos created by their HackerLab alumni. It demonstrates using famous to create some complex scrolling/swiping animations.
I've learned a lot about Famo.us from the code in the demos, however this hasn't been made available to those outside the beta list yet. So I cloned the project files.
UltraVisual: A Parallax Scrolling Demo
https://github.com/KraigWalker/famous-UltraVisual
A more advanced scrolling animation demo
https://github.com/KraigWalker/famous-IFTTT
Hope this helps you out!

How to use image qualifiers in WebView in Windows 8 without specifying height and width

I have a webview in my Windows 8 (Metro) app that I will use to display much of my content. The webview automatically scales any CSS dimensions to 100%, 140%, and 180%. This means that when I specify:
#square {
width:100px;
height:100px;
background-color:white;
}
...we get a nice square that is 100, 140, or 180 device pixels, depending on the display. So far, so good.
Further, if I supply an image that is 100px square, the OS correctly scales it to 140 and 180 as appropriate on higher density screens.
Further still, if I supply versions of the image that are 100px, 140px, and 180px, and I indicate the size as 100px in the CSS, like this:
#my_image {
width:100px;
height:100px;
}
The OS uses an area that is 100 dp square (that is to say, 100, 140, or 180 device pixels square as appropriate) and automatically selects the right image. So far, still good.
The problem occurs when I try to use images with density qualifiers without naming a literal size in CSS. Why would I want to do this? I have lots of images with variable sizes. I'd prefer to just allow the webview to infer the appropriate size based on the dimensions of the images.
So I expect that if I supply 100, 140, and 180 versions of an image, the OS will be smart enough to say, "Ah, this is a 100-dp image that happens to have additional versions available."
What actually happens, however, is this.
I supply images:
square.scale-100.png
square.scale-140.png
square.scale-180.png
The OS picks the appropriate one. On a 180% screen, it picks the version that is 180 device pixels square. Recall, however, that we made it 180 device pixels because it was the 180% version of the 100 dp image. We want it to actually take up only 100x100 dp of space.
However, the OS takes 180 as the size in DP. So it scales it by 180% again.
How can I avoid this double-scaling? Any pointers would be awesome!
We've figured out a solution to this that I'm sharing in case it helps anyone else.
The solution is to include dynamically written CSS that zooms images using a factor that is the inverse of the current scale factor.
The current scale factor is available to app code, but not to Javascript running in a WebView. From the point of view of such Javascript, all dimensions are already scaled. So, for example, window.devicePixelRatio is no good -- it always returns 1.
You can obtain the current scale factor in app code like so:
ResolutionScale scale = DisplayInformation.GetForCurrentView().ResolutionScale;
From this, you can derive a zoom factor like this:
float imageZoomFactor = 1.0F;
switch (DisplayInformation.GetForCurrentView().ResolutionScale)
{
case ResolutionScale.Scale140Percent:
imageZoomFactor = (1.0F / 1.4);
break;
// etc
}
You can pass this into your Javascript in one of several ways. Since we were reading HTML from the app bundle and using WebView.NavigateToString, we created a placeholder in the Javascript that we replace in the string. The Javascript looks like this:
<!-- Scale images so that their sizes map 1:1 to device pixels -->
<script type="text/javascript" language="javascript">
document.write('<style type="text/css">img {zoom:' + HOSTING_CODE_SUPPLIED_ZOOM_FACTOR + ';}</style>');
</script>
Now when you use an image tag without specifying explicit dimensions, it works properly. For example, an image that is 180px x 180px, created for the purpose of being displayed at 100dp x 100dp in 180% mode, is displayed correctly using 180 device pixels.
One caveat is that if you have CSS that explicitly sizes an image, you need to cancel the zoom. So, for example:
#my_explicit_image {
width:200px;
height:200px;
zoom:normal; /* cancel the zoom on img since we're being explicit */
}
If you don't include the last line, the zoom specified on img will apply to the dimensions you specify here.
Hope this helps someone out there!