• OpenLayers学习笔记(八)— 类似比例尺的距离环(二)


    openlayers 3 地图上创建一个距离环,始终以地图中心为中心,每个环之间的距离类似比例尺,随地图缩放而变化。

    添加具有覆盖整个范围的特征的虚拟层,其可以被设置为围绕地图中心的环。

    这篇是上一篇距离环文章的拓展和完善

    GitHub:八至

    作者:狐狸家的鱼

    在线预览

    这是模仿openlayers插件库ol-ext新出的canvas距离环功能,简直雪中送炭。

    代码:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>距离环</title>
        <link rel="stylesheet" href="css/ol.css" type="text/css">
        <script src="build/jquery.js"></script>
        <script src="build/ol.js"></script>
        <style>
            
    
            html,
            body {
                height: 100%;
                 100%;
                padding: 0px;
                margin: 0px;
            }
    
            .map {
                height: 100%;
                 100%;
            }
    
    
        </style>
    </head>
    <body>
        <div id="map"></div>
    
        <script>
    
            var map = new ol.Map({
                layers: [
                    new ol.layer.Tile({
                        source: new ol.source.OSM(),
                    })
                ],
                target: 'map',
                view: new ol.View()
            });
    
            ol.control.CanvasScaleLine = function(options) {
                ol.control.ScaleLine.call(this, options);
                this.scaleHeight_ = 6;
                // Get style options
                if (!options) options={};
                if (!options.style) options.style = new ol.style.Style();
                this.setStyle(options.style);
            }
            ol.inherits(ol.control.CanvasScaleLine, ol.control.ScaleLine);
            ol.control.CanvasScaleLine.prototype.setMap = function (map) {
                var oldmap = this.getMap();
                if (this._listener) ol.Observable.unByKey(this._listener);
                this._listener = null;
                ol.control.ScaleLine.prototype.setMap.call(this, map);
                if (oldmap) oldmap.renderSync();
                // Add postcompose on the map
                if (map) {
                    this._listener = map.on('postcompose', this.drawScale_.bind(this));
                } 
                // Hide the default DOM element
                this.element.style.visibility = 'hidden';
                this.olscale = this.element.querySelector(".ol-scale-line-inner");
            }
            ol.control.CanvasScaleLine.prototype.setStyle = function (style) {
                var stroke = style.getStroke();
                this.strokeStyle_ = stroke ? ol.color.asString(stroke.getColor()) : "#000";
                this.strokeWidth_ = stroke ? stroke.getWidth() : 2;
                var fill = style.getFill();
                this.fillStyle_ = fill ? ol.color.asString(fill.getColor()) : "#fff";
                var text = style.getText();
                this.font_ = text ? text.getFont() : "10px Arial";
                stroke = text ? text.getStroke() : null;
                fill = text ? text.getFill() : null;
                this.fontStrokeStyle_ = stroke ? ol.color.asString(stroke.getColor()) : this.fillStyle_;
                this.fontStrokeWidth_ = stroke ? stroke.getWidth() : 3;
                this.fontFillStyle_ = fill ? ol.color.asString(fill.getColor()) : this.strokeStyle_;
                // refresh
                if (this.getMap()) this.getMap().render();
            }
    
            ol.control.CanvasScaleLine.prototype.drawScale_ = function(e) {
                if ( this.element.style.visibility!=="hidden" ) return;
                var ctx = e.context;
                // Get size of the scale div
                var scalewidth = parseInt(this.olscale.style.width);
                if (!scalewidth) return;
                var text = this.olscale.textContent;
                var position = {left: this.element.offsetLeft, top: this.element.offsetTop};
                // Retina device
                var ratio = e.frameState.pixelRatio;
                ctx.save();
                ctx.scale(ratio,ratio);
                // Position if transform:scale()
                var container = this.getMap().getTargetElement();
                var scx = container.offsetWidth / container.getBoundingClientRect().width;
                var scy = container.offsetHeight / container.getBoundingClientRect().height;
                position.left *= scx;
                position.top *= scy;
                // On top
                position.top += this.element.clientHeight - this.scaleHeight_;
                // Draw scale text
                ctx.beginPath();
                ctx.strokeStyle = this.fontStrokeStyle_;
                ctx.fillStyle = this.fontFillStyle_;
                ctx.lineWidth = this.fontStrokeWidth_;
                ctx.textAlign = "center";
                ctx.textBaseline ="bottom";
                ctx.font = this.font_;
                ctx.strokeText(text, position.left+scalewidth/2, position.top);
                ctx.fillText(text, position.left+scalewidth/2, position.top);
                ctx.closePath();
                // Draw scale bar
                position.top += 2;
                ctx.lineWidth = this.strokeWidth_;
                ctx.strokeStyle = this.strokeStyle_;
                var max = 4;
                var n = parseInt(text);
                while (n%10 === 0) n/=10;
                if (n%5 === 0) max = 5;
                for (var i=0; i<max; i++) {
                    ctx.beginPath();
                    ctx.fillStyle = i%2 ? this.fillStyle_ : this.strokeStyle_;
                    ctx.rect(position.left+i*scalewidth/max, position.top, scalewidth/max, this.scaleHeight_);
                    ctx.stroke();
                    ctx.fill();
                    ctx.closePath();
                }
    
                // Calculate and draw rings corresponding to scale line
                var map = this.getMap();
                var proj = map.getView().getProjection();
                var center = ol.proj.transform(map.getView().getCenter(), proj, 'EPSG:4326');
                var sphere = ol.Sphere ? new ol.Sphere(6371008.8) : undefined;
                var t = text.split(' ');
                var multiplier = t[0]/max;
                switch (t[1]) {
                    case 'km':
                        multiplier *= 1000;
                        break;
                    case 'm':
                        multiplier *= 1;
                        break;
                    case 'mm':
                        multiplier *= 0.001;
                        break;
                    default:
                }
                for (var i=0; i<max; i++) {
                    var geometry = sphere ? ol.geom.Polygon.circular(sphere, center, (i+1)*multiplier, 128).transform('EPSG:4326', proj)
                                        : ol.geom.Polygon.circular(center, (i+1)*multiplier, 128).transform('EPSG:4326', proj);
                    var coordinates = geometry.getCoordinates()[0];
                    var pixels = [];
                    var top = [0, Infinity];
                    coordinates.forEach( function(coordinate) {
                        var pixel = map.getPixelFromCoordinate(coordinate);
                        pixels.push(pixel);
                        if (pixel[1] < top[1]) { top = pixel; }
                    });
                    ctx.moveTo(pixels[0][0], pixels[0][1]);
                    for (var j=1; j<pixels.length; j++) {
                        ctx.lineTo(pixels[j][0], pixels[j][1]);
                    }
                    ctx.lineWidth = this.strokeWidth_;
                    ctx.strokeStyle = this.strokeStyle_;
                    ctx.stroke();
                }
                // Draw scale text above the rings
                ctx.beginPath();
                ctx.strokeStyle = this.fontStrokeStyle_;
                ctx.fillStyle = this.fontFillStyle_;
                ctx.lineWidth = this.fontStrokeWidth_;
                ctx.textAlign = "center";
                ctx.textBaseline ="bottom";
                ctx.font = this.font_;
                ctx.strokeText(text, top[0], top[1]-this.strokeWidth_);
                ctx.fillText(text, top[0], top[1]-this.strokeWidth_);
                ctx.closePath();
    
                ctx.restore();
            }
    
            
            var proj = map.getView().getProjection();
            map.getView().setCenter(ol.proj.transform([-38, 75.9], 'EPSG:4326', proj));
            map.getView().setZoom(2);
            map.addControl(new ol.control.CanvasScaleLine());
        </script>
    </body>
    </html>
  • 相关阅读:
    快速排序
    jenkins 升级
    JAVA中的Random()函数
    拦截器
    两个链表合并不加入新的链表空间
    统计字符 比如aaabbcca----3a2b1c1a
    折半查找两种实现
    字符串偏移
    java值传递
    基于zookeeper实现配置集中管理【转】
  • 原文地址:https://www.cnblogs.com/suRimn/p/10297087.html
Copyright © 2020-2023  润新知