【openlayers】CSS3样式的Popups

 一直觉得ol自带的Popup的样式太难看,后来也换了一套自己的皮肤,感觉展示效果还是不怎么地。

看到leafet上的样式挺不错的:

就自己搞个了个,popup主体加个圆角和阴影:

  border-radius: 1.2em 1.2em 1.2em 1.2em;
  box-shadow: 0 3px 14px rgba(0, 0, 0, 0.35);

popup的那个小箭头:矩形旋转45度,使用transform: rotate(45deg)来实现。另外针对不同的浏览器还需要添加不同的hack,例如Opera的-o-transform、Firefox的-moz-transform。

具体效果如下:

 实现的过程如下:

  1. 我在OpenLayers.Popup.Framed基础上另写了一个类如下:
    View Code
    OpenLayers.Popup.CSSFramedCloud = OpenLayers.Class(OpenLayers.Popup.Framed, {
        autoSize: true,
        panMapIfOutOfView: true,
        fixedRelativePosition: false,
    
      positionBlocks: {
            "tl": {
                'offset': new OpenLayers.Pixel(44, -6),
                'padding': new OpenLayers.Bounds(5, 14, 5, 5),
                'blocks': [
                    { 
                        className: 'olwidgetPopupStemTL',
                        size: new OpenLayers.Size(20, 20),
                        anchor: new OpenLayers.Bounds(null, 4, 32, null),
                        position: new OpenLayers.Pixel(0, -28)
                    }
                ]
            },
            "tr": {
                'offset': new OpenLayers.Pixel(-44, -6),
                'padding': new OpenLayers.Bounds(5, 14, 5, 5),
                'blocks': [
                    { 
                        className: "olwidgetPopupStemTR",
                        size: new OpenLayers.Size(20, 20),
                        anchor: new OpenLayers.Bounds(32, 4, null, null),
                        position: new OpenLayers.Pixel(0, -28)
                    }
                ]
            },
            "bl": {
                'offset': new OpenLayers.Pixel(44, 6),
                'padding': new OpenLayers.Bounds(5, 5, 5, 14),
                'blocks': [
                    { 
                        className: "olwidgetPopupStemBL",
                        size: new OpenLayers.Size(20,20),
                        anchor: new OpenLayers.Bounds(null, null, 32, 4),
                        position: new OpenLayers.Pixel(0, 0)
                    }
                ]
            },
            "br": {
                'offset': new OpenLayers.Pixel(-44, 6),
                'padding': new OpenLayers.Bounds(5, 5, 5, 14),
                'blocks': [
                    { 
                        className: "olwidgetPopupStemBR",
                        size: new OpenLayers.Size(20, 20),
                        anchor: new OpenLayers.Bounds(32, null, null, 4),
                        position: new OpenLayers.Pixel(0, 0)
                    }
                ]
            }
        },
    
        initialize: function(id, lonlat, contentSize, contentHTML, anchor, closeBox,
                        closeBoxCallback, relativePosition, separator) {
            if (relativePosition && relativePosition != 'auto') {
                this.fixedRelativePosition = true;
                this.relativePosition = relativePosition;
            }
            if (separator === undefined) {
                this.separator = ' of ';
            } else {
                this.separator = separator;
            }
    
            this.olwidgetCloseBox = closeBox;
            this.olwidgetCloseBoxCallback = closeBoxCallback;
            this.page = 0;
            OpenLayers.Popup.Framed.prototype.initialize.apply(this, [id, lonlat,
                contentSize, contentHTML, anchor, false, null]);
        },
    
        /*
         * 构造popup内部容器。
         */
        setContentHTML: function(contentHTML) {
            if (contentHTML !== null && contentHTML !== undefined) {
                this.contentHTML = contentHTML;
            }
      
            if (this.contentDiv !== null)  {
                var popup = this; 
    
                // 清空旧数据
                this.contentDiv.innerHTML = "";
    
                // 创建内部容器
                var containerDiv = document.createElement("div");
                containerDiv.innerHTML = this.contentHTML;
                containerDiv.className = 'olwidgetPopupContent';
                this.contentDiv.appendChild(containerDiv);
    
                // 创建关闭按钮
                if (this.olwidgetCloseBox) {
                    var closeDiv = document.createElement("div");
                    closeDiv.className = "olwidgetPopupCloseBox";
                    closeDiv.innerHTML = "close";
                    closeDiv.onclick = function(event) {
                        popup.olwidgetCloseBoxCallback.apply(popup, arguments);
                    };
                    this.contentDiv.appendChild(closeDiv);
                }
                if (this.autoSize) {
                    this.registerImageListeners();
                    this.updateSize();
                }
            }
        },
    
        /*
         * 重写createBlocks:使用CSS样式而不是特定的img图片
         */
        createBlocks: function() {
            this.blocks = [];
    
            // since all positions contain the same number of blocks, we can
            // just pick the first position and use its blocks array to create
            // our blocks array
            var firstPosition = null;
            for(var key in this.positionBlocks) {
                firstPosition = key;
                break;
            }
    
            var position = this.positionBlocks[firstPosition];
            for (var i = 0; i < position.blocks.length; i++) {
    
                var block = {};
                this.blocks.push(block);
    
                var divId = this.id + '_FrameDecorationDiv_' + i;
                block.div = OpenLayers.Util.createDiv(divId,
                    null, null, null, "absolute", null, "hidden", null
                );
                this.groupDiv.appendChild(block.div);
            }
        },
        /*
         * 重写updateBlocks
         */
        updateBlocks: function() {
            if (!this.blocks) {
                this.createBlocks();
            }
            if (this.size && this.relativePosition) {
                var position = this.positionBlocks[this.relativePosition];
                for (var i = 0; i < position.blocks.length; i++) {
    
                    var positionBlock = position.blocks[i];
                    var block = this.blocks[i];
    
                    // adjust sizes
                    var l = positionBlock.anchor.left;
                    var b = positionBlock.anchor.bottom;
                    var r = positionBlock.anchor.right;
                    var t = positionBlock.anchor.top;
    
                    // note that we use the isNaN() test here because if the
                    // size object is initialized with a "auto" parameter, the
                    // size constructor calls parseFloat() on the string,
                    // which will turn it into NaN
                    //
                    var w = (isNaN(positionBlock.size.w)) ? this.size.w - (r + l)
                                                          : positionBlock.size.w;
    
                    var h = (isNaN(positionBlock.size.h)) ? this.size.h - (b + t)
                                                          : positionBlock.size.h;
    
                    block.div.style.width = (w < 0 ? 0 : w) + 'px';
                    block.div.style.height = (h < 0 ? 0 : h) + 'px';
    
                    block.div.style.left = (l !== null) ? l + 'px' : '';
                    block.div.style.bottom = (b !== null) ? b + 'px' : '';
                    block.div.style.right = (r !== null) ? r + 'px' : '';
                    block.div.style.top = (t !== null) ? t + 'px' : '';
    
                    block.div.className = positionBlock.className;
                }
    
                this.contentDiv.style.left = this.padding.left + "px";
                this.contentDiv.style.top = this.padding.top + "px";
            }
        },
        updateSize: function() {
            
                return OpenLayers.Popup.prototype.updateSize.apply(this, arguments);
        
        },
    
        CLASS_NAME: "OpenLayers.Popup.CSSFramedCloud"
    });

     

  2. 然后是css样式:
    .olPopupContent {
        overflow: visible !important;
        padding: 0 !important;
    }
    .olPopup {
        z-index: 1005 !important;
    }
    .olwidgetPopupContent {
        background: none repeat scroll 0 0 #FFFFFF;
        border-radius: 1.2em 1.2em 1.2em 1.2em;
        box-shadow: 0 3px 14px rgba(0, 0, 0, 0.35);
        overflow: auto;
        padding: 10px 8px 8px;
    }
    .olwidgetPopupCloseBox {
        background: url("img/popup_icons.png") no-repeat scroll -80px 0 #FFFFFF;
        cursor: pointer;
        height: 0;
        overflow: hidden;
        padding-top: 16px;
        position: absolute;
        right: 10px;
        top: 10px;
        width: 16px;
    }
    .olwidgetPopupCloseBox:hover {
        background-position: -64px 0;
    }
    .olwidgetPopupStemTL,.olwidgetPopupStemTR {
        -moz-transform: rotate(45deg);
        -webkit-transform: rotate(45deg);
        -ms-transform: rotate(45deg);
        -o-transform: rotate(45deg);
        transform: rotate(45deg);
        background: none repeat scroll 0 0 #FFFFFF;
        z-index: 1;
    }
    
    .olwidgetPopupStemBL,.olwidgetPopupStemBR {
        -moz-transform: rotate(45deg);
        -webkit-transform: rotate(45deg);
        -ms-transform: rotate(45deg);
        -o-transform: rotate(45deg);
        transform: rotate(45deg);
        background: none repeat scroll 0 0 #FFFFFF;
        z-index: 1;
    }

     

    使用方法和OL自带的一样:
     function onFeatureSelect(feature) {
                selectedFeature = feature;
                popup = new OpenLayers.Popup.CSSFramedCloud("chicken", 
                                         feature.geometry.getBounds().getCenterLonLat(),
                                         null,
                                         "<div style='font-size:.8em'>Feature: " + feature.id +"<br>Area: " + feature.geometry.getArea()+"</div>",
                                         null, true, onPopupClose);
                feature.popup = popup;
                map.addPopup(popup);
            }

     源码:https://github.com/shitao1988/OL_CSSPopups

 在线示例:http://www.fenglgis.com/github/OL_CSSPopups/select-feature-openpopup.html

posted @ 2012-09-27 08:49  fengl  阅读(4265)  评论(5编辑  收藏  举报