mirror of
https://github.com/Viglino/ol-ext.git
synced 2026-01-25 17:36:21 +00:00
301 lines
8.7 KiB
HTML
301 lines
8.7 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<!--
|
|
Copyright (c) 2015-2019 Jean-Marc VIGLINO,
|
|
released under CeCILL-B (french BSD like) licence: http://www.cecill.info/
|
|
-->
|
|
<title>ol-ext: Flow style</title>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
|
|
|
<meta name="description" content="Draw flow maps or Sankey maps with Openlayers." />
|
|
<meta name="keywords" content="ol, openlayers, vector, style, stroke, width, color, variable, sankey, flow, arrow" />
|
|
|
|
<link rel="stylesheet" href="../style.css" />
|
|
|
|
<!-- jQuery -->
|
|
<script type="text/javascript" src="https://code.jquery.com/jquery-1.11.0.min.js"></script>
|
|
<!-- FontAwesome -->
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
|
|
|
|
<!-- Openlayers -->
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/ol@latest/ol.css" />
|
|
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/ol@latest/dist/ol.js"></script>
|
|
|
|
|
|
<!-- ol-ext -->
|
|
<link rel="stylesheet" href="../../dist/ol-ext.css" />
|
|
<script type="text/javascript" src="../../dist/ol-ext.js"></script>
|
|
<!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
|
|
<script src="https://unpkg.com/elm-pep"></script>
|
|
|
|
<style>
|
|
#map {
|
|
width: 100%;
|
|
min-height: 400px;
|
|
height: 70vh;
|
|
}
|
|
.options label {
|
|
display: inline-block;
|
|
text-align: right;
|
|
min-width: 4em;
|
|
}
|
|
.options input[type="number"] {
|
|
width: 5em;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body >
|
|
<a href="https://github.com/Viglino/ol-ext" class="icss-github-corner"><i></i></a>
|
|
|
|
<a href="../../index.html">
|
|
<h1>ol-ext: Flow line style</h1>
|
|
</a>
|
|
<div class="info">
|
|
<p>
|
|
The <i>ol.style.FlowLine</i> is a line style to draw LineString with variable colors and widths.
|
|
<br/>
|
|
This can be used to display <a href="https://en.wikipedia.org/wiki/Flow_map">flows</a> maps
|
|
or <a href="https://en.wikipedia.org/wiki/Sankey_diagram">Sankey diagram</a> on a map.
|
|
</p>
|
|
<ul>
|
|
</ul>
|
|
<p>
|
|
Look at <a href='map.style.flowline.html'>this example</a> for more information on FlowLine style.
|
|
</p>
|
|
</div>
|
|
|
|
<!-- Map div -->
|
|
<div id="map"></div>
|
|
|
|
<div class="options" style="min-width:300px;">
|
|
<h2>Options:</h2>
|
|
<ul>
|
|
<li>
|
|
<label>color:</label>
|
|
<select class="color" onchange="vector.changed();">
|
|
<option value='red' selected="selected">red</option>
|
|
<option value='yellow'>yellow</option>
|
|
<option value='#0f0'>green</option>
|
|
<option value='#00f'>blue</option>
|
|
<option value='#fff'>white</option>
|
|
<option value='#000'>black</option>
|
|
<option value='rgba(255,255,255,0)'>transparent</option>
|
|
</select>
|
|
</li>
|
|
<li>
|
|
<label>color2:</label>
|
|
<select class="color2" onchange="vector.changed();">
|
|
<option value='red'>red</option>
|
|
<option value='yellow' selected="selected">yellow</option>
|
|
<option value='#0f0'>green</option>
|
|
<option value='#00f'>blue</option>
|
|
<option value='#fff'>white</option>
|
|
<option value='#000'>black</option>
|
|
<option value='rgba(255,255,255,0)'>transparent</option>
|
|
</select>
|
|
</li>
|
|
<li>
|
|
<label>Offset:</label>
|
|
<input class="offset" value="10" type="number" step=1 onchange="vector.changed();" />px
|
|
</li>
|
|
<li>
|
|
<label>
|
|
Curve lines :
|
|
<select id="curve" onchange="vector.changed();">
|
|
<option value="0">none</option>
|
|
<option value="curve">curve</option>
|
|
<option value="circle">circle</option>
|
|
</select>
|
|
</label>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<script type="text/javascript">
|
|
|
|
// Layers
|
|
var layer = new ol.layer.Geoportail({ layer: 'ORTHOIMAGERY.ORTHOPHOTOS' });
|
|
|
|
// The map
|
|
var map = new ol.Map({
|
|
target: 'map',
|
|
view: new ol.View ({
|
|
zoom: 7,
|
|
center: [218664, 6158372]
|
|
}),
|
|
layers: [layer]
|
|
});
|
|
// GeoJSON layer
|
|
var dep = new ol.layer.VectorImage ({ source: new ol.source.Vector({
|
|
url: '../data/departements.geojson',
|
|
format: new ol.format.GeoJSON(),
|
|
attributions: [ "© <a href='https://www.insee.fr'>INSEE</a>", "© <a href='https://www.data.gouv.fr/fr/datasets/geofla-r/'>IGN</a>" ],
|
|
})
|
|
});
|
|
map.addLayer(dep);
|
|
|
|
// Read Data
|
|
var flowData = {};
|
|
// Event handlers when source is ready
|
|
var listener = dep.getSource().on('change',function(e) {
|
|
ol.Observable.unByKey(listener)
|
|
if (dep.getSource().getState() === 'ready') {
|
|
var sel;
|
|
dep.getSource().getFeatures().forEach(function (f) {
|
|
var p, g = f.getGeometry();
|
|
if (f.get('id')==='41') sel = f;
|
|
if (g.getInteriorPoint) {
|
|
p = g.getInteriorPoint().getFirstCoordinate();
|
|
} else {
|
|
var max = 0;
|
|
g.getPolygons().forEach(function(poly) {
|
|
var a = poly.getArea();
|
|
if (max<a) {
|
|
max = a;
|
|
p = poly.getInteriorPoint().getFirstCoordinate();
|
|
}
|
|
});
|
|
}
|
|
flowData[f.get('id')] = {
|
|
xy: p,
|
|
data: []
|
|
};
|
|
})
|
|
$.ajax({
|
|
url: '../data/mobilite-2017.csv',
|
|
success: function (data) {
|
|
data = data.split('\n');
|
|
data.shift();
|
|
data.forEach(function(l) {
|
|
l = l.split(',');
|
|
if (flowData[l[0]] && flowData[l[1]]) {
|
|
flowData[l[0]].data.push ({
|
|
dep: l[1],
|
|
xy: flowData[l[1]].xy,
|
|
flow: parseInt(l[2])
|
|
});
|
|
}
|
|
})
|
|
}
|
|
});
|
|
setTimeout(function() {
|
|
select.dispatchEvent({ type:'select', selected:[sel] })
|
|
}, 0);
|
|
}
|
|
});
|
|
|
|
// Default style to make the feature selectable
|
|
var defaultStyle = new ol.style.Style({
|
|
stroke: new ol.style.Stroke({ color: [255, 255, 255, .1], width: 2.5 })
|
|
});
|
|
|
|
// Get geom
|
|
function getGeom(f) {
|
|
switch ($('#curve').val()) {
|
|
case 'curve': {
|
|
var l = f.getGeometry().getCoordinates();
|
|
var p1 = l.pop();
|
|
var p0 = l[0];
|
|
var r = map.getView().getResolution();
|
|
l.push([
|
|
p0[0] + 8*(p1[0]-p0[0]) / 10,
|
|
p1[1] + (p1[1]-p0[1] < -30*r ? 3*Math.abs(p1[1]-p0[1])/4 : 40*r)
|
|
]);
|
|
l.push(p1);
|
|
var sp = ol.coordinate.cspline(l, {
|
|
resolution: 500,
|
|
tension: .75
|
|
});
|
|
return (new ol.geom.LineString(sp));
|
|
}
|
|
case 'circle': {
|
|
var l = f.getGeometry().getCoordinates();
|
|
var p1 = l.pop();
|
|
var p0 = l[0];
|
|
var dx = (p1[0] - p0[0]);
|
|
var dy = (p1[1] - p0[1]);
|
|
var a = Math.atan2(dy,dx);
|
|
if (a < 0 || a > Math.PI) {
|
|
dx=-dx;
|
|
dy=-dy;
|
|
}
|
|
l.push([
|
|
(p0[0]+p1[0])/2 + dy / 3,
|
|
(p0[1]+p1[1])/2 - dx / 3
|
|
]);
|
|
l.push(p1);
|
|
var sp = ol.coordinate.cspline(l, {
|
|
resolution: 500,
|
|
tension: .75
|
|
});
|
|
return (new ol.geom.LineString(sp));
|
|
}
|
|
default: {
|
|
return f.getGeometry();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Flow style
|
|
var done = false;
|
|
function getStyle(feature, res) {
|
|
var flowStyle = new ol.style.FlowLine({
|
|
color: $('.color').val(),
|
|
color2: $('.color2').val(),
|
|
width: 2,
|
|
width2: feature.get('flow'),
|
|
offset0: parseInt($('.offset').val()),
|
|
arrow: 1,
|
|
geometry: getGeom,
|
|
zIndex: -(feature.getGeometry().getLastCoordinate()[1])
|
|
});
|
|
return [ defaultStyle, flowStyle ];
|
|
}
|
|
|
|
// Nouvelle source de donnee
|
|
var vector = new ol.layer.VectorImage({
|
|
source: new ol.source.Vector(),
|
|
style: getStyle
|
|
})
|
|
map.addLayer(vector);
|
|
|
|
var popup = new ol.Overlay.Popup({ className: 'tooltips' });
|
|
map.addOverlay(popup);
|
|
|
|
var hover = new ol.interaction.Hover({ cursor: 'pointer', layers: [vector], hitTolerance:2 });
|
|
map.addInteraction(hover);
|
|
hover.on('hover', function(e) {
|
|
popup.show(e.coordinate, e.feature.get('flux'));
|
|
});
|
|
hover.on('leave', function(e) {
|
|
popup.hide();
|
|
});
|
|
|
|
// global so we can remove it later
|
|
var select = new ol.interaction.Select ({
|
|
condition: ol.events.condition.Click,
|
|
layers: [dep]
|
|
});
|
|
map.addInteraction(select);
|
|
select.on('select', function(e) {
|
|
var f = e.selected[0];
|
|
vector.getSource().clear();
|
|
if (f) {
|
|
var id = f.get('id');
|
|
var dep = flowData[id]
|
|
dep.data.forEach(function(d) {
|
|
if (d.flow > 300 && d.dep !== id) {
|
|
var l = new ol.Feature(new ol.geom.LineString([dep.xy, d.xy]))
|
|
l.set('flow', Math.max(2, Math.min(30, d.flow/300)));
|
|
l.set('flux', d.flow.toLocaleString());
|
|
vector.getSource().addFeature(l);
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
</script>
|
|
|
|
</body>
|
|
</html> |