add image along the lineString in Openlayers3 - openlayers-3

I would like to place images on a line. For example, instead of a dotted or dashed line, I could include a symbol of a ship or a character (e.g. |) repeated along the line.
Here is code:
lineStyle = new ol.style.Style({
image: new ol.style.Icon(({
opacity: 1,
size:20,
src: './icon.png'
})),
stroke: new ol.style.Stroke({
color: 'black',
width: 5,
lineDash: [10]
})
});
I want to get a result like this:
Here is my example, but it cannot show the image along with line. http://jsfiddle.net/Wenhua1224/jguxq4j0/

Related

How to add a GeoJSON polygon feature to a vector source in OpenLayers 5

I am embarrassed by how elementary this problem seems, but I can't seem to work out how to simply add a GeoJSON polygon feature to a vector source.
I'm using OpenLayers 5, and up until now I've been creating a separate source and layer for every feature I'm adding to the map. The reason being I needed to be able to turn the visibility of individual polygons on and off, and this seemed like the best way to do that at the time. This worked at first, but I'm sure it's not the best practice - in effect I'm creating 200 layers and 200 sources for 200 polygons. I'd prefer to be creating one layer which uses one source which contains those 200 polygons.
This is what I currently have:
window["srcCells"] = new ol.source.Vector({});
window["ftr1"] = new ol.Feature({
geometry: new ol.geom.Polygon({ // <--- this is where I'm getting an error
coordinates: geometry.coordinates[0]
})
});
window["srcCells"].addFeature(window["ftr1"]);
window["lyrCells"] = new ol.layer.Vector({
name: "lyrCells",
source: window["srcCells"],
visible: true,
style: new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'rgba(255, 255, 255, 1)',
width: 0.5
}),
fill: new ol.style.Fill({
color: 'rgba(255, 255, 255, 0)'
}),
text: new ol.style.Text({
font: '11px Roboto',
overflow: false,
fill: new ol.style.Fill({
color: '#fff'
}),
stroke: new ol.style.Stroke({
color: '#333',
width: 2
})
})
})
});
map.addLayer(window["lyrCells"]);
console.dir(geometry.coordinates[0]); gives the following:
0: (3) [140.9528856796365, -37.00284635019008, 111.304]
1: (3) [140.9536707180603, -37.00304972058393, 113.03]
2: (3) [140.9537622719694, -37.00307250872015, 110.607]
3: (3) [140.95383548835147, -37.003105295678026, 110.64]
4: (3) [140.95393795398604, -37.003149857783384, 110.26276070403628]
5: (3) [140.95586925648476, -37.00401679761869, 111.192]
6: (3) [140.95644098404094, -37.00388629902322, 110.38710718081241]
7: (3) [140.95644582710668, -37.0051300157363, 111.17174176388276]
8: (3) [140.9528945167084, -37.00514320603378, 110.9445749409575]
9: (3) [140.95289318042316, -37.004769323489825, 113.688]
At the third line of the code above (where I've indicated), I'm getting this error:
SimpleGeometry.js:187 Uncaught TypeError: Cannot read property 'length' of undefined
at e.setLayout (SimpleGeometry.js:187)
at e.setCoordinates (Polygon.js:313)
at new e (Polygon.js:80)
geometry.coordinates[0] looks like an open linestring. To use it as a polygon you would need to close the ring and, as a polygon is an array of linear rings, enclose with []. Also the coordinates are the first parameter of the constructor, not an option:
geometry: new ol.geom.Polygon(
[ geometry.coordinates[0].concat([geometry.coordinates[0][0]]) ]
)
Alternatively you may need check that your data is polygon or linestring and use new ol.geom.LineString where appropriate

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 3 Resize a feature

I am using OpenLayers 3 and OpenStreetMap for my application.
I've managed to draw circle vectors on the map to draw markers, the problem I have is that the circles have always the same size when zooming in and out.
How can I change the size of the vectors according to the resolution ?
Here is my vector definition:
var dealerSource = new ol.source.Vector();
function dealerStyle(feature) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: 6,
stroke: new ol.style.Stroke({
color: 'white',
width: 2
}),
anchor: [1.5, 1.5],
fill: new ol.style.Fill({
color: 'green'
})
})
});
return [style];
}
you can change the size of your circle depending on the zoom level ( if that's what you want to do )
var dealerSource = new ol.source.Vector();
function dealerStyle(feature) {
var style = new ol.style.Style({
image: new ol.style.Circle({
radius: map.getView().getZoom(),
stroke: new ol.style.Stroke({
color: 'white',
width: 2
}),
anchor: [1.5, 1.5],
fill: new ol.style.Fill({
color: 'green'
})
})
});
return [style];
}
getZoom() returns the zoom level of your map as a number you can either use it or do a transformation on it to suit the desired size of your circle.
Note that above the bigger the zoom level is the bigger your circle will be drawn, to do the inverse you can replace the value by:
yourMaxZoomLevel - map.getView().getZoom()
you can also use getResolution() it returns a number too

Openlayers 3 Offset RegularShape

For clustered features I would like to make the following style in OL3:
A square, and on top of it another smaller square at the right-top corner. The bigger square would hold the symbol, and the smaller square would hold the number of the clustered features.
Similar to this
Is it possible to achieve this? In the API I've seen that ol.style.Icon and ol.style.Text has anchor and offset properties, but not RegularShape...
I have eventually overcome on this problem with using a single png image which included the square AND the smaller square, too, and overlayed the dynamic text on it, like this:
var clusterStyle = [new ol.style.Style({
image: new ol.style.Icon({
src: clustericon.png
}),
text: new ol.style.Text({
text: feature.get('features').length.size.toString(),
offsetY: -18,
offsetX: 18,
font: '12px Arial',
fill: new ol.style.Fill({
color: '#fff'
}),
scale: 1
}),
zIndex: 20
}), new ol.style.Style({
image: new ol.style.Icon({
src: 'overlayicon.png'
}),
zIndex: 21
})];
You can also insert an overlay image on it. Hope it helps you anyways

What's "an array of ol.style.Style" good for?

A style of an ol.layer.Vector can be set as ol.style.Style, a style function or an array of ol.style.Style. What's the array for and what does it do -- compared to just passing an ol.style.Style object?
I cannot find any information on this, neither in the official API docs nor in the tutorials.
If you look at the draw features example, when drawing lines, they are displayed in blue with a white border/outline.
These is achieved by styling the line twice, first with a large white line, then a thin blue line above.
There are 2 styles for the same geometry. It can’t be done with a single ol.style.Style, so to achieve this you need to pass an array of 2 styles: see the source for this.
Because I think this is still relevant and the edit queue is full for the approved answer, I'm posting this with the links updated and with code examples.
The most common way to see the array of styles in action is when drawing features since this is default style in Openlayers. For the line to appear blue with a white border it has to have two styles since it can't be done with a single Style. Openlayers does this by default like this:
styles['LineString'] = [
new Style({
stroke: new Stroke({
color: white,
width: width + 2,
}),
}),
new Style({
stroke: new Stroke({
color: blue,
width: width,
}),
}),
];
source
To expand on how usefull this feature could be you could check the custom polygons example. To have the vertices highlighted, they use two styles, one for the vertices and another for the polygon contour itself. Relevant piece of code:
const styles = [
new Style({
stroke: new Stroke({
color: 'blue',
width: 3,
}),
fill: new Fill({
color: 'rgba(0, 0, 255, 0.1)',
}),
}),
new Style({
image: new CircleStyle({
radius: 5,
fill: new Fill({
color: 'orange',
}),
}),
geometry: function (feature) {
// return the coordinates of the first ring of the polygon
const coordinates = feature.getGeometry().getCoordinates()[0];
return new MultiPoint(coordinates);
},
}),
];

Resources