In my actionscript 3 i have a textfield, which i fill with the messages (get them from the webservice). Not all the messages are visible, so every (for Example) 5s i'm moving them vertically to the top.
To do that, i'm using the Tween effect, but the thing is, that it moves only the visible text and not the rest text together (the invisible one).
When scrolling - i can see the rest text.
Image to show the situation (Sorry for my skills):
Here are some code: Function to fill messages object. Plus count how many lines every message will take to display ( so i could easilly use the tween effect (From - to))
private function getNewMsg(e:ResultEvent):void
{
size = e.result.toString().split(" ").length - 1;
for (var i=0; i<size; i++)
{
smsList.push(new smsItem(e.result[i].Id, e.result[i].text));
}
summ = 0;
for (var d=0; d<size; d++)
{
textfield.appendText(smsList[d].Text.toUpperCase()+'\n');
if (d >= 1)
{
smsList[d].Lines = textfield.numLines - summ;
summ += smsList[d].Lines;
}
else
{
smsList[d].Lines = textfield.numLines-1;
summ += smsList[d].Lines + 1;
}
}
twEnd = smsList[1].Lines * (-30.5);
}
And on timer i'm starting the Tween:
function timerHandler(e:TimerEvent):void
{
myTweenX = new Tween(textfield, "y", None.easeIn, twStart, twEnd, 4, true)
myTweenX.addEventListener(TweenEvent.MOTION_FINISH, tweenCompleted);
}
function tweenCompleted(e:TweenEvent):void
{
twInd++;
twStart = twEnd;
twEnd += smsList[twInd].Lines * (-30.5);
}
Found the problem. Because of my fixed textfield height, text wasn't. After made the textfields height auto size, evrything got fixed.
Related
Currently I am plotting the graph with two data plots(two lines on the graph), when I click on one line "indexOfVisiblePointClosestToPlotAreaPoint" method giving me right index and other one throwing me wrong one, not even closest visible one its skipping/jumping multiple points in between. Ex: if I click on index number 20 it jumps to 15 or 25 vice versa. Here is the calculation to find the index
-(NSUInteger)indexOfVisiblePointClosestToPlotAreaPoint:(CGPoint)viewPoint
{
NSUInteger dataCount = self.cachedDataCount;
CGPoint *viewPoints = calloc(dataCount, sizeof(CGPoint));
BOOL *drawPointFlags = calloc(dataCount, sizeof(BOOL));
[self calculatePointsToDraw:drawPointFlags forPlotSpace:(CPTXYPlotSpace *)self.plotSpace includeVisiblePointsOnly:YES numberOfPoints:dataCount];
[self calculateViewPoints:viewPoints withDrawPointFlags:drawPointFlags numberOfPoints:dataCount];
NSInteger result = [self extremeDrawnPointIndexForFlags:drawPointFlags numberOfPoints:dataCount extremeNumIsLowerBound:YES];
if ( result != NSNotFound ) {
CGFloat minimumDistanceSquared = CPTNAN;
for ( NSUInteger i = (NSUInteger)result; i < dataCount; ++i ) {
if ( drawPointFlags[i] ) {
CGFloat distanceSquared = squareOfDistanceBetweenPoints(viewPoint, viewPoints[i]);
if ( isnan(minimumDistanceSquared) || (distanceSquared < minimumDistanceSquared)) {
minimumDistanceSquared = distanceSquared;
result = (NSInteger)i;
}
}
}
}
free(viewPoints);
free(drawPointFlags);
return (NSUInteger)result;
}
Are you checking the plot parameter passed in the delegate method? The touch will register on the frontmost plot if there are any points within the plotSymbolMarginForHitDetection. It won't even check the other plot unless nothing hits on the front one. With two lines close together like that, you'll need to use a small hit margin to make sure touches register on the right plot.
I have two styles of interactions, one highlights the feature, the second places a tooltop with the feature name. Commenting both out, they're very fast, leave either in, the map application slows in IE and Firefox (but not Chrome).
map.addInteraction(new ol.interaction.Select({
condition: ol.events.condition.pointerMove,
layers: [stationLayer],
style: null // this is actually a style function but even as null it slows
}));
$(map.getViewport()).on('mousemove', function(evt) {
if(!dragging) {
var pixel = map.getEventPixel(evt.originalEvent);
var feature = null;
// this block directly below is the offending function, comment it out and it works fine
map.forEachFeatureAtPixel(pixel, function(f, l) {
if(f.get("type") === "station") {
feature = f;
}
});
// commenting out just below (getting the feature but doing nothing with it, still slow
if(feature) {
target.css("cursor", "pointer");
$("#FeatureTooltip").html(feature.get("name"))
.css({
top: pixel[1]-10,
left: pixel[0]+15
}).show();
} else {
target.css("cursor", "");
$("#FeatureTooltip").hide();
}
}
});
I mean this seems like an issue with OpenLayers-3 but I just wanted to be sure I wasn't overlooking something else here.
Oh yeah, there's roughly 600+ points. Which is a lot, but not unreasonably so I would think. Zooming-in to limit the features in view definitely helps. So I guess this is a # of features issue.
This is a known bug and needs more investigation. You can track progress here: https://github.com/openlayers/ol3/issues/4232.
However, there is one thing you can do to make things faster: return a truthy value from map.forEachFeatureAtPixel to stop checking for features once one was found:
var feature = map.forEachFeatureAtPixel(pixel, function(f) {
if (f.get('type') == 'station') {
return feature;
}
});
i had same issue, solved a problem by setInterval, about this later
1) every mouse move to 1 pixel fires event, and you will have a quee of event till you stop moving, and the quee will run in calback function, and freezes
2) if you have an objects with difficult styles, all element shown in canvas will take time to calculate for if they hit the cursor
resolve:
1. use setInterval
2. check for pixels moved size from preview, if less than N, return
3. for layers where multiple styles, try to simplify them by dividing into multiple ones, and let only one layer by interactive for cursor move
function mouseMove(evt) {
clearTimeout(mm.sheduled);
function squareDist(coord1, coord2) {
var dx = coord1[0] - coord2[0];
var dy = coord1[1] - coord2[1];
return dx * dx + dy * dy;
}
if (mm.isActive === false) {
map.unByKey(mm.listener);
return;
}
//shedules FIFO, last pixel processed after 200msec last process
const elapsed = (performance.now() - mm.finishTime);
const pixel = evt.pixel;
const distance = squareDist(mm.lastP, pixel);
if (distance > 0) {
mm.lastP = pixel;
mm.finishTime = performance.now();
mm.sheduled = setTimeout(function () {
mouseMove(evt);
}, MIN_ELAPSE_MSEC);
return;
} else if (elapsed < MIN_ELAPSE_MSEC || mm.working === true) {
// console.log(`distance = ${distance} and elapsed = ${elapsed} mesc , it never should happen`);
mm.sheduled = setTimeout(function () {
mouseMove(evt);
}, MIN_ELAPSE_MSEC);
return;
}
//while multithreading is not working on browsers, this flag is unusable
mm.working = true;
let t = performance.now();
//region drag map
const vStyle = map.getViewport().style;
vStyle.cursor = 'default';
if (evt.dragging) {
vStyle.cursor = 'grabbing';
}//endregion
else {
//todo replace calback with cursor=wait,cursor=busy
UtGeo.doInCallback(function () {
checkPixel(pixel);
});
}
mm.finishTime = performance.now();
mm.working = false;
console.log('mm finished', performance.now() - t);
}
In addition to #ahocevar's answer, a possible optimization for you is to utilize the select interaction's select event.
It appears that both the select interaction and your mousemove listener are both checking for hits on the same layers, doing double work. The select interaction will trigger select events whenever the set of selected features changes. You could listen to it, and show the popup whenever some feature is selected and hide it when not.
This should reduce the work by half, assuming that forEachFeatureAtPixel is what's hogging the system.
been fighting with this problem for a good 3 hours now, and i figured it was finally time to ask some professionals.
My problem is that i want to make a scrollbar, and I've figured out that i want to make it by using two integers and then give every item in the list an ID, and then say that all the items that has an ID thats in between the two integers are going to be shown, and then afterwards make 2 buttons that will + or - the integers so you can "scroll" though the items.
So to realize this i decided to make dummy code, to see how i could work it out.
And for most part its working, however i have the problem now, that it seems that my draw function is refreshing the screen constantly (Even though I've put in a bool to make sure it woulden), and by doing that it keeps erasing the numbers I'm listing on the screen.
Heres the code:
List<int> test = new List<int>() {1,2,3,4,5,6,7 };
int low = 0;
int high = 3;
int count;
bool isDone = false;
public override void Draw(GameTime gameTime)
{
spriteBatch.Begin(SpriteSortMode.Deferred, BlendState.AlphaBlend, SamplerState.PointClamp, null, null, null);
if (!isDone)
{
int posX = 20;
foreach (int nr in test)
{
if (count == high)
{
isDone = true;
break;
}
else
{
count++;
}
if (count >= low && count <= high)
{
posX += 20;
spriteBatch.DrawString(gameFont, nr.ToString(), new Vector2(posX, 20), Color.White);
}
}
}
spriteBatch.End();
}
Hopefully some of you clever folks can eye the mistake I've been missing.
Thanks in advance
~Etarnalazure.
You never reset your counter. Therefore, the numbers will be only visible in the first frame. Add
count = 0;
before the for-loop.
Furthermore, you might want to revise your structure. If you use a List<>, then every item already has its index. And you don't have to iterate over each and every item, if you use a for loop:
for(int i = low; i <= high; ++i)
{
var currentItem = list[i];
}
Hoping someone can help me with this... I'm following examples seen here for CCMenuAdvanced but am ending up with a weird result, I see my menu and it scrolls but using the boundaryRect property I can't seem to get it to hide part of the menu and show what I want.
Here's my code:
// Setup Menu Alignment
[menuA alignItemsVerticallyWithPadding:0 bottomToTop:NO]; //< also sets contentSize and keyBindings on Mac
menuA.isRelativeAnchorPoint = YES;
menuA.boundaryRect = CGRectMake(0, 100, 230, 200);
[menuA fixPosition];
[self addChild:menuA];
I'm able to scroll and view my entire list which is good, but I can't set up an area to view only part of the menu at a time, which is what boundaryRect should do. Has anyone used this before and can give me some advice?!?
Thanks!
Well, not from the same class, but a home grown scrolling menu. I use the visibility and transparencies of the menuItems themselves. When scrolling up, if a menu label approaches the rectangle's edge, i start fading it out to 0. When the anchor point of the menuItem is outside the rectangle, i set its visibility to NO (thus cant be clicked). Same going down. Clamping is tricky. You have to set these properties when the list of menuItems changes, in case it grows shorter than the height of the boundary rectangle, or grows again greater than the rectangle. Something like this (edited, not actual code ... dont know if it compiles :) ):
-(void) fixMenuItemOpacity:(CCMenuItemLabel*) mi{
float theY = mi.position.y ;
if (fadeOutZoneHeight_<4.0f) {
if (theY> self.boundaryRect.origin.y+self.boundaryRect.size.height/2 - fadeOutZoneHeight_) {
mi.visible=NO;
} else if( theY < self.boundaryRect.origin.y-self.boundaryRect.size.height/2 + fadeOutZoneHeight_) {
mi.visible=NO;
} else {
mi.visible=YES;
}
return;
}
float delta;
float percentOpacity;
float topWindow;
float bottomWindow;
float top;
float bottom;
/*
not visible
--------------------------- top
visible, variable opacity
--------------------------- top window
opacity 100%
-------------------------- bottomWindow
visible, variable opacity
------------------------- bottom
*/
top = self.boundaryRect.origin.y + self.boundaryRect.size.height/2;
topWindow = top - fadeOutZoneHeight_;
bottom = self.boundaryRect.origin.y - self.boundaryRect.size.height/2;
bottomWindow=bottom+ fadeOutZoneHeight_;
if (theY> top ) {
mi.visible=NO;
} else if ( (theY > topWindow) && (theY < top)) {
mi.visible=YES;
delta = abs((int)top - (int)theY);
percentOpacity=delta/fadeOutZoneHeight_;
mi.opacity=(GLubyte )(255.0f*percentOpacity);
} else if( (theY <= topWindow ) && (theY >= bottomWindow ) ){
mi.opacity=255;
mi.visible=YES;
} else if ( (theY < bottomWindow) && (theY >= bottom) ){
mi.visible=YES;
delta= abs((int)bottom - (int)theY);
percentOpacity = delta/fadeOutZoneHeight_;
mi.opacity=(GLubyte ) (255.0*percentOpacity);
} else {
mi.visible=NO;
}
}
I am using TabStrip on a project of mine. The tabstrip has TTTabItems that are the alphabet A-Z. When I click to each alphabet letter the delegate navigates to another page.
In the other page there is a TTTabstrip also (same construction, frame etc). How can I mark the alphabet also on the second tabstrip without triggering the event?
I tried to get the integer value of the letter mod the integer value of "a" (so that it will bring me an index) and assign it to selectedIndex:
unichar letter = [[NSString stringWithString:#"e"] characterAtIndex:0];
/*(k is #"a" unichar)*/
tabBar.selectedTabIndex = letter % kEnglishAlpha;
But it gives me deallocation error.
** UPDATE **
on the drill down detail view (where I have the problem) I mentioned in the comments I have the following coming from a tt navigation:
tt://listWords/Cat
on the view did load event, and after the initialization of the TTTabStrip (that contains only TTTabItem with letters A-Z) and the tabBar.delegate = self declaration, I use the upper code to "select" the chosen letter. The rest of the view shows the definition and everything related. Normally that would be the case, but when I use the back button to return to the view that has the tttableItems (cat, catsup, catnip etc) it says deallocated controller.
My guess is that using the tabselected delegation code and setting a tabindex, it triggers the tab selected code immediate and that's where the problem is. If I don't use the selectedTabIndex code, I can navigate back and through the letters without problem.
There's no function to auto selected a TTTabItem in TTStripTab.
You will have to extend TTTabStrip and add this function:
///////////////////////////////////////////////////////////////////////////////////////////////////
- (void)setSelectedTabIndexToCenter:(NSInteger)selectedTabIndex {
if (selectedTabIndex>_tabItems.count-1) {
selectedTabIndex = _tabViews.count-1;
}
[self layoutSubviews];
float horizontalOffset = 0.0f - _scrollView.size.width/2;
for (int i = 0; i < selectedTabIndex; ++i) {
TTTab* tab = [_tabViews objectAtIndex:i];
if (selectedTabIndex-1==i) {
horizontalOffset += tab.size.width*1.5;
} else {
horizontalOffset += tab.size.width;
}
}
if (horizontalOffset<0) {
horizontalOffset = 0;
}
_scrollView.contentOffset = CGPointMake(horizontalOffset, 0);
[super setSelectedTabIndex:selectedTabIndex];
}
This function will select a specific tab item and center on it by changing the offset of the strip tab.