I have an Android application which uses WebView to load the GUI using HTML. There is a <canvas> element into which i draw charts using Chart.js Javascript library for plotting charts.
It was tested on 3 devices. On two of them it works fine (Android 2.2 and 2.6), but on a later vesion of android (4.1.2) the canvas makes it double: all the charts are visible twice in the canvas, one of them is shifted a bit up and to the left.
What is the problem with the canvas? Why does it double the things rendered? How can i made it render only once?
Here's the code:
HTML:
<canvas id="graph_canvas"></canvas>
JavaScript:
var canvas=document.getElementById("graph_canvas");
canvas.height=200;
canvas.width=200;
var graphSelection=document.getElementById("graphSelection");
var ctx = canvas.getContext("2d");
var data_=JSON.parse(JI.getGraphData(graphSelection.value));
var myNewChart = new Chart(ctx).Line(data_);
Where graphSelection is a <select> element with which we select the chart,
JI.getGraphData returns JSON data for Chart.js.
If you do not want problems caused by "position: fixed;" on element,
canvas parent element should not have css property "overflow" with value "hidden".
So define something like "overflow: visible;" on parent element.
Try this:
// If Samsung android browser is detected
if (window.navigator && window.navigator.userAgent.indexOf('534.30') > 0) {
// Tweak the canvas opacity, causing it to redraw
$('canvas').css('opacity', '0.99');
// Set the canvas opacity back to normal after 5ms
setTimeout(function() {
$('canvas').css('opacity', '1');
}, 5);
}
I met this problem too. I solved it by using position:relative , left and -webkit-transform instead margin;. The problem was solved accidentally.
Related
I have a webservice that returns GeoJson polygons (timezones) and I'm trying to draw them in a layer over the map object using GeoJsonLayer
I already tested the GeoJson file in geojson.io and it looks fine (image at the bottom) but when I add it to the map its not being filled and some extra lines appear down south, it looks like its not closing the poly properly, this is the code I'm using to load the file (I have it locally in raw folder at the moment)
val layer = GeoJsonLayer(mGoogleMap, R.raw.sample_timezones_response, requireContext())
layer.addLayerToMap()
val polygonStyle = GeoJsonPolygonStyle()
polygonStyle.fillColor = resources.getColor(R.color.color_main_green_200, null)
polygonStyle.zIndex = 10000f
layer.features.forEach { it1 ->
it1.polygonStyle = polygonStyle
}
This is the json file I'm trying with.
EDIT: the original json file was not followinf the right-hand rule, I fixed it with python lib: geojson-rewind, this is the fixed version that passes the test in https://geojsonlint.com/
I tried also updating to the latest version of the library (18.0.2) and updating the renderer to the newer one but it displays in the same way.
This is how it looks on android:
This is how its supose to look, same json file in geojson.io:
When validating the geojson, I get the error:
Line 1: Polygons and MultiPolygons should follow the right-hand rule
https://www.rfc-editor.org/rfc/rfc7946#section-3.1.6
A linear ring MUST follow the right-hand rule with respect to the
area it bounds, i.e., exterior rings are counterclockwise, and
holes are clockwise.
I am currently creating a game in HTML5 using Canvas. Right now, it works pretty well with all the internet browsers except Google Chrome for Android which refuses to display my "filltext" commands...
I noticed that the game worked when I disabled the 2D acceleration of Chrome Android through chrome://flags/... but i obviously cannot ask users to disable their 2D acceleration feature of Chrome prior to playing. Does anybody have a solution to display my filltext under google chrome for android?
You will find below the code: basically, i can see the text in all the browsers except chrome for android... it draws the background and not the text.
//Get the canvas
var canvas2 = document.getElementById("layer2");
var ctx2 = canvas2.getContext("2d");
//Rendering function (draw background and draw image)
var render = function () {
ctx2.drawImage(background, 0, 0);
ctx2.fillText("Lolo", 400, 400);
}
// main loop
var main = function () {
var now = Date.now();
var delta = now - then;
update(delta / 1000);
render();
then = now;
};
var then = Date.now();
setInterval(main, 1);
Thank you!
Laurent
This appears to be a bug with the software renderer, you will need to make your canvas at least 256 pixels in size to force it in to the GPU path. Paul Lewis face a similar problem and blogged about it
If you can provide a reduced demo, I will file the Bug against Chrome (or you can do it at http://m.crbug.com/new)
I'm trying to animate an element by CSS3 transtions using translate3d: JSFiddle.
// for start animation
$("#content")
.css("-webkit-transition", "all 100s");
.css("-webkit-transform", "translate(0, -900px)");
// for stop animation
$("#content")
.css("-webkit-transition", "none");
In desktop Chrome and Safari is good, but in the default browser on Android 4.1.x (SGSII, Galaxy Nexus, etc) this approach does not work - transition does not stop. Additionally, I note that the situation is only a relatively translate3d: with translate and position CSS props (e.g. "top", "left") it works.
The transition implementation on Android 4 seems to be buggy in cases where a transitioning hardware-rendered layer is canceled by adjusting the webkitTransitionDuration to 0 (and setting webkitTransition to 'none' or '' often implies this). This can be circumvented by using a transition duration of .001ms or similar, although this very likely still draws multiple frames.
A more practical work-around on at least certain devices is to use a negative value for the webkitTransitionDelay, forcing a new transition to take effect, but choosing this value such that the transition starts directly in its finished state.
Like so:
e.style.webkitTransition = '-webkit-transform linear 10s';
e.style.webkitTransform = 'translate3d(100px,100px,0)';
# now cancel 10s-long transition in 1s and reset transformation
setTimeout(function() {
e.style.webkitTransitionDelay = '-10s'
e.style.webkitTransform = 'translate3d(0,0,0)';
}, 1000)
Here is what I discovered with some experimentation:
Stopping a running translate2d or 3d on chrome, safari, firefox, and iphone webview can be done by setting a transition of "none" or a transition with a negative or 0 time delay and giving a new translation to the current position as described above.
This however does not work for android webview. The only solution I could find for android was to set the transition delay to a small positive number like .001s and giving a translate for the current position.
Note that in iphone webview the solution of a negative transition delay is preferable to "none" or a small positive number which will flash the final position of the ongoing transition before performing the preempting following transition.
This solves my (very similar) problem:
$el.removeClass('THE_ANIMATION').css('opacity', 0.99);
window.setTimeout(function () {
$el.css('opacity', 1);
}, 0);
When you hide the addressbar in WebbApps you got nearly the feeling of native Apps. Unfortunately, to hide the address bar works in jQuery mobile only if the content is large enough. If the content is too small it does not work - also with fullscreen and fixed footer - see http://jquerymobile.com/demos/1.2.0/docs/toolbars/bars-fixed.html. Reason appears to be a bug in the browser in Android. If the content is too small the jQuery funktion $(window).height() delivers only 450px as screen height (I'm using Android 2.3.6 with a Galaxy S2). The height of the addressbar is missing. Is the content big enough the function delivers 508px - as expected. Also a quite good approach - http://www.semicomplete.com/blog/tags/jquery%20mobile -does not work. I found a solution which works but need a delay of 500ms. It brings a flipping adressbar when you load a page for a small time. Is there an another approch, that there is no flipping of the addressbar?
But maybe someone has an idea how this could work even better. And does it work well with iOS? It would be great if someone could test this with an iPhone.
Thanks in advance.
Here the code:
var fixgeometry = function() {
/* Calculate the geometry that our content area should take */
var header = $(".header:visible");
var footer = $(".footer:visible");
var content = $(".content:visible");
var viewport_height = $(window).height()+60; /*Here is the idea! Make it bigger here and make it later smaller*/
var content_height = viewport_height - header.outerHeight() - footer.outerHeight();
/* Trim margin/border/padding height */
content_height -= (content.outerHeight() - content.height());
content.height(content_height);
setTimeout(function(){
window.scrollTo(0, 1);
content.height(content_height-60); }, 500 );
};
$(document).ready(function(){
$(window).bind("orientationchange resize pageshow", fixgeometry);
});
The scrollTo-function is implemented in jQuery, but it doesnt work after an oriantationchange or an input in a textfield. So its necessary here in the setTimeout-function.
I'm using Flash CS 5 and Flex 4, both to build an AIR application for android. I would like to know how to allow the user to move content(image or text) up and down(like a map,in this case only vertically).
There are no touch UI controls available yet, so you need to implement it yourself. Here's a little bit of code that might help get you started. I wrote it on the timeline so that I could test it quickly. You'll need to make a couple adjustments if you're using it in a class.
The variable content is a MovieClip that is on the stage. If it is larger than the height of the stage, you'll be able to scroll it by dragging it with the mouse (or with your finger on a touch screen). If it is smaller than the height of the stage, then it won't scroll at all because it doesn't need to.
var maxY:Number = 0;
var minY:Number = Math.min(0, stage.stageHeight - content.height);
var _startY:Number;
var _startMouseY:Number;
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
function mouseDownHandler(event:MouseEvent):void
{
_startY = content.y;
_startMouseY = mouseY;
stage.addEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler, false, 0, true);
stage.addEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler, false, 0, true);
}
function stage_mouseMoveHandler(event:MouseEvent):void
{
var offsetY:Number = mouseY - _startMouseY;
content.y = Math.max(Math.min(maxY, _startY + offsetY), minY);
}
function stage_mouseUpHandler(event:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_MOVE, stage_mouseMoveHandler);
stage.removeEventListener(MouseEvent.MOUSE_UP, stage_mouseUpHandler);
}
Alternatively, you could use the scrollRect property. That one is pretty nice because it will mask the content to a rectangular region for you. If you just change y like in the code above, you can draw other display objects on top of the scrolling content to simulate masking. It's faster than scrollRect too.