View Full Version : Jittering at switching image in a View
MBachstein
03-05-2008, 01:25 AM
Hello,
I have written an application in which you can switch between images when you click on a navigation button. As the image needs some time to be completly loaded, there is a black gap in the view between the click and the moment the image is shown, causing a flickering.
Therefore I created TWO views on top of each other which change their activation when a new image is loaded. As soon as the image is completely loaded the view with the new image becomes activated.
Now there is a problem. The image only changes every second time, when I click on a navigation button (first/next/previous/last). On every second click the image, which has been skipped, becomes visible for a subsecond and then the second image becomes visible. Fortunately, this is very fluently and there is no flickering effect any more.
Now I do not understand why the view does not change its content on every single click on a navigation button.
Here are some extracts of my source code:
<Image name="image1" id="image1" ...> // Image extends="view"
<handler name="onload">
image2.active = false;
image1.active = true;
show();
</handler>
</Image>
// image2 vice versa
<method name="loadImage">
<![CDATA[
var curImgView;
var newImgView;
if (imageBox.imageBackground.image1.active) {
curImgView = imageBox.imageBackground.image1;
newImgView = imageBox.imageBackground.image2;
} else {
curImgView = imageBox.imageBackground.image2;
newImgView = imageBox.imageBackground.image1;
}
// generating imgURL
imgUrl = ...
newImgView.unload();
newImgView.setSource(imgUrl, "none");
]]>
</method>
Maybe someone can help me.
Thanks in advance,
Marc
rcyeager
03-05-2008, 09:15 AM
Can you provide a self-contained test program that demonstrates the issue?
Robert
http://www.qrowd.com
http://www.cooqy.com
MBachstein
03-06-2008, 04:03 AM
Hi,
here is a test file. You just need to set some image sources in line 111.
When you click on the next button and then on the previous button you'll see that the image, which should have been shown on the first click, is visible for a subsecond.
Marc
rcyeager
03-06-2008, 09:57 AM
When I ran the test program, two images overlayed each other continually.
I changed it to get better results like so:
<canvas height="100%" width="100%">
<library>
<class name="MyImage" extends="view">
<attribute name="active" type="boolean" value="false"/>
<handler name="onload"><![CDATA[
show();
]]>
</handler>
<method name="show"><![CDATA[
this.animate('opacity', 1, 100);
]]>
</method>
<method name="hide"><![CDATA[
this.animate('opacity', 0, 100);
]]>
</method>
</class>
</library>
<attribute name="currentIndex" value="1" type="number"/>
<simplelayout axis="y" spacing="5" inset="50"/>
<!-- This box contains the buttons for image navigation -->
<view name="functionBox" width="450" x="120" y="0" height="45"
bgcolor="#CCCCCC" options="ignorelayout">
<simplelayout axis="x" spacing="5" inset="5"/>
<!-- Button first/initial Image -->
<button name="tbbfirst" text="first/init" y="3" width="100" height="30">
<handler name="onclick"><![CDATA[
canvas.currentIndex = 1;
canvas.loadImage();
]]>
</handler>
</button>
<!-- Button previous Image -->
<button name="tbbprev" text="previous" y="3" width="100" height="30">
<handler name="onclick"><![CDATA[
if (canvas.currentIndex > 1) {
canvas.currentIndex--;
canvas.loadImage();
}
]]>
</handler>
</button>
<!-- Button next Image -->
<button name="tbbnext" text="next" y="3" width="100" height="30">
<handler name="onclick"><![CDATA[
if (canvas.currentIndex < 8) {
canvas.currentIndex++;
canvas.loadImage();
}
]]>
</handler>
</button>
<!-- Text field, which shows Image number -->
<text name ="textfield" id="tf" text="image nr: undefined">
</text>
</view>
<view name="imagecontainer" x="${parent.width/2 - this.width/2}" width="512" height="512" bgcolor="#000000">
<MyImage name="image1" id="image1" stretches="both"
x="${parent.width / 2 - this.width / 2}"
y="${parent.height / 2 - this.height / 2}" visible="false" opacity="0">
<handler name="onload">
image2.setVisible(false); //RCY
this.setVisible(true); //RCY
</handler>
</MyImage>
<MyImage name="image2" id="image2" stretches="both"
x="${parent.width / 2 - this.width / 2}"
y="${parent.height / 2 - this.height / 2}" visible="false" opacity="0">
<handler name="onload">
image1.setVisible(false); //RCY
this.setVisible(true); //RCY
</handler>
</MyImage>
</view>
<method name="loadImage"><![CDATA[
var curImgView;
var newImgView;
if (imagecontainer.image1.active) {
Debug.write(" => paint new image in view image2");
curImgView = imagecontainer.image1;
newImgView = imagecontainer.image2;
} else {
Debug.write(" => paint new image in view image1");
curImgView = imagecontainer.image2;
newImgView = imagecontainer.image1;
}
//actualize text of image nr
tf.setText("image nr: "+canvas.currentIndex);
// sources must be set !
if (this.currentIndex == 1) {
var imgUrl = "http://www.cooqy.com/images/cooqy_logo.gif";
} else if (this.currentIndex == 2) {
var imgUrl = "http://www.qrowd.com/images/qrowd_logo.gif";
} else if (this.currentIndex == 3) {
var imgUrl = "http://www.cooqy.com/images/cooqy_logo.gif";
} else if (this.currentIndex == 4) {
var imgUrl = "http://www.qrowd.com/images/qrowd_logo.gif";
} else if (this.currentIndex == 5) {
var imgUrl = "http://www.cooqy.com/images/cooqy_logo.gif";
} else if (this.currentIndex == 6) {
var imgUrl = "http://www.qrowd.com/images/qrowd_logo.gif";
} else if (this.currentIndex == 7) {
var imgUrl = "http://www.cooqy.com/images/cooqy_logo.gif";
} else if (this.currentIndex == 8) {
var imgUrl = "http://www.qrowd.com/images/qrowd_logo.gif";
}
newImgView.unload();
newImgView.setSource(imgUrl, "none");
Debug.write(" load Image URL: "+imgUrl.toString());
]]>
</method>
</canvas>
Now each image only appears after it finishes loading. You can replace the setVisible calls with your fade animations, if you want to use transitions.
Robert
http://www.qrowd.com
http://www.cooqy.com
MBachstein
03-07-2008, 01:32 AM
Hi Robert.
I tested your changes. Now there is again a black image between the image changes causing a flickering during image navigation.
When I ran the test program, two images overlayed each other continually.
That is exactly what I want. By doing it this way I avoid that the new image is loaded in the same image view (causing a black image for a short time in this view). Therefore there are two image views, which change their activation when a navigation button is pressed and the new image is completely loaded in the other view. The view with the old image becomes deactivated.
Now each image only appears after it finishes loading.
This is unfortunately not the case.
The effect with the "black image" between image changes does not occur when the new image is already in your cache. Therefore you have to delete the cache in your browser before you start the application and you should also load completely different 8 pictures. Otherwise you reload the picture of the cache.
You can replace the setVisible calls with your fade animations, if you want to use transitions.
You deactivated the image view switches by deleting the lines where the activations are set.
I added them again and changed the order of the two .setvisible(), so that the new image view is firstly set visible and THEN the other image view (with the old image) is set invisible.
Unfortunately there is still a "black image" between the image changes:
[...]
<view name="imagecontainer" x="${parent.width/2 - this.width/2}" width="512" height="512" bgcolor="#000000">
<MyImage name="image1" id="image1" stretches="both"
x="${parent.width / 2 - this.width / 2}"
y="${parent.height / 2 - this.height / 2}" visible="false" opacity="0">
<handler name="onload">
this.setVisible(true); //Marc
image1.active = true; //Marc
image2.active = false; //Marc
image2.setVisible(false); //Marc
</handler>
</MyImage>
<MyImage name="image2" id="image2" stretches="both"
x="${parent.width / 2 - this.width / 2}"
y="${parent.height / 2 - this.height / 2}" visible="false" opacity="0">
<handler name="onload">
this.setVisible(true); //Marc
image2.active = true; //Marc
image1.active = false; //Marc
image1.setVisible(false); //Marc
</handler>
</MyImage>
</view>
[...]
Marc
MBachstein
03-07-2008, 05:14 AM
Hi,
I solved the problem.
Instead of using .show() it ought to be .bringToFront() and all .setVisible() have to be deleted.
Now it is perfect. :)
Marc
vBulletin® v3.8.4, Copyright ©2000-2012, Jelsoft Enterprises Ltd.