OpenLayers图形与列表互动

项目上遇到这样一种需求:查询数据库后得到结果(带地理位置的)列表,每个结果在地图上都是一个四边形,四边形之间有交叉,有重叠,需要实现地图上的四边形和结果列表的互动。抛开其他逻辑功能,互动需求可以表示为如下两点意思:

1、点击地图上的四边形,被点击的(或者说被选中的)四边形会由蓝色变成绿色,结果列表中对应项会被打钩选中;

2、反过来,点击结果列表中的复选框,被打钩选中的结果对应的地图上的四边形会随之由蓝色变成绿色,取消打钩选中,则绿色还原成蓝色。

(约定:查询结果四边形用蓝色表示,被选中的四边形用绿色表示)

如图所示:

实现思路:

1、每个四边形都是一个OpenLayers.Feature.Vector对象,包含一个fid属性,该属性唯一,且可以由用户设定。我们可以通过fid和结果列表中的checkbox的id的某种关系(直接将fid设置成id的值即可)实现两者的一一对应,绘制四边形的代码如下:

// lefttop, righttop, rightdown, letdown是四个二维向量,表示四边形四个顶点的经纬度坐标
// featureID用于设定OpenLayers.Feature.Vector的fid,可以用于保存checkbox的id值
function drawPolygon(lefttop, righttop, rightdown, letdown, featureID) { var lr = new OpenLayers.Geometry.LinearRing([ new OpenLayers.Geometry.Point(lefttop[0], lefttop[1]), new OpenLayers.Geometry.Point(righttop[0], righttop[1]), new OpenLayers.Geometry.Point(rightdown[0], rightdown[1]), new OpenLayers.Geometry.Point(letdown[0], letdown[1]), new OpenLayers.Geometry.Point(lefttop[0], lefttop[1])]); lr = lr.transform("EPSG:4326", "EPSG:900913"); var polygonFeature = new OpenLayers.Feature.Vector( new OpenLayers.Geometry.Polygon(lr), { 'location': 'Fanghorn Forest', 'description': 'Land of the Ents' } ); polygonFeature.renderIntent = "default"; polygonFeature.fid = featureID; vectorLayer.addFeatures([polygonFeature]); // vectorLayer是四边形几何对象的容器图层,在第2点中说明... }

 

2、将所有的四边形Vector对象都绘制在一个OpenLayers.Layer.Vector父容器图层对象(设为vectorLayer)中,给vectorLayer指定一组样式,用于统一设定其内四边形选中和未选中时的颜色,样式代码如下:

var polygonLayerStyle = new OpenLayers.StyleMap({
            'default': {
                fillColor: "#0000ff", //蓝色表示默认状态
                fillOpacity: 0.1,
                strokeColor: "#0000ff",
                strokeOpacity: 1,
                strokeWidth: 1
            },
            'select': {
                fillColor: "#00ff00", //绿色表示选中的状态
                fillOpacity: 0.1,
                strokeColor: "#00ff00",
                strokeOpacity: 1,
                strokeWidth: 1
            }
        });
 

3、使用OpenLayers.Control.SelectFeature组件,绑定vectorLayer图层,使vectorLayer层里边的各个四边形Vector可以被选中,同时给vectorLayer图层添加其内Feature被选中时要触发的动作事件,代码如下:

var selcetCtl = new OpenLayers.Control.SelectFeature(vectorLayer, { //将vectorLayer绑定到SelectFeature组件上
                clickout: false, toggle: false,
                multiple: true, hover: false,
                clickout: true,
                renderIntent: "select"
            });
vectorLayer.events.on({ // 注册动作事件
                'featureselected': function (feature) {
                    selcetCtl.unselect(feature.feature); // 为何要调用该函数呢,是为了vector在选中和解除选中时样式不可控(SelectFeature空间定义的默认样式跟我们要的不一样)
                    var a = document.getElementById(feature.feature.fid);
                    a.checked = true;
                    checkboxchange(a); // 手动触发checkbox状态改变事件,貌似用代码改变其checked属性后,并没有失去焦点的动作,没办法自动触发
                }
            });
map.addControl(selcetCtl); 
selcetCtl.activate(); // 添加空间后需要显式地激活

 4、修改四边形样式,以及改变checkbox的状态等功能的实现,主要是如下函数:

        function checkboxchange(e) {
            var theFeature = vectorLayer.getFeatureByFid(e.id);
            if (e.checked) {
                theFeature.renderIntent = "select";

            } else {
                theFeature.renderIntent = "default";
            }
            vectorLayer.drawFeature(theFeature); 
        }

这里略提一点细节问题,通过修改Feature对象的renderIntent,能够指定其套用Style对象里的哪套样式,但是修改之后,Feature的样式不会立马改变(静态页面嘛...),需要调用一下vectorLayer.drawFeature(theFeature)来重绘一下(缩放一下也能起到刷新重绘效果),drawFeature函数的含义可以参考一下api中的注释,这里截取一部分如下:

 * This function is not designed to be used when adding features to 
 * the layer (use addFeatures instead). It is meant to be used when
 * the style of a feature has changed, or in some other way needs to 
 * visually updated *after* it has already been added to a layer. You
 * must add the feature to the layer for most layer-related events to 
 * happen.

效果如下图所示:

 (补充:仅仅是个实现思路,具体细节还需要慢慢完善,比如如何才能让SelectFeature组件的操作不影响自定义样式,需不需要重构SelectFeature类,SelectFeature是不是已经留有相应的功能等)

posted @ 2014-07-01 10:56  ArthurYMN  阅读(1589)  评论(2编辑  收藏  举报