【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。
具体效果如下:
实现的过程如下:
- 我在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" });
- 然后是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; }
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); }
在线示例:http://www.fenglgis.com/github/OL_CSSPopups/select-feature-openpopup.html