代码之家  ›  专栏  ›  技术社区  ›  Aenaon

传单.js:将功能属性传递给类构造函数

  •  1
  • Aenaon  · 技术社区  · 6 年前

    我有很多使用定义的svg标记(glyphs)(非常感谢名为rioV8的SO用户在这方面的帮助,不仅仅是这个…),理想情况下,我希望这些glyphs能够从featureproperties结构中获得它们的形状。

                //create feature properties
                var p = {
                    "id": i,
                    "popup": "Dot_" + i,
                    "year": parseInt(data[i].year),
                    "glyphName": "square",
                    "size": 500 // Fixed size circle radius=~13
                };
    

    L.circleMarker 为了简单起见,假设它们的形状可以是正方形或菱形。目前,我正在扩展 L.Class 我在构造函数中传递glyphName:(如果你觉得它不好看,请随意批评)

            var glyph = L.Class.extend({
            initialize: function(glyphName) {
                 glyphName === "square"? this.type = MarkerSquare:
                 glyphName === "diamond"? this.type = MarkerDiamond:
                 this.type = L.circleMarker; 
                },
            });
    

    当我需要绘制字形的时候,我有这样的东西:

    L.geoJson(myDots[i], {
        pointToLayer: function(feature, latlng) {
            var p = latlng;
            var myGlyph = new glyph('diamond')
            return new myGlyph.type(p, style(feature));
           },
           onEachFeature: onEachDot
       }).addTo(map);
    

    var myGlyph = new glyph('diamond')
    return new myGlyph.type(p, style(feature));
    

    像这样的

    return new myGlyph.type(p, style(feature));
    

    这将使我能够绘制不同的形状,这些形状将由用于填充特征属性的输入数据决定。与这些属性用于颜色或大小的方式类似,它们现在可以用于设置形状。

    谢谢!(完整代码如下)

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="utf-8">
    
        <title>Chart</title>
        <style>
            html,
            body {
                height: 100%;
                margin: 0;
            }
    
            #map {
                width: 600px;
                height: 600px;
            }
        </style>
    
    
        <script src='https://d3js.org/d3.v4.min.js' type='text/javascript'></script>
        <script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js'></script>
        <link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.3/dist/leaflet.css" />
        <script src="https://unpkg.com/leaflet@1.3.3/dist/leaflet.js"></script>
    </head>
    
    <body>
        <div id="map"></div>
        <script>
            L.Canvas.include({
                _updateMarkerDiamond: function(layer) {
                    if (!this._drawing || layer._empty()) {
                        return;
                    }
    
                    var p = layer._point,
                        ctx = this._ctx,
                        r = Math.max(Math.round(layer._radius), 6);
    
                    this._drawnLayers[layer._leaflet_id] = layer;
    
                    ctx.beginPath();
                    ctx.moveTo(p.x - r, p.y);
                    ctx.lineTo(p.x, p.y - r);
                    ctx.lineTo(p.x + r, p.y);
                    ctx.lineTo(p.x, p.y + r);
                    ctx.lineTo(p.x - r, p.y);
                    ctx.closePath();
                    this._fillStroke(ctx, layer);
                }
            });
            var MarkerDiamond = L.CircleMarker.extend({
                _updatePath: function() {
                    this._renderer._updateMarkerDiamond(this);
                }
            });
    
    
            L.Canvas.include({
                _updateMarkerSquare: function(layer) {
                    if (!this._drawing || layer._empty()) {
                        return;
                    }
    
                    var p = layer._point,
                        ctx = this._ctx,
                        r = Math.max(Math.round(layer._radius), 5);
    
                    this._drawnLayers[layer._leaflet_id] = layer;
    
                    ctx.beginPath();
                    ctx.moveTo(p.x - r, p.y - r);
                    ctx.lineTo(p.x + r, p.y - r);
                    ctx.lineTo(p.x + r, p.y + r);
                    ctx.lineTo(p.x - r, p.y + r);
                    ctx.lineTo(p.x - r, p.y - r);
                    ctx.closePath();
                    this._fillStroke(ctx, layer);
                }
            });
            var MarkerSquare = L.CircleMarker.extend({
                _updatePath: function() {
                    this._renderer._updateMarkerSquare(this);
                }
            });
    
            var glyph = L.Class.extend({
                initialize: function(glyphName) {
                    glyphName === "square"? this.type = MarkerSquare:
                    glyphName === "diamond"? this.type = MarkerDiamond:
                    this.type = L.circleMarker;
                },
            });
    
    
            var data = [];
            var NumOfPoints = 100;
            for (let i = 0; i < NumOfPoints; i++) {
                data.push({
                    num: i,
                    x: Math.random() * 60,
                    y: Math.random() * 60,
                    year: Math.floor(100 * Math.random())
                })
            }
    
            renderChart(data);
    
            function make_dots(data) {
                var arr = [];
                var nest = d3.nest()
                    .key(function(d) {
                        return Math.floor(d.year / 10);
                    })
                    .entries(data);
    
                for (var k = 0; k < nest.length; ++k) {
                    arr[k] = helper(nest[k].values);
                }
                return arr;
            }
    
            function helper(data) {
                dots = {
                    type: "FeatureCollection",
                    features: []
                };
                for (var i = 0; i < data.length; ++i) {
                    x = data[i].x;
                    y = data[i].y;
                    var g = {
                        "type": "Point",
                        "coordinates": [x, y]
                    };
    
                    //create feature properties
                    var p = {
                        "id": i,
                        "popup": "Dot_" + i,
                        "year": parseInt(data[i].year),
                        //"glyphName": "square",
                        "size": 500 // Fixed size circle radius=~13
                    };
    
                    //create features with proper geojson structure
                    dots.features.push({
                        "geometry": g,
                        "type": "Feature",
                        "properties": p
                    });
                }
                return dots;
            }
    
    
            //create color ramp
            function getColor(y) {
                return y > 90 ? '#6068F0' :
                    y > 80 ? '#6B64DC' :
                    y > 70 ? '#7660C9' :
                    y > 60 ? '#815CB6' :
                    y > 50 ? '#8C58A3' :
                    y > 40 ? '#985490' :
                    y > 30 ? '#A3507C' :
                    y > 20 ? '#AE4C69' :
                    y > 10 ? '#B94856' :
                    y > 0 ? '#C44443' :
                    '#D04030';
            }
    
            //calculate radius so that resulting circles will be proportional by area
            function getRadius(y) {
                r = Math.sqrt(y / Math.PI)
                return r;
            }
    
            var myRenderer;
    
            //create style, with fillColor picked from color ramp
            function style(feature) {
                return {
                    radius: getRadius(feature.properties.size),
                    fillColor: getColor(feature.properties.year),
                    color: "#000",
                    weight: 0,
                    opacity: 1,
                    fillOpacity: 0.9,
                    renderer: myRenderer
                };
            }
    
            //create highlight style, with darker color and larger radius
            function highlightStyle(feature) {
                return {
                    radius: getRadius(feature.properties.size) + 1.5,
                    fillColor: "#FFCE00",
                    color: "#FFCE00",
                    weight: 1,
                    opacity: 1,
                    fillOpacity: 0.9,
                };
            }
    
            //attach styles and popups to the marker layer
            function highlightDot(e) {
                var layer = e.target;
                dotStyleHighlight = highlightStyle(layer.feature);
                layer.setStyle(dotStyleHighlight);
                if (!L.Browser.ie && !L.Browser.opera) {
                    layer.bringToFront();
                }
            }
    
            function resetDotHighlight(e) {
                var layer = e.target;
                dotStyleDefault = style(layer.feature);
                layer.setStyle(dotStyleDefault);
            }
    
            function onEachDot(feature, layer) {
                layer.on({
                    mouseover: highlightDot,
                    mouseout: resetDotHighlight
                });
                var popup = '<table style="width:110px"><tbody><tr><td><div><b>Marker:</b></div></td><td><div>' + feature.properties.popup +
                    '</div></td></tr><tr class><td><div><b>Group:</b></div></td><td><div>' + feature.properties.glyphName +
                    '</div></td></tr><tr><td><div><b>X:</b></div></td><td><div>' + feature.geometry.coordinates[0] +
                    '</div></td></tr><tr><td><div><b>Y:</b></div></td><td><div>' + feature.geometry.coordinates[1] +
                    '</div></td></tr></tbody></table>'
    
                layer.bindPopup(popup);
            }
    
    
    
            function renderChart(data) {
    
    
                var myDots = make_dots(data);
    
                var minZoom = 0,
                    maxZoom = 15;
    
                var map = L.map('map', {
                    minZoom: minZoom,
                    maxZoom: maxZoom
                }).setView([30, 30], 3);
    
                L.tileLayer("http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", {
                    continuousWorld: false,
                    minZoom: 0,
                    noWrap: true
                }).addTo(map);
    
                myRenderer = L.canvas({
                    padding: 0.5
                });
    
                // Define an array to keep layerGroups
                var dotlayer = [];
    
                //create marker layer and display it on the map
                for (var i = 0; i < myDots.length; i += 1) {
                    dotlayer[i] = L.geoJson(myDots[i], {
                        pointToLayer: function(feature, latlng) {
                            var p = latlng;
                            
                            var myGlyph = new glyph('diamond')
                            return new myGlyph.type(p, style(feature));
                        },
                        onEachFeature: onEachDot
                    }).addTo(map);
                }
                var cl = L.control.layers(null, {}).addTo(map);
                for (j = 0; j < dotlayer.length; j += 1) {
                    var name = "Group " + j + "0-" + j + "9";
                    cl.addOverlay(dotlayer[j], name);
                }
            }
        </script>
    </body>
    
    </html>
    1 回复  |  直到 6 年前
        1
  •  2
  •   rioV8    6 年前

    你需要做出决定 shape 标记的属性,并合并 MarkerDiamond MarkerSquare if 里面 这个 _updateMarkerXX 基于属性的方法 形状 .

    layer.options.shape

    或者在厨房里做 Marker 常规

    var Marker = L.CircleMarker.extend({
         _updatePath: function() {
             if (this.options.shape === "square")
                 this._renderer._updateMarkerSquare(this);
             if (this.options.shape === "diamond")
                 this._renderer._updateMarkerDiamond(this);
         }
     });
    
        function style(feature) {
            return {
                radius: getRadius(feature.properties.size),
                shape: feature.properties.shape,
                fillColor: getColor(feature.properties.year),
                color: "#000",
                weight: 0,
                opacity: 1,
                fillOpacity: 0.9,
                renderer: myRenderer
            };
        }
    

    编辑