I have a path which I want to animate every 5 seconds. I tried the using setInterval in the following code but it keeps duplicating the canvas. Is there an easier solution?
JS Fiddle Link
window.onload= function aa () {
paper = Raphael(0,0,900,900);
var p=paper.path("M10,10 h20 v10 h-20z");
p.animate({path:"M10,10 h300 v10 h-300z"},5000);
//window.setInterval(aa(), 5000);
}
You are repeating the whole aa function that initializes the raphael paper (paper = Raphael(0,0,900,900);). That's why your canvas gets duplicated.
Moreover, it would be better to use callbacks (you can see the the docs on animate) rather than setInterval to trigger your animations.
This is how I would code it :
function init(){
var paper = Raphael(0, 0, 900, 900),
pathsString = ["M10,10 h20 v10 h-20z","M10,10 h300 v10 h-300z"],
p = paper.path(pathsString[0]),
animationCounter = 0,
animationDuration = 5000,
animate = function(){
animationCounter++;
p.animate({path : pathsString[animationCounter %2]}, animationDuration, animate);
};
animate();
};
window.onload = init;
Here's a working example of the above code.
Related
I want to create a text typing effect in simple web application. It's my first time using dart for web application. I did something like this.
var chars = "Hello World".split('');
var textstream = Stream<String>.fromIterable(chars);
var idx = 0;
textstream.listen((data) {
Future.delayed(Duration(milliseconds: idx * 200), () {
var element = querySelector('#hero-keyword');
element.appendText(data);
idx++;
});
});
And my html has this
<p id="hero-keyword"></p>
But, I want each letter printed in the interval of 200ms. But what I got is, all letters show up at the same time.
Your idx variable is only being updated when the delayed future completes, which will happen on the first pass of the event loop after the specified delay.
fromIterable, however, will process its values all at once, in sequence. Taken together, the net effect is that all of your delays are being set to 0, and then, after a slight delay, all of your characters will be emitted, and idx will be incremented.
You can try the following pattern, instead, adjusted to your use case:
void main() {
var text = "Hello world";
Stream
.periodic(Duration(milliseconds: 200), (count) {
print(text[count]);
})
.take(text.length)
.drain();
}
I have created a map with ol3 and added ol.animation to "fly" from one city to another. The Animation should start some seconds after clicking the start button. So, it should work like this:
The map is centered on a point called "Eifel"
Click start-button
After three seconds the flight to "Berlin" starts (it will take 2 seconds)
Stay in Berlin for 1 second and then fly to "Stuttgart"
The following code nearly works, but it switches to "Stuttgart" directly. I think the problem ist the "map.getView().setCenter(Stuttgart);" at the End. How can I make it work as expected?
// Klick auf Button -> Start
var startflight = document.getElementById('start-flight');
// Flug 1: Eifel > Berlin
startflight.addEventListener('click', function() {
var duration = 2000;
var start = (new Date()).getTime()+3000;
var pan = ol.animation.pan({
source: (view.getCenter(Eifel)),
start: start
});
map.beforeRender(pan);
map.getView().setCenter(Berlin);
},
true);
// Flug 2: Berlin > Stuttgart
startflight.addEventListener('click', function() {
var duration = 2000;
var start = (new Date()).getTime()+6000;
var pan = ol.animation.pan({
source: (view.getCenter(Berlin)),
start: start
});
map.beforeRender(pan);
map.getView().setCenter(Stuttgart);
},
true);
Looking forward to your answers,
jsc
You could do something like this:
startflight.addEventListener('click', function() {
var duration = 2000;
var start = Date.now() + 3000; // use Date.now()
var pan = ol.animation.pan({
duration: duration,
source: (view.getCenter(Eifel)),
start: start
});
map.beforeRender(pan);
map.getView().setCenter(Berlin);
}, true);
But this will fire immediately when you render, after that setCenter() call is made. So the map will just go blank and then render. Probably a better approach would be to wrap the whole thing in a setTimeout.
startflight.addEventListener('click', function() {
var duration = 2000;
setTimeout(function () {
var pan = ol.animation.pan({
duration: duration,
source: view.getCenter()
});
map.beforeRender(pan);
map.getView().setCenter(Berlin);
}, 3000);
}, true);
If you want to then fly to another city, you can just add another panning function. I would say that if you have a lot of these multi-city pans you'll want to abstract this some more though.
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.
I'm newbie in cocos-js.
I want to make a health bar in cocos JS and try this code. And i choose to use Progress Timer. But when i use this code, it just show the bar, no running action. What's wrong ?
var healthBar = cc.ProgressTimer.create(cc.Sprite.create("health_bar1.png"));
healthBar.setType(cc.PROGRESS_TIMER_TYPE_BAR);
healthBar.setBarChangeRate(cc.p(1,0));
healthBar.setMidpoint(cc.p(0,0));
this.addChild(healthBar, 1);
healthBar.setPosition(cc.winSize.width/2, cc.winSize.height/2);
var to1 = cc.progressTo(5, 100);
healthBar.runAction(to1);
This code is working for me very well:
var healthBar = cc.ProgressTimer.create(cc.Sprite.create("health_bar1.png"));
healthBar.setType(cc.ProgressTimer.TYPE_BAR);
healthBar.setBarChangeRate(cc.p(1,0));
healthBar.setMidpoint(cc.p(0,0));
healthBar.setPosition(cc.winSize.width/2, cc.winSize.height/2);
this.getParent().addChild(healthBar, 1);
var to1 = cc.progressTo(5, 100);
healthBar.runAction(to1);
I am a newbie in game developing, now i am working with a shooter game for learning purpose.
I have a question,
in my game I created three tween animation :
var myTween:Tween = new Tween(this, "scaleX", Back.easeIn, 1.2, 0, 10);
var myTween2:Tween = new Tween(this, "scaleY", Back.easeIn, 1.2, 0, 10);
var myTween3:Tween = new Tween(this, "alpha", None.easeIn, 1, 0, 10);
This tweens will occur after enemy's health become zero,
What I intended is after the animation, the clip will be removed from stage.
my question is, is there a way to know that all these tweens has finished? I tried to apply TweenEvent.MOTION_FINISH event for each tween , but If i do that i have to create three listenesr ( which will be problematic if I want to create ten tweens).
Thank you
Since all the tweens run for the same duration could you not just add your listener to the last tween and when the handler executes you will know that they have all completed?
Alternatively you could do something like this:
import fl.transitions.Tween;
import fl.transitions.TweenEvent;
import fl.motion.easing.Back;
import fl.transitions.easing.None;
// Populate an array with the tweens
var tweens:Array = [];
tweens.push(new Tween(this, "scaleX", Back.easeIn, 1.2, 0, 10));
tweens.push(new Tween(this, "scaleY", Back.easeIn, 1.2, 0, 10));
tweens.push(new Tween(this, "alpha", None.easeIn, 1, 0, 10));
// Finished tweens count
var finishedCount:int = 0;
// Loop through all the tweens and add a handler for the motion finished event
for (var i:int = 0; i < tweens.length; i ++)
{
// Each of the tweens motion finished event can be assigned to the same handler
Tween(tweens[i]).addEventListener(TweenEvent.MOTION_FINISH, motionFinishedHandler);
}
function motionFinishedHandler(e:TweenEvent):void
{
// Good practice to remove the event listener when it is no longer needed
e.target.removeEventListener(TweenEvent.MOTION_FINISH, motionFinishedHandler);
// Increment the count and test whether it equals the number of tweens
if (++ finishedCount == tweens.length)
trace("Finished");
}
You might also want to consider Greensock's TweenLite which is pretty much the standard for animating objects in Flash and which will allow you to tween multiple properties of the same object in a single call.
+1 for Greensock's TweenLite & TimelineLite.
Makes tweening everything cleaner and easier.