Stop animation symbol on polyline - googlemaps - javascript

I used the animation for symbols on polylines according to this answer that was very useful:
Animate symbol on multiple geodesic polylines
What i would like is to have several polylines and generate animation when one is selected and stop animation for the others.
That is, i want to remove symbol and stop animation once it has started with the method mentioned above:
function animateCircle(id) {
var count = 0;
offsetId = window.setInterval(function () {
count = (count+1) % 200;
id.setOptions({
icons: [{
offset: (count/2)+'%'
}]
});
}, 20);
};
I tried another function like this but it didn't work at all:
function stopCircle(id) {
id.setOptions({
icons: [{
offset: '0%'
}]
};
Neither:
function stopCircle(id) {
id.setOptions({
icons: null
};
Thanks.

id is an index into your array of polylines. To access the polyline you need to use polylines[id] (i.e polylines[id].setOptions.
You probably also want to stop the timer, for that you need to keep a reference to the value returned by setInterval.
working example
function stopCircle(id) {
clearInterval(polylines[id].handle);
polylines[id].polyline.setOptions({
icons: null});
};
Where the polylines array now contains:
polylines[i] = new Object();
polylines[i].polyline = polyline;
polylines[i].handle = animateCircle(i);

For me "id" is a polyline itself.
All I need is to keep the output from "setInterval", that should be the input for "clearInterval".
These are the two functions:
function animateCircle(id) {
var count = 0;
window.clearInterval(id.offsetId);
id.offsetId = window.setInterval(function () {
count = (count+1) % 200;
id.setOptions({
icons: [{
offset: (count/2)+'%'
}]
});
}, 20);
};
function stopCircle(id) {
window.clearInterval(id.offsetId);
id.setOptions({
icons: null
});
};

Related

why is my variable in a nested function with array.forEach use undefined in Javascript

I am sorry if the answer here is obvious, I am mostly a c/c++ guy and javascript is relatively new to me.
I am using THREE, bundling with browserify. In one module, I am creating an array of mesh objects that I need to access in a nested function using forEach(...), but I keep getting an error, that the corresponding object is not defined. I am suspecting that the problem is related to me actually defining the array in a separate callback function that is defined in parallel with the nested function using the forEach(). I have been trying to "declare" the variable globally, before I assign it to the array in the callback function, but that doesn't work. In c++ I would define an uninstantiated object globally (or in a class header) and then instantiate it in some function later, while accessing it in yet another function after that. Below is the relevant code and the variable that keeps coming back undefined is called "mesh". Note that I am not even sure why setPallete(...) and update(...) are implemented as nested function (a strange concept to me)? In another incarnation of this code, I implement them as "standalone" (e.g. not nested) functions and things are working, but in that code I am not using browserify to bundle, because I have just one, monolythic script. So maybe this has soemthing to do with that.
Thank you for your help.
let mesh; //try global definition -- no dice
module.exports = function (app) {
const totalMeshes = 40;
const subdivisions = 300;
const numSides = 8;
const openEnded = false;
const geometry = createGeometry(numSides, subdivisions, openEnded);
const container = new THREE.Object3D();
const lines = newArray(totalMeshes);
ShaderLoader("scripts/Grp3D/lib/shaders/tube.vert", "scripts/Grp3D/lib/shaders/tube.frag", function (vertex, fragment) {
const baseMaterial = new THREE.RawShaderMaterial({
vertexShader: vertex,
fragmentShader: fragment,
side: THREE.FrontSide,
extensions: {
deriviatives: true
},
defines: {
lengthSegments: subdivisions.toFixed(1),
ROBUST: false,
ROBUST_NORMALS: false,
FLAT_SHADED: true
},
uniforms: {
thickness: { type: 'f', value: 1 },
time: { type: 'f', value: 0 },
color: { type: 'c', value: new THREE.Color('#303030') },
animateRadius: { type: 'f', value: 0 },
animateStrength: { type: 'f', value: 0 },
index: { type: 'f', value: 0 },
totalMeshes: { type: 'f', value: totalMeshes },
radialSegments: { type: 'f', value: numSides }
}
});
lines.map((_, i) => {
const t = totalMeshes <= 1 ? 0 : i / (totalMeshes - 1);
const material = baseMaterial.clone();
material.uniforms = THREE.UniformsUtils.clone(material.uniforms);
material.uniforms.index.value = t;
material.uniforms.thickness.value = randomFloat(0.005, 0.0075);
mesh = new THREE.Mesh(geometry, material);
mesh.frustumCulled = false; // to avoid ThreeJS errors
return mesh;
});
lines.forEach(tmesh => container.add(tmesh));
});
return {
object3d: container,
update,
setPalette
};
// animate in a new color palette
function setPalette (palette) {
tweenr.cancel();
lines.forEach((mesh, i) => {
const uniforms = mesh.material.uniforms;
uniforms.color.value.set(palette);
const delay = i * 0.004;
uniforms.animateRadius.value = 0;
uniforms.animateStrength.value = 1;
tweenr.to(uniforms.animateRadius, { value: 1, duration: 0.5, delay, ease: 'epxoOut' });
tweenr.to(uniforms.animateStrength, { value: 0, duration: 1, delay, ease: 'expoInOut' });
});
}
function update (dt) {
dt = dt / 1000;
lines.forEach(mesh => { //undefined when the code runs
mesh.material.uniforms.time.value += dt;
});
}
};
Few problems here:
wrong const lines = newArray(totalMeshes);
correct const lines= []; //In Js its not necessary to have a predefined length.
You need to put data in above lines array as well.
I hope I get this right. You probably mean the container variable etc., right?
The problem I see is that you are adding a anonymous callback function to ShaderLoader which takes two parameters. This function is called within ShaderLoader somewhere. Within the scope of ShaderLoader your variable container etc. is not available anymore.
You are using const here, which is block scoped. I found an article which explains it in a very good way.

Getting callback is not a function in JS with Highcharts

I am not being able to update min/max/avg values in Highcharts when doing zoom.
I am trying to combine these two pieces of code:
1.Update min/max/avg---->http://jsfiddle.net/d_paul/supgh9c1/4/
2.load DB tables based on zoom ---> https://jsfiddle.net/gh/get/library/pure/highcharts/highcharts/tree/master/samples/stock/demo/lazy-loading/
So the code shown here produce a "callback is not a function".
But if i remove the "e"(that is the event that highcharts pass when the user select a zoom) in the function after_Set_Extreme , I get "e" is not defined in that function. And if I add "e" as passing parameter (e,updateLegendLabel) I get same error as before, but now in the afterSetExtremes line. So it seems e(event) is not being recognized.
But if you see the link # 2 above, afterSetExtremes is called without passing "e", but is expected in the function . See function definition..
Can anyone help me to understand what is wrong here?
This is highcharts when doing the actual chart
$('#container2').highcharts('StockChart', {
chart: {
zoomType: 'x',
events: {
load: updateLegendLabel
}
},
......
xAxis: {
events: {
afterSetExtremes: after_Set_Extremes(updateLegendLabel),
},
.....
function after_Set_Extremes(e, callback) {
processed_json_temperatura.length = 0;
processed_json_presion.length = 0;
processed_json_humedad.length = 0;
processed_json_lluvia.length = 0;
processed_json_horas_frio.length = 0;
if (typeof(e.rangeSelectorButton) !== 'undefined') {
........
callback();
}
function updateLegendLabel() {
var chrt = !this.chart ? this : this.chart;
// alert('entre updatelegend')
console.log(this);
chrt.update({
....
}
Combining these two functionalities seems to be very simple, please check this example: https://jsfiddle.net/BlackLabel/oh3ubdLv/
However, in your case after_Set_Extremes function is called only once, when the chart is initialized. You need to create an additional function to pass arguments:
Highcharts.stockChart('container', {
...,
xAxis: {
events: {
afterSetExtremes: function(e) {
after_Set_Extremes(e, updateLegendLabel)
}
}
}
});
function after_Set_Extremes(e, callback) {
callback();
}
function updateLegendLabel() {
console.log('callback');
}
Live demo: http://jsfiddle.net/BlackLabel/ebdtry20/

Unable to get pixi js elements after init

I need help form this bit of code, been stuck for hours, cant seems to figure out. Any help will be much appreciated.
I have multiple sections that has pixi.js app. Initiated the functions as below.
var pixiFunctions = [
function(type) {
var pixi, sectionContainer, stage, texture, sprite, bars;
sectionContainer = $('section[data-media="established"]');
var established = {
init: function() {
pixi = new PIXI.Application({
width: getViewport().width,
height: getViewport().height,
transparent: true,
resolution: window.devicePixelRatio || 1,
antialias: true
});
sectionContainer.append(pixi.view);
stage = new PIXI.Container();
texture = new PIXI.Texture.from(loadedMedia[1].src);
texture.baseTexture.resource.autoplay = false;
texture.baseTexture.resource.source.loop = 'loop';
sprite = new PIXI.Sprite(texture);
texture.baseTexture.on('loaded', function() {
sprite.height = pixi.renderer.screen.height;
sprite.width = pixi.renderer.screen.width;
pixi.stage.addChild(sprite);
established.start();
});
},
start: function() {
pixi.render(stage);
requestAnimationFrame(established.start);
},
animateIn: function() {
console.log('animateIN');
**console.log(pixi)**
sectionContainer.addClass('active');
},
animateOut: function() {
console.log('animateOut');
sectionContainer.removeClass('active');
}
}
if (type === 'animateIn') established.animateIn();
if (type === 'animateOut') established.animateOut();
if (type === 'init') established.init();
}
]
I have a sets of functions like this for each ,
On DOM load, I am calling these functions in this manner,
for (var i = 0; i < pixiFunctions.length; i++) {
pixiFunctions[i]('init');
}
And here comes the issue, when I am scrolling, I have set up functions to fire up in this manner;
pixiFunctions[currentPosition]('animateIn');
[currentPosition] - refers to the count that increment as you scroll so that I can animate in sections.
Issue is whenever i call this function with a , the console logs as PIXI undefined. I have no clue how to sort it out. I needed this because I need to get a hold of pixi in order to animate the mask.
** pixiFunctionscurrentPosition;**
Thank you all.

Highmaps: Need to get unplotted data

I want to get the data points which cannot be plotted on the underlying map (i.e. joinBy fails to map the data to the geojson). Is there any way to get the unplotted data?
You can check all points and find which are not plotted, the condition is that point has a value but doesn't have graphic:
chart: {
events: {
load: function () {
var chart = this,
unplottedPoints = [];
$.each(chart.series[0].data, function (i, point) {
if (point.value && !point.graphic) {
unplottedPoints.push(point);
}
});
console.log(unplottedPoints);
}
}
},
In array unplottedPoints you have list of all not rendered points.
Demo: http://jsfiddle.net/spmx9xu3/1/

jQuery break out of $.on that is within $.each

I need to iterate over an AJAX response and break out of an event handler when a condition is met. I'm having trouble with this code:
$.each(response, function(i, v) {
// create mapbox object
var map = L.mapbox.map('map', v.map_embed_id, {
zoomAnimation: false
});
var polygonLayer = L.mapbox.featureLayer().loadURL('https://a.tiles.mapbox.com/v4/' + v.map_embed_id + '/features.json?access_token=abcde').addTo(map);
polygonLayer.on('ready', function() {
var layer = leafletPip.pointInLayer(latlng, polygonLayer, true);
if (layer.length) {
// this is where I need to break out of $.on
// and the current $.each iteration
}
});
});
I know return false would break out of the $.each iteration but this is more difficult since I need to break out of the $.on event handler. What can I do? Could I use a trigger maybe?
Thanks to #Kevin B's advice to use recursion, this is how I fixed my code to make it work.
getMapsList().done(function(maps) {
getMapboxMap(maps, geocode);
});
function getMapboxMap(maps, geocode) {
var map_params = maps[0];
var map_embed_id = map_params.map_embed_id;
if (maps.length > 0)
maps.shift();
// create mapbox object
var map = L.mapbox.map('map', map_embed_id, {
zoomAnimation: false
});
// create marker of address entered
L.mapbox.featureLayer({
type: 'Feature',
geometry: {
type: 'Point',
coordinates: [
geocode.location.lng,
geocode.location.lat
]
},
properties: {
title: address,
'marker-size': 'medium',
'marker-color': '#f44',
'marker-symbol': 'star'
}
}).addTo(map);
// create polygon layer and add to map from map's geojson
var polygonLayer = L.mapbox.featureLayer().loadURL('https://a.tiles.mapbox.com/v4/' + map_embed_id + '/features.json?access_token=pk.eyJ1IjoiZW5nbGVzaWRldGVycml0b3JpZXMiLCJhIjoiekFIU0NlayJ9.rE9XdicgXc9aIiXJ9yn68w').addTo(map);
// after polygon layer has been added to map
polygonLayer.on('ready', function() {
// featureLayer.getBounds() returns the corners of the furthest-out markers,
// and map.fitBounds() makes sure that the map contains these.
map.fitBounds(polygonLayer.getBounds());
// create a latLng object based on lat/lng of address entered
var latlng = L.latLng(geocode.location.lat, geocode.location.lng);
// create point in layer object
var layer = leafletPip.pointInLayer(latlng, polygonLayer, true);
if (layer.length) {
// found it
return false;
} else {
if (maps.length > 0) {
getMapboxMap(maps, geocode);
}
}
});
}
function getMapsList() {
return $.get('/utility/territories/maps-list');
}

Categories