简体   繁体   English

OpenLayers 3:偏移描边样式

[英]OpenLayers 3: Offset stroke style

I have LineString features styled by a single stroke.我有一个 LineString 功能,由一个笔划设置样式。 Some of these features represent two things, so in addition to the initial stroke color, I would like to have a parallel line next to it in a different color.其中一些特征代表两件事,所以除了初始笔划颜色之外,我还想在它旁边有一条不同颜色的平行线。 This would be a no-brainer if ol/style/Stroke had an offset property like ol/style/Image does, but sadly, it does not.如果ol/style/Stroke具有像ol/style/Image那样的偏移属性,这将是一个明智的选择,但遗憾的是,它没有。 If I created offset geometries for those features, they wouldn't be visible from a zoomed out level.如果我为这些特征创建了偏移几何体,它们将不会在缩小的水平上可见。 What are my options?我有哪些选择?

You can offset the geometries based on resolution 您可以根据分辨率偏移几何形状

 var style = function(feature, resolution) { var colors = ['green', 'yellow', 'red']; var width = 4; var styles = []; for (var line = 0; line < colors.length; line++) { var dist = width * resolution * (line - (colors.length-1)/2); var geom = feature.getGeometry(); var coords = []; var counter = 0; geom.forEachSegment(function(from, to) { var angle = Math.atan2(to[1] - from[1], to[0] - from[0]); var newFrom = [ Math.sin(angle) * dist + from[0], -Math.cos(angle) * dist + from[1] ]; var newTo = [ Math.sin(angle) * dist + to[0], -Math.cos(angle) * dist + to[1] ]; coords.push(newFrom); coords.push(newTo); if (coords.length > 2) { var intersection = math.intersect(coords[counter], coords[counter+1], coords[counter+2], coords[counter+3]); coords[counter+1] = (intersection) ? intersection : coords[counter+1]; coords[counter+2] = (intersection) ? intersection : coords[counter+2]; counter += 2; } }); styles.push( new ol.style.Style({ geometry: new ol.geom.LineString(coords), stroke: new ol.style.Stroke({ color: colors[line], width: width }) }) ); } return styles; }; var raster = new ol.layer.Tile({ source: new ol.source.OSM() }); var source = new ol.source.Vector(); var vector = new ol.layer.Vector({ source: source, style: style }); var map = new ol.Map({ layers: [raster, vector], target: 'map', view: new ol.View({ center: [-11000000, 4600000], zoom: 4 }) }); map.addInteraction(new ol.interaction.Draw({ source: source, type: 'LineString' })); 
 html, body, .map { margin: 0; padding: 0; width: 100%; height: 100%; } 
 <link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" /> <script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.4.1/math.min.js"></script> <div id="map" class="map"></div> 

The intersect test prevents effects like this on sharp angles 相交测试可防止这样的锐角影响

在此处输入图片说明

For each each segment of the feature geometry the style function calculates parallel segments set to be 4 pixels apart regardless of the resolution (in this case line width and spacing are the same) for the styling geometries centered around the original segment (eg if three colors the center style line would follow the original and the outer style lines are offset by +/- 4, if two colors each lines would be offset by +/- 2) Initially the parallel segments are the same length as the original but need to be increased at outside angles or reduced at inside angles so math.intersect is used to find the point where they should join to form a continuous line. 对于要素几何的每个分段,样式函数都会计算平行分段,间距设为4个像素,而与分辨率(在这种情况下,线宽和间距相同)无关,而以原始分段为中心的样式几何(例如,如果三种颜色中心样式线将跟随原始样式,而外部样式线将偏移+/- 4,如果每条线的两种颜色都将偏移+/- 2)最初,平行线段的长度与原始样式相同,但需要在math.intersect处增加或在内角处减小,因此使用math.intersect来查找它们应连接以形成连续线的点。 Finally for each color the completed linestring is used as the geometry for the color's style, and an array containing each style is returned. 最后,对于每种颜色,将完整的线串用作该颜色样式的几何图形,并返回包含每种样式的数组。

Here is a second example where instead of simple colors and fixed width each offset line has its own width and stroke pattern. 这是第二个示例,其中,每条偏移线都具有自己的宽度和笔划样式,而不是简单的颜色和固定的宽度。

 var white = [255, 255, 255, 1]; var blue = [0, 153, 255, 1]; var width = 3; var pointStyle = new ol.style.Style({ image: new ol.style.Circle({ radius: width * 2, fill: new ol.style.Fill({ color: blue }), stroke: new ol.style.Stroke({ color: white, width: width / 2 }) }), zIndex: Infinity }); var style = function(feature, resolution) { var widths = [10, 10]; var strokes = [ [ { width: 4, color: '#7af500' }, { width: 4, color: '#55aa00', lineDash: [7,9] } ], [ { width: 2, color: 'black' }, { width: 8, color: 'black', lineDash: [2,14], lineCap: 'butt' } ] ]; var styles = [pointStyle]; var totalWidth = 0 for (var line = 0; line < widths.length; line++) { totalWidth += widths[line]; } var width = 0; for (var line = 0; line < widths.length; line++) { var dist = (width + widths[line]/2 - totalWidth/2) * resolution; width += widths[line]; var geom = feature.getGeometry(); if (geom.forEachSegment) { var coords = []; var counter = 0; geom.forEachSegment(function(from, to) { var angle = Math.atan2(to[1] - from[1], to[0] - from[0]); var newFrom = [ Math.sin(angle) * dist + from[0], -Math.cos(angle) * dist + from[1] ]; var newTo = [ Math.sin(angle) * dist + to[0], -Math.cos(angle) * dist + to[1] ]; coords.push(newFrom); coords.push(newTo); if (coords.length > 2) { var intersection = math.intersect(coords[counter], coords[counter+1], coords[counter+2], coords[counter+3]); coords[counter+1] = (intersection) ? intersection : coords[counter+1]; coords[counter+2] = (intersection) ? intersection : coords[counter+2]; counter += 2; } }); strokes[line].forEach( function(stroke) { styles.push( new ol.style.Style({ geometry: new ol.geom.LineString(coords), stroke: new ol.style.Stroke(stroke) }) ); }); } } return styles; }; var raster = new ol.layer.Tile({ source: new ol.source.OSM() }); var source = new ol.source.Vector(); var vector = new ol.layer.Vector({ source: source, style: style }); var map = new ol.Map({ layers: [raster, vector], target: 'map', view: new ol.View({ center: [-11000000, 4600000], zoom: 4 }) }); map.addInteraction(new ol.interaction.Draw({ source: source, style: style, type: 'LineString' })); 
 html, body, .map { margin: 0; padding: 0; width: 100%; height: 100%; } 
 <link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" /> <script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.4.1/math.min.js"></script> <div id="map" class="map"></div> 

I have a version of this that works - but not when I zoom the chart.我有一个可以使用的版本 - 但当我缩放图表时却不行。

Lines separates on zoom缩放时线条分开

I plot lines on the chart (from the database) and use our function to draw the lines.我在图表上的 plot 线(来自数据库)并使用我们的 function 来绘制线。

I tried to insert code here but my functions in the javascript are not run.我试图在这里插入代码,但我在 javascript 中的函数没有运行。 How do I use functions in code snipplets?如何在代码片段中使用函数?

 function print_my_string( my_string ) { console.log( my_string ); }
 html, body, .map { margin: 0; padding: 0; width: 100%; height: 100%; }
 <link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" /> <script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.4.1/math.min.js"></script> <div id="map" class="map"></div> // How do I use the java-script (Include before called... <script>print_my_string( "Hello" );</script>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM