Last active
September 24, 2024 14:50
-
-
Save pgiraud/6131715 to your computer and use it in GitHub Desktop.
OpenLayers 2 - Direction arrows along linestrings
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var map, drawControls; | |
function init() { | |
map = new OpenLayers.Map('map'); | |
var wmsLayer = new OpenLayers.Layer.WMS("OpenLayers WMS", "http://vmap0.tiles.osgeo.org/wms/vmap0?", { | |
layers: 'basic' | |
}); | |
var vector = new OpenLayers.Layer.Vector("Vector Layer", { | |
renderers: ['SVGExtended', 'VMLExtended', 'CanvasExtended'], | |
styleMap: new OpenLayers.StyleMap({ | |
'default': OpenLayers.Util.extend({ | |
orientation: true | |
}, OpenLayers.Feature.Vector.style['default']), | |
'temporary': OpenLayers.Util.extend({ | |
orientation: true | |
}, OpenLayers.Feature.Vector.style['temporary']) | |
}) | |
}); | |
map.addLayers([wmsLayer, vector]); | |
map.addControl(new OpenLayers.Control.LayerSwitcher()); | |
map.addControl(new OpenLayers.Control.MousePosition()); | |
drawControls = { | |
line: new OpenLayers.Control.DrawFeature( | |
vector, | |
OpenLayers.Handler.Path | |
), | |
modify: new OpenLayers.Control.ModifyFeature(vector) | |
}; | |
for (var key in drawControls) { | |
map.addControl(drawControls[key]); | |
} | |
map.setCenter(new OpenLayers.LonLat(0, 0), 3); | |
document.getElementById('noneToggle').checked = true; | |
} | |
function toggleControl(element) { | |
for (key in drawControls) { | |
var control = drawControls[key]; | |
if (element.value == key && element.checked) { | |
control.activate(); | |
} else { | |
control.deactivate(); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Copyright Pierre GIRAUD, https://gist.github.com/pgiraud/6131715 | |
* Published under WTFPL license. */ | |
/** | |
* @requires OpenLayers/Renderer/SVG.js | |
*/ | |
OpenLayers.Renderer.SVGExtended = OpenLayers.Class(OpenLayers.Renderer.SVG, { | |
eraseGeometry: function(geometry, featureId) { | |
this.removeArrows(geometry); | |
return OpenLayers.Renderer.SVG.prototype.eraseGeometry.apply(this, arguments); | |
}, | |
drawFeature: function(feature, style) { | |
if (feature.geometry) { | |
this.removeArrows(feature.geometry); | |
} | |
return OpenLayers.Renderer.SVG.prototype.drawFeature.apply(this, arguments); | |
}, | |
/** | |
* Method: drawLineString | |
* Method which extends parent class by also drawing an arrow in the middle | |
* of the line to represent it's orientation. | |
*/ | |
drawLineString: function(node, geometry) { | |
this.drawArrows(geometry, node._style); | |
return OpenLayers.Renderer.SVG.prototype.drawLineString.apply(this, arguments); | |
} | |
}); | |
/** | |
* @requires OpenLayers/Renderer/Canvas.js | |
*/ | |
OpenLayers.Renderer.CanvasExtended = OpenLayers.Class(OpenLayers.Renderer.Canvas, { | |
eraseGeometry: function(geometry, featureId) { | |
this.removeArrows(geometry); | |
return OpenLayers.Renderer.Canvas.prototype.eraseGeometry.apply(this, arguments); | |
}, | |
drawFeature: function(feature, style) { | |
if (feature.geometry) { | |
this.removeArrows(feature.geometry); | |
} | |
return OpenLayers.Renderer.Canvas.prototype.drawFeature.apply(this, arguments); | |
}, | |
/** | |
* Method: drawLineString | |
* Method which extends parent class by also drawing an arrow in the middle | |
* of the line to represent it's orientation. | |
*/ | |
drawLineString: function(geometry, style) { | |
this.drawArrows(geometry, style); | |
return OpenLayers.Renderer.Canvas.prototype.drawLineString.apply(this, arguments); | |
} | |
}); | |
/** | |
* @requires OpenLayers/Renderer/VML.js | |
*/ | |
OpenLayers.Renderer.VMLExtended = OpenLayers.Class(OpenLayers.Renderer.VML, { | |
eraseGeometry: function(geometry, featureId) { | |
this.removeArrows(geometry); | |
return OpenLayers.Renderer.VML.prototype.eraseGeometry.apply(this, arguments); | |
}, | |
drawFeature: function(feature, style) { | |
if (feature.geometry) { | |
this.removeArrows(feature.geometry); | |
} | |
return OpenLayers.Renderer.VML.prototype.drawFeature.apply(this, arguments); | |
}, | |
/** | |
* Method: drawLineString | |
* Method which extends parent class by also drawing an arrow in the middle | |
* of the line to represent it's orientation. | |
*/ | |
drawLineString: function(node, geometry) { | |
this.drawArrows(geometry, node._style); | |
return OpenLayers.Renderer.VML.prototype.drawLineString.apply(this, arguments); | |
} | |
}); | |
OpenLayers.Renderer.prototype.removeArrows = function(geometry) { | |
var i; | |
// remove any arrow already drawn | |
// FIXME may be a performance issue | |
var children = this.vectorRoot.childNodes, | |
arrowsToRemove = []; | |
for (i = 0; i < children.length; i++) { | |
var child = children[i]; | |
if (child.id.indexOf(geometry.id + "_arrow") != -1) { | |
arrowsToRemove.push(child); | |
} | |
} | |
for (i = 0; i < arrowsToRemove.length; i++) { | |
this.vectorRoot.removeChild(arrowsToRemove[i]); | |
} | |
}; | |
OpenLayers.Renderer.prototype.drawArrows = function(geometry, style) { | |
var i; | |
if (style.orientation) { | |
var pts = geometry.components; | |
var prevArrow, | |
distance; | |
for (i = 0, len = pts.length; i < len - 1; ++i) { | |
var prevVertex = pts[i]; | |
var nextVertex = pts[i + 1]; | |
var x = (prevVertex.x + nextVertex.x) / 2; | |
var y = (prevVertex.y + nextVertex.y) / 2; | |
var arrow = new OpenLayers.Geometry.Point(x, y); | |
arrow.id = geometry.id + '_arrow_' + i; | |
style = OpenLayers.Util.extend({}, style); | |
style.graphicName = "arrow"; | |
style.pointRadius = 4; | |
style.rotation = this.getOrientation(prevVertex, nextVertex); | |
if (prevArrow) { | |
var pt1 = this.map.getPixelFromLonLat(new OpenLayers.LonLat(arrow.x, arrow.y)), | |
pt2 = this.map.getPixelFromLonLat(new OpenLayers.LonLat(prevArrow.x, prevArrow.y)), | |
w = pt2.x - pt1.x, | |
h = pt2.y - pt1.y; | |
distance = Math.sqrt(w*w + h*h); | |
} | |
// don't draw every arrow, ie. ensure that there is enough space | |
// between two | |
if (!prevArrow || distance > 40) { | |
this.drawGeometry(arrow, style, arrow.id); | |
prevArrow = arrow; | |
} | |
} | |
} | |
}; | |
OpenLayers.Renderer.prototype.getOrientation = function(pt1, pt2) { | |
var x = pt2.x - pt1.x; | |
var y = pt2.y - pt1.y; | |
var rad = Math.acos(y / Math.sqrt(x * x + y * y)); | |
// negative or positive | |
var factor = x > 0 ? 1 : -1; | |
return Math.round(factor * rad * 180 / Math.PI); | |
}; | |
OpenLayers.Renderer.symbol.arrow = [0, 2, 1, 0, 2, 2, 1, 0, 0, 2]; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0"> | |
<meta name="apple-mobile-web-app-capable" content="yes"> | |
<title>Direction Arrows Example</title> | |
<link rel="stylesheet" href="http://openlayers.org/dev/theme/default/style.css" type="text/css"> | |
<link rel="stylesheet" href="http://openlayers.org/dev/examples/style.css" type="text/css"> | |
<style type="text/css"> | |
#controlToggle li { | |
list-style: none; | |
} | |
p { | |
width: 512px; | |
} | |
/* avoid pink tiles */ | |
.olImageLoadError { | |
background-color: transparent !important; | |
} | |
</style> | |
<script src="http://openlayers.org/dev/OpenLayers.js"></script> | |
<script type="text/javascript" src="ExtendedRenderers.js"></script> | |
<script type="text/javascript" src="direction-arrows.js"></script> | |
</head> | |
<body onload="init()"> | |
<h1 id="title">OpenLayers Draw Feature Example</h1> | |
<div id="tags"> | |
point, line, linestring, polygon, box, digitizing, geometry, draw, drag | |
</div> | |
<p id="shortdesc"> | |
Demonstrate the rendering of arrows to show line direction. Can be useful for routing or trails. | |
</p> | |
<div id="map" class="smallmap"></div> | |
<ul id="controlToggle"> | |
<li> | |
<input type="radio" name="type" value="none" id="noneToggle" | |
onclick="toggleControl(this);" checked="checked" /> | |
<label for="noneToggle">navigate</label> | |
</li> | |
<li> | |
<input type="radio" name="type" value="line" id="lineToggle" onclick="toggleControl(this);" /> | |
<label for="lineToggle">draw line</label> | |
</li> | |
<li> | |
<input type="radio" name="type" value="modify" id="modifyToggle" onclick="toggleControl(this);" /> | |
<label for="modifyToggle">modify</label> | |
</li> | |
</ul> | |
</body> | |
</html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Copyright (C) 2013 Pierre GIRAUD <[email protected]> | |
This work is free. You can redistribute it and/or modify it under the | |
terms of the Do What The Fuck You Want To Public License, Version 2, | |
as published by Sam Hocevar: | |
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
Version 2, December 2004 | |
Copyright (C) 2004 Sam Hocevar <[email protected]> | |
Everyone is permitted to copy and distribute verbatim or modified | |
copies of this license document, and changing it is allowed as long | |
as the name is changed. | |
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE | |
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |
0. You just DO WHAT THE FUCK YOU WANT TO. |
Thanks man, very nice code.
Beautiful. Thanks!
But how can I set My Style rule to it, for example strokeColor: '#010101'?
If you are going to overwrite the styles, you need to place the orientation property with any value
var vectorLayer = new OpenLayers.Layer.Vector("Overlay", {
renderers: ['SVGExtended', 'VMLExtended', 'CanvasExtended'],
styleMap: new OpenLayers.StyleMap({
'default': OpenLayers.Util.extend({
orientation: true
}, OpenLayers.Feature.Vector.style['default']),
'temporary': OpenLayers.Util.extend({
orientation: true
}, OpenLayers.Feature.Vector.style['temporary'])
}),
style : {
strokeColor : '#ff0000',
orientation : 'any value'
}
});
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Beautiful. Thanks!