can openlayers 3 render the animated marker using gif - openlayers-3

I wanna ask how to make the marker show animated gif picture like openlayers 2 do...it can show the animated marker..what I want is show animated gif marker not make a marker move..it is possible or not?
style = {
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
anchor: anchor,
opacity: 1,
src: 'https://articulate-heroes.s3.amazonaws.com/uploads/rte/kgrtehja_DancingBannana.gif',
scale: 1,
};
var iconStyle = new ol.style.Style({
image: new ol.style.Icon(/** #type {olx.style.IconOptions} */ (style))
});
var iconFeature = new ol.Feature({
position: data.coordinate,
geometry: new ol.geom.Point([0,0]),
});
iconFeature.setStyle(iconStyle);
How to make https://articulate-heroes.s3.amazonaws.com/uploads/rte/kgrtehja_DancingBannana.gif displayed animated as a gif in a map? is it possible or not create animated features in openlayers 3..I don't find any article with contain this solving...thanks

Yes there is a way do it but is a bit tricky so I am not sure whether it fit to your needs.
You need to add a marker instead and use css to style the marker.
check this
your html with the dom element
<div id="map" class="map"></div>
<div id="marker" title="Marker"></div>
your js here
var layer = new ol.layer.Tile({
source: new ol.source.OSM()
});
var map = new ol.Map({
layers: [layer],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
// the position of your marker
var pos = ol.proj.fromLonLat([23.3725, 35.208889]);
var marker = new ol.Overlay({
position: pos,
positioning: 'center-center',
element: document.getElementById('marker'),
stopEvent: false
});
map.addOverlay(marker);
and your css here
#marker {
width: 365px;
height: 360px;
background: url("https://articulate-heroes.s3.amazonaws.com/uploads/rte/kgrtehja_DancingBannana.gif") no-repeat scroll 0% 0% transparent;
}
and a fiddle here with the dancing banana (nice gif though :)))) )

This can definitely be done with a feature or layer style, with the help of a gif decoder that extracts the frames from the gif and controls an animation. Using gifler, the relevant code could look something like this:
const gifUrl = "./data/kgrtehja_DancingBannana.gif";
const gif = gifler(gifUrl);
gif.frames(
document.createElement("canvas"),
(ctx, frame) => {
if (!iconFeature.getStyle()) {
iconFeature.setStyle(
new Style({
image: new Icon({
img: ctx.canvas,
imgSize: [frame.width, frame.height]
})
})
);
}
ctx.clearRect(0, 0, frame.width, frame.height);
ctx.drawImage(frame.buffer, frame.x, frame.y);
map.render();
},
true
);
The above code sets an icon style with the animated gif on an existing feature. The feature is stored in a variable iconFeature.
See https://codesandbox.io/s/beautiful-fire-cdrou?file=/main.js for a working example.

An alternative is to use two png images. An effect similar to a gif image can be obtained if you apply two different styles to the same layer using the setStyle () method with a setInterval () function. Ej:
Style1 = {
...
src: '../image1.png',
...
};
Style2 = {
...
src: '../image2.png',
...
};
iconFeature.setStyle(Style1);
then
var n = 0; // global
function changeStyleEvery (){
if (n == 0){
n = 1;
iconFeature.setStyle(Style1);
}else{
n = 0;
iconFeature.setStyle(Style2);
};
};
function applyInterval (){
setInterval(function(){changeStyleEvery(); }, 500);
};

Related

openlayers3 : ol.style.Icon in vectorContext.setStyle can not work?

This example shows how to use postcompose and vectorContext to animate features:
http://openlayers.org/en/latest/examples/feature-animation.html
I try to replace the style in these lines:
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: radius,
snapToPixel: false,
stroke: new ol.style.Stroke({
color: 'rgba(255, 0, 0, ' + opacity + ')',
width: 0.25 + opacity
})
})
});
vectorContext.setStyle(style);
when I replace the style to an img style, like this:
var style = new ol.style.Style({
image: new ol.style.Icon(({
src: 'https://openlayers.org/en/v3.20.1/examples/data/icon.png'
}))
});
it's not working and throws an error: Cannot read property '0' of null
Is it a bug? Or how can I use img style about it?
If you want to add an image instead of a normal Point, you don't need to change the style into the animate function.
You can add the desired style into the vector layer this way:
var vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
image: new ol.style.Icon(({
src: 'https://openlayers.org/en/v3.20.1/examples/data/icon.png'
}))
})
});
I edited your jsfiddle without any style for the vectorContext. If you want to get some animation, like in the Openlayers Site example, you only have to add the old styling by uncommenting it in the jsfiddle code.

OpenLayers: get pixel color from image layer

I have a simple map with a static pixel image layer:
<!DOCTYPE html>
<html>
<head>
<title>Simple Map</title>
<link rel="stylesheet" href="http://openlayers.org/en/v3.13.0/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.13.0/build/ol.js"></script>
// reference to jquery here
</head>
<body>
<div id="map" class="map"></div>
<script>
var extent = [0, 0, 2000000, 2000000];
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: extent
});
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
image = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: 'http://imgs.xkcd.com/comics/online_communities.png',
projection: projection,
imageExtent: extent
})
});
map.addLayer(image);
image.on('singleclick', function(evt) {
var xy = evt.pixel;
console.log(xy);
var canvasContext = $('.ol-unselectable')[0].getContext('2d');
var pixelAtClick = canvasContext.getImageData(xy[0], xy[1], 1, 1).data;
var red = pixelAtClick[0]; // green is [1] , blue is [2] , alpha is [4]
});
</script>
</body>
</html>
When clicking on the image I want to get the color of the pixel that I clicked on. As far as I understand the raster source example (http://openlayers.org/en/v3.13.0/examples/raster.html), this is only possible with raster sources so I converted the image into a raster source. (When I add that raster source to the layer, I get the message that this operation is insecure, so I still use the image to show on the map.)
Here (How to get a pixel's color value from an Openlayers 3 layer?) the color is read from evt.context. However, with me evt.context is undefined.
Addendum: There might be several image layers overlaying each other. I need to get the color from a single specific image layer.
So this isn't ideal but might send you along the right lines:
You can use the pixel xy of the click event to query the canvas object that openlayers creates and puts your map data onto.
map.on('singleclick', function(evt) {
var xy = evt.pixel;
var canvasContext = $('.ol-unselectable')[0].getContext('2d');
var pixelAtClick = canvasContext.getImageData(xy[0], xy[1], 1, 1).data;
var red = pixeAtClick[0]; // green is [1] , blue is [2] , alpha is [4]
});
This assumes that you are using jQuery and that the canvas is the first DOM element using the class '.ol-unselectable'.
Hope it helps.

Is it possible to set different colors to each segment of a LineString without meeting a huge performance hit?

My openlayers 3 application draws several LineString features on the map (from a few dozen up to 2000-3000).
When setting different colors for each segment of the LineStrings, I meet a huge performance hit (starting from just a few LineStrings on the map). The zoom and pan become completely unresponsive making my aplication not usable in this form.
Since I don't want to set a new geometry for each segment (but only change its color), I imagine there must be a more performance effective way of achieving this ?
Here's my code :
var styleFunction = function(feature, resolution) {
var i = 0, geometry = feature.getGeometry();
geometry.forEachSegment(function (start, end) {
color = colors[i];
styles.push(new ol.style.Style({
geometry: new ol.geom.LineString([start, end]),
fill: new ol.style.Fill({
color: color
}),
stroke: new ol.style.Stroke({
color: color,
width: 2
})
}));
i++;
});
return styles;
}
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: styleFunction
});
There are a few things that you can try to optimize:
Cache fill and stroke style
var fillStyles = colors.map(function(color, i) {
return new ol.style.Fill({
color: color
})
});
var strokeStyles = colors.map(function(color, i) {
return new ol.style.Stroke({
color: color,
width: 2
})
});
Cache the style for each feature
vectorSource.forEach(function(feature, i) {
var geometry = feature.getGeometry();
var styles = [];
var i = 0;
geometry.forEachSegment(function (start, end) {
styles.push(new ol.style.Style({
geometry: new ol.geom.LineString([start, end]),
fill: fillStyles[i],
stroke: strokeStyles[i]
}));
i++;
});
feature.setStyle(styles);
});
Disable that the rendering is updated during animations and interactions
var vectorLayer = new ol.layer.Vector({
source: vectorSource,
updateWhileAnimating: false,
updateWhileInteracting: false
});
See ol.layer.Vector.
If all this doesn't help, you might also want to take a look at ol.source.ImageVector(example).
Since we could not solve the problem, even with tsauerwein's recommendations, this feature was put to the fridge for a while. Now we got back to it with fresh ideas and actually found a "solution".
Something that I made not clear in the question is that segments of a LineString are colored according to a property of their starting point. Several consecutive segments may thus share the same color if the value of this property doesn't change between them.
The idea is to avoid creating a new style for each and every segment but rather to create a new style only when necessary (when the color changes) :
let i = 0,
color = '#FE2EF7', //pink. should not be displayed
previousColor = '#FE2EF7',
lineString,
lastCoordinate = geometry.getLastCoordinate();
geometry.forEachSegment(((start, end) => {
color = this.getColorFromProperty(LinePoints[i].myProperty);
//First segment
if (lineString == null) {
lineString = new ol.geom.LineString([start, end]);
} else {
//Color changes: push the current segment and start a new one
if (color !== previousColor) {
styles.push(new ol.style.Style({
geometry: lineString,
fill: new ol.style.Fill({
color: previousColor
}),
stroke: new ol.style.Stroke({
color: previousColor,
width: 2
})
}));
lineString = new ol.geom.LineString([start, end]);
} else {
//Color is same: continue the current segment
lineString.appendCoordinate(end);
}
//Last segment
if (end[0] === lastCoordinate[0] && end[1] === lastCoordinate[1]) {
styles.push(new ol.style.Style({
geometry: lineString,
fill: new ol.style.Fill({
color: color
}),
stroke: new ol.style.Stroke({
color: color,
width: 2
})
}));
}
}
previousColor = color;
i++;
}

Selectable Points of vector layer have an offset

I've got a vector layer with a GeoJSON source, consisting of Points and a LineString. When I click on a point I want to open a popup with additional information.
Here's some code:
var style = {
'Point': [new ol.style.Style({
image: new ol.style.Circle({
fill: new ol.style.Fill({
color: 'rgb(255,0,0)'
}),
radius: 5,
stroke: new ol.style.Stroke({
color: '#000000',
width: 1
}),
})
})],
'LineString': [new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#ff0000',
width: 3
})
})],
'MultiLineString': [new ol.style.Style({
stroke: new ol.style.Stroke({
color: '#0000ff',
width: 3
})
})]
};
var map = new ol.Map({
target: 'map-ol-canvas',
interactions: ol.interaction.defaults({mouseWheelZoom: false}),
layers: [new ol.layer.Tile({ source: new ol.source.OSM() })],
view: new ol.View({
zoom: 8,
maxZoom: 16
})
});
map.getView().fit(extent, map.getSize());
var trackSource = new ol.source.Vector({
url: '/test.geojson',
format: new ol.format.GeoJSON()
});
var track = new ol.layer.Vector({
source: trackSource,
style: function(feature, resolution) {
return style[feature.getGeometry().getType()];
}
});
map.addLayer(track);
var select = new ol.interaction.Select({
filter: function (feature, layer) {
return feature.getGeometry().getType() === 'Point';
}
});
map.addInteraction(select);
// When user clicks on a waypoint, show a tooltip.
function onMouseClick(browserEvent) {
var coordinate = browserEvent.coordinate;
var pixel = map.getPixelFromCoordinate(coordinate);
map.forEachFeatureAtPixel(pixel, function(feature) {
if (feature.getGeometry().getType() === 'Point') {
console.log(feature.get('date'));
}
});
}
map.on('click', onMouseClick);
The problem:
When I click directly on a point nothing happens. When I click a couple of pixels below and a bit right or left (depends on zoom level!), the point gets selected and the console.log is triggered.
I can fix this by using Firebox WebDeveloper Addon and activating "Disable all styles".
However, when I manually remove all CSS one by one that behavior never goes away.
In the first place I thought this might be some inherited padding or margin, but currently I think the canvas shouldn't be affected by any CSS at all.
Any ideas about what could be wrong?
I'm experiencing the same issue. It appears to be linked to navigating to the page from a specific modal (I'm using ajax hash paging). The footer doesn't load and after I interact with the first feature on the map the following happens;
The map jumps and stretches/smears slightly
The footer shows up on my page
The vertical scroll bar appears
The issue doesn't seem to occur when i link from another page.
I have the same problem.Here are some advices may help you:
check the the size of map's container(may be a Div).
check the size of map(openlayers's map object).
compare that two size to confirm whether the two size are equal.
if not, you can use the map.setSize([width,height])to adjust the map's size.

Open Layers 3 Icon overlap tearing

I have a vector layer with a lot of close together data, each rendered by an icon. When rendered in Open Layers 3 using icons of any type/design I often get tearing of elements trying to get through others, I'm sure many people using Open Layers will have seen this happen.
Is there a way of solving this issue?
My code is fairly standard:
var styleCache2 = {};
var WFS_layer_Dangerous_Bends = new ol.layer.Vector({
source : new ol.source.GeoJSON({
projection : 'EPSG:3857',
url : "Vector_Data/A_Vector_Data_Set.geojson"
}),
style : function(feature, resolution) {
if (!styleCache2[path]) {
styleCache2[path] = [new ol.style.Style({
fill : new ol.style.Fill({
color : 'rgba(255, 255, 255, 0.1)'
}),
stroke : new ol.style.Stroke({
color : '#319FD3',
width : 1
}),
image: new ol.style.Icon(({
anchor: [x_anchor, y_anchor],
anchorXUnits: 'pixels',
anchorYUnits: 'pixels',
src: path
}))
}),
zIndex : 1
})];
}
return styleCache2[path];
}
});
/*Creating the map object linked to the map selector/div in the HTML */
map_object = new ol.Map({
target: 'map',
controls: controls_list,
interactions: interactions_list,
overlays: [overlay],
layers: [OSM_raster, WFS_layer_Dangerous_Bends],
view: view
});
Obviously overlay, controls_list, interactions_list and the OSM_raster are defined somewhere too, but I don't think they're relevant to the question so I haven't included them.
I tried to capture an example, it's quite difficult because its intermittent, this shows about 5 icons overlapping normally, but a couple in the middle are tearing through each other:

Resources