Rotating marker (icon) in openlayers 3 - openlayers-3

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'
})
)

Related

React+Konva: How to use strokeLinearGradientColorStops?

I am trying to give an ellipse in my Stage (I am using React) a gradient color, like css's border-color with a linear gradient.
I have tried to use strokeLinearGradientColorStops, that will show an empty ellipse. I have also tried using strokeLinearGradientColorStops + strokeLinearGradientStartPoints + StrokeLinearGradientEndPoint, but that turned out weird: when I move my circle around the Stage the gradient will be different, so it was like a gradient color applied to the entire Stage and only showing up on the ellipse
<Ellipse
strokeLinearGradientStartPoint={{ x: 0, y: 0 }}
strokeLinearGradientEndPoint={{ x: 200, y: 150 }}
strokeLinearGradientColorStops={[0, "blue", 1, "yellow"]}
/>
Ofcourse given the parameters of strokeLinearGradientStart and endPoint, I should expect the color to be applied to the stage instead of the element.
If this was the expected result, is there anyway around it? I have also tried to select these elements in css, but Stage maps to a canvas so I don't think I can access the individual elements as they are just pixels.

Issues when drawing using scale

I have a KonvaJS application and I'm dealing with an issue using the scale option.
You can see the problem here:
Issue example
I use the KonvaJS Line class to draw and it's working fine. But when I change the Stage scale then the problem comes up. It's like the cursor is in a different position.
I tried different solutions without luck.
Any ideas on how to solve this issue?
Thanks in advance.
You just need to adapt mouse position to stage transform. You can do this:
const pos = stage.getPointerPosition();
const stageTransform = stage.getAbsoluteTransform().copy();
const position = stageTransform.invert().point(pos);
layer.add(new Konva.Circle({
x: position.x,
y: position.y,
radius: 10,
fill: 'red'
}));
Demo: http://jsbin.com/gaqepodivu/1/edit?js,output

How to properly align Font Awesome symbols on Highcharts scatter plots?

Using the Highcharts example posted here how can you ensure that the Font Awesome icons will be positioned exactly in the middle of the data point like the native symbols/markers are? It gets called like this in the data series and uses the "plugin" that is found in that same Fiddle:
marker: {
symbol: 'text:\uf183' // fa-male
}
Using that example, if you toggle the series on/off a couple of times or zoom in/out the icons are no longer visually accurate, often displaying above the actual coordinate. In the image below you'd believe that data point had a value >50 based on where the icon is.
Their SVGRenderer example here doesn't seem to be effected.
It looks like problem with re-rendering icons later - height of the marker isn't considered. I suggest to change a bit logic for rendering icon:
var text = symbol.split(':')[1],
svgElem = this.text(text, x, y)
.attr({
translateY: h, // translate marker
translateX: -1
})
.css({
fontFamily: 'FontAwesome',
fontSize: h * 2
});
See demo: http://jsfiddle.net/2A7Zf/29/
If you want to use the markers XL-sized (i.e larger radius) for a custom chart (e.g. a Yes/No prevalence chart using the x and check icons, circle empty for the less prevalent one and circle filled for the more prevalent one and data labels showing counts/%s), then I'd recommend this tweak to center the symbols:
translateX: -w/2 + options.radius/4 - 3

Images along on a line

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

Make one layer to not rotate with map

I have layer with pictures, I want them to stay as they are and don't rotate with map when I call map.getView().setRotation(x) . There is option to disable rotation for map, but is it possible to disable rotation for one layer?
If your "layer with pictures" is a vector layer with icon images, the icons won't rotate by default. You can control rotation of icons by configuring the icon style with the rotateWithView option. The default is false. Make sure you don't have a style like this:
new ol.style.Style({
image: new ol.style.Icon({
src: 'data/image.png',
rotateWithView: true
})
});
If you do, just remove the rotateWithView: true line.
If your layer is a WMS layer, and your images are point styles, you may be lucky to have a WMS server that supports rotation. Then you can add a vendor option (ANGLE for GeoServer and MapServer) and update that whenever the view rotation changes:
map.getView().on('change:rotation', function() {
wmsLayer.getSource().updateParams({
ANGLE: map.getView().getRotation() / Math.PI * 180
});
The above snippet assumes that map is your ol.Map instance and wmsLayer is your ol.layer.Image instance with an ol.source.ImageWMS.
As far as I know, you can't disable rotation for one layer. As suggests the answer from #ahocevar the best practice should be to display your "pictures" in a separate vector layer and use the rotateWithView options in the style definition of this layer.

Resources