I am wondering how 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.
My current code:
line = new ol.geom.LineString([[0, 0], [100, 100]]);
lineStyle = new ol.style.Style({
stroke: new ol.style.Stroke({
color: 'black',
width: 5,
lineDash: [10, 10]
}),
});
lineFeature = new ol.Feature({
geometry: line,
});
lineFeature.setStyle(lineStyle);
. . .
map = new ol.Map({
layers: [
new ol.layer.Vector({
source: new ol.source.Vector({
features: [
lineFeature,
],
}),
})
],
. . .
EDIT 2:
Here is what my line looks like:
(See image)
Here is what it should look like:
(See image)
It could be like this, or pictures of anchors.
EDIT:
New style code (not working):
lineStyle = new ol.style.Style({
radius: 10,
images: './icon.png',
stroke: new ol.style.Stroke({
color: 'black',
width: 5,
lineDash: lineDash,
}),
});
Am I doing anything wrong?
EDIT 3:
I have figured out how to do this:
Using Blender, add a mesh and add vertices on where the vertices are on your line.
Convert the mesh to a curve (Alt-C).
Add a plane and add your image to it as a texture.
Scale the plane to the appropriate size relative to the line (S).
Add an Array modifier to the plane with the image and choose Fit Curve for Fit Type.
Set the Curve: to the name of the curve you created from the mesh.
Set the Relative Offset’s first box to the space between the dots (relative to the size of the dots)
Add a Curve modifier to the plane and choose the curve you created as the Object:.
Note: This may result in the images being deformed. If this occurs, follow these steps:
Duplicate the plane (Alt-D)
Remove the Array and Curve modifiers from the duplicate.
Parent the duplicate plane to the original plane.
Select the duplicate plane, then the original plane.
Press Ctrl-P.
Select Object.
In the original plane, go to the Object buttons (orange cube) and select Faces under Duplication.
This will place a copy of the plane at the center of each face.
There is currently no support for this in OpenLayers 3, I am also trying to find a mechanism that would work well and scale with many features. The only thing currently available in OpenLayers 3 to acheive this would be to use this technique, but it would greatly affect performance: http://boundlessgeo.com/2015/04/geometry-based-styling-openlayers-3/
A live example is available here:
http://openlayers.org/en/master/examples/line-arrows.html
To acheive the kind of style you want, you would have to compute points along the line for the given resolution and assign a ol.style.Icon for those points.
I guess it could be possible to implement more advanced stroke styles in OpenLayers 3, the following page demonstrates multiple techniques to render strokes with Canvas: http://perfectionkills.com/exploring-canvas-drawing-techniques/
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: lineDash,
})
});
Visit these links to find more about this.
http://openlayers.org/en/v3.8.1/apidoc/ol.style.Style.html
http://openlayers.org/en/v3.6.0/apidoc/ol.style.Icon.html
Related
I have a feature with an Image, it shows well on the map.
var style = new ol.style.Style({
image: new ol.style.Icon(/** #type {olx.style.IconOptions} */ ({
src: imagesource,
})),
});
But when I add a select control on the layer
var selectcontrol = new ol.interaction.Select({
});
Only part of the image is clickable if the image is larger. Is there any settings to set here so that the whole image is clickable.
Here is a fiddle for the issue, you can see the cursor changes as you move to the center of the image, but the feature is not detected at the corners of the image
http://jsfiddle.net/c88keve7/2/
You can set the renderBuffer property when creating your vector layer. See ol.layer.Vector:
renderBuffer: The buffer around the viewport extent used by the renderer when getting features from the vector source for the rendering or hit-detection. Recommended value: the size of the largest symbol, line width or label. Default is 100 pixels.
I've added a series to a chart:
chart.addSeries({
id: 'child-bmi-scores',
name: 'Child\'s BMI',
color: 'blue',
type: 'scatter',
showInLegend: false,
data: [ [3, 20], [10, 16] ]
});
and later on, I want to add a point to that series. So I've done that:
var chart = chartContainer.highcharts();
var series = chart.get('child-bmi-scores');
series.addPoint(
{
x: 16.5,
y: 19,
height: 456,
weight: 789,
ageYears: 16,
ageMonths: 6
}
);
The point does get added, but the trouble is that the blue marker is not visible.
You can see from the image below, the two visible blue squares are from the initial data: [ [3, 20], [10, 16] ], and you can see the crosshairs focussing in on the newly added point - it's definitely there, but without the crosshairs hovering over the point, you just don't see it.
The other curves that you can see are all areaspline series also on the chart.
I'm wondering if the Z-order has got messed up and the new point is somehow behind one of the area splines?
I created a fiddle that demonstrates what I mean:
http://jsfiddle.net/j08L6afh/
So before you click the "Add point" button, hover around and prove there are only two scatter points. Then, if you click the button at the top, then it will add the point, you'll be able to find it by hovering your mouse near and getting the crosshairs, but you won't see the marker.
UPDATE
I removed the curves off the chart, so that the scatter was the only series:
http://jsfiddle.net/j08L6afh/1/
Now you can see it works as expected, so it would appear to be being hidden by one or more of the curves. How can I make the new point at the front?
So I solved this by doing a .push onto an array of measurements, and reinitialising the entire chart.
It worked, but I imagine there is a better way?
Is it possible to make the symbolizer of a feature be a polygon?
Openlayers 3 has a ol.style.Circle and ol.style.RegularShape symbolizers for example. Is there something equivalent to a hypothetical ol.style.Polygon? Whereby you could make a dynamic symbolizer from multiple points?
The reason I want to do this is because I have markers on my map that are dynamically shaped depending on the data for that marker. It is possible to simply draw a ol.geom.Polygon at each point, but then they are not zoom independent. I want to have markers that are zoom independent, meaning that their size on the screen does not change when I zoom in or out.
And just to be clear, using raster images (for example in ol.style.Icon) is not possible. There are way too many markers in way too many shapes and colours in my project.
Yes, this is possible. ol.style.Style takes a geometry argument that you can use to overwrite the geometry that is used to render a feature.
var style = function(feature, resolution) {
// construct the polygon taking the resolution into account
var polygon = new ol.geom.Polygon(...);
return [
new ol.style.Style({
geometry: polygon,
stroke: ...
fill: ...
}),
];
};
Also see this question: Drawing a Speed Leader line in OpenLayers
In my OpenLayers3 map, I can easily create points or linestrings.
When I modify linestrings, I can set up the Modify interaction to be able to delete a vertex on a shift-click. I then get a callback on the linestring feature on('change') event.
For points, I get no such callback and in fact the shift-click does not delete the point.
I was referencing this example:
http://openlayers.org/en/v3.2.1/examples/draw-and-modify-features.html?q=modify
Now that I think about it, what I really might want to do is have a select interaction and when the user selects a point with a shift-click, that point would be deleted.
Has anyone else solved this problem?
Thanks
--
I updated my application to have a selection handler for deletion; Now I'm having a problem where the selection is happening on a click, even though I specify it should select on a shift-click.
this.stationDeleter = new ol.interaction.Select({
layers: [this.stationsLayer],
// for debugging
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 12,
fill: new ol.style.Fill({
color: 'rgba(255, 0, 0, 0.5)'
})
})
}),
addCondition: function(event) {
return ol.events.condition.shiftKeyOnly(event)
&& ol.events.condition.singleClick(event);
}
});
There is a difference between deleting a vertex of a feature and deleting the whole geometry. To delete the whole geometry it's a good idea to use a Select interaction. Like in this example: http://openlayers.org/en/master/examples/modify-features.html
If there is a feature selected, you could show a control with a button "Remove selected feature".
I m using openlayers 3 in my project. I created a custom marker (icon) and i need to rotate marker with angle.
Is anybody tried this before? It is a critical part of my code and i couldnt figure it out.
Note: Not the map. just marker.
Set up an overlay like in the icon example and apply CSS rotation to it (ie. transform: rotate(120deg);, add browser prefixed versions as needed). If you need this to be dynamic, adjust the property through JavaScript.
In current versions of OpenLayers 3, you can use the rotation property of ol.style.Icon like this:
new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 0.5],
anchorXUnits: 'fraction',
anchorYUnits: 'fraction',
rotation: Math.PI / 2.0,
src: 'icon.png'
})
)