浅谈Supermap iClient for JavaScript 弹窗类
地图作为信息的载体和呈现方式,是GIS的重要组成部分,它是一个浏览信息的窗口,在信息日益发达的今天 ,各种地图应用如雨后春笋一般出现在大众眼前,而不是像以往一样太过局限于专业的领域。而弹窗,是作为地图信息的补充说明和描述的重要呈现方式,也广泛应用于各种地图应用中。一个好的前端界面的设计要灵活地使用空间,也要生动地完成与用户的交互,而在地图应用中,弹窗使用得好,不但会让人感觉舒适也会方便和增加与用户的交互,提升用户体验。如何使用和如何更好地使用iClient for JavaScript的弹窗(Popup)类,便是本文要探讨的话题。

一、 基础
1. 分类
普通弹窗(SuperMap.Popup):同时也是弹窗类的基类,不仅可以直接new出来,还能被子类继承其公开的属性和方法,JS API手册列举的属性和方法均可被其子类继承。其默认出现位置是,弹窗左上角在给定坐标点。
其默认效果如下↓:
固定锚点位置弹窗(SuperMap.Popup.Anchored):固定锚点位置的的浮动弹窗,可以围绕指定位置四周自适应显示。即当弹窗定位点(lonlat)在当前地图可视范围边缘时,会自动调整弹窗哪个角停靠在定位点。
其默认效果如下↓:
带小尾巴的弹窗(SuperMap.Popup.FramedCloud):具有指向和边框的浮动弹窗。它虽然没有边缘自适应位置的效果,但具有边缘时移动地图使弹窗显示完整的效果和阴影效果。
其默认效果如下↓:
2. 使用
弹窗类的使用很简单,new一个加到地图里就好了,这里以FramedCloud为例,上代码:
var map = new SuperMap.Map("map"); //引号内map为页面div元素ID
//初始化FramedCloud类
var framedCloud = new SuperMap.Popup.FramedCloud(
"chicken", //弹窗的唯一标识ID,即加载在地图上的弹窗div的ID
new SuperMap.LonLat(11339634, 4588716), //当前地图上的坐标点,用于定位弹窗位置
new SuperMap.Size(120,60), //弹窗内容的大小,可以为null
'<div style="margin:25px 10px; padding:0;"> 弹窗内容,相当于div元素的innerHTML
</div>',
null, //锚点,即弹窗怎么定位到坐标点
true, //bool,是否显示关闭按钮
null, //Function,关闭弹窗触发该回调函数
false //是否显示阴影,默认为true
);
framedCloud.fixedRelativePosition=true; // 是否固定相对位置,默认为false。
var layer = new SuperMap.Layer.CloudLayer(); //初始化超图云图层
map.addLayers([layer]); //添加超图云图层
map.setCenter(new SuperMap.LonLat(11339634, 4588716), 4); //设置显示的中心点及比例尺级别
map.addPopup(framedCloud); //将弹窗加载到map控件上,即放在地图上
就这样?就这样。
JS API类参考里有更多的属性和方法,可以自己去调整、设置。上面的代码只是初始化时就给放个弹窗,显然不符合我们的需要,但是已经足够说明它的用法了。弹窗基础的用法就是这么用,弹窗内容的部分,你可以自由发挥了,可以使用第三方插件,JQuery UI(教程)、BootStrap等等,你可以自由定制弹窗的内容。
一般我们怎么用?最常见的就是点击地图上的图标,任何可以注册点击事件的地方来添加弹窗。下面举个例子:
点击点对象,显示弹窗:
这里使用SuperMap.Layer.Vector图层上的点对象(其他对象也一样),点对象怎么得到,怎么风格化处理就不多说了,我们来看看它需要什么参数:
首先,最重要的参数,定位点,它是SuperMap.LonLat类型的,所以我们得想办法得到所点击的点的坐标。SuperMap.Layer.Vector图层上要素的点击事件可以用SuperMap.Control.SelectFeature来注册,设置onSelect属性并且设置其repeat属性为true,或者使用callbacks属性(JS API类参考可以看到支持的事件)来实现点击事件:
var selectFeature = new SuperMap.Control.SelectFeature(VectorLayer,{onSelect:onFeatureSelect,repeat:true,selectStyle:style});
//onSelect:{Function},当要素被选中时调用该方法,要求用户定义具体方法,该方法接收当前选中要素作为参数。
//function onFeatureSelect(e){};
顺便说下,设置VectorLayer的要素选中状态样式的方法有很多,上面就是其中之一。
我们来看看点击(这里是重复触发的选中事件)事件触发后,传给回调函数的参数里有没有我们想要的坐标参数,用console.log(e)看看:
虽然没有直接的lonlat对象,但好在有geometry对象,它就是这个点对象的信息,可是类参考里,SuperMap.Geometry.Point点对象没有直接获取lonlat对象的方法和属性,一种方法是new一个SuperMap.LonLat对象,我这里使用另外一种Geometry对象通用的方法,先用geometry.getBounds()方法获取Geometry对象的Bounds,再使用SuperMap.Bounds对象的Bounds.getCenterLonLat()方法获取其中心坐标点lonlat对象:
var lonlat= e.geometry.getBounds().getCenterLonLat();
有了定位点,接下来要怎么做就不用我多说了吧?这里再补充一下锚点属性的使用,它是用来定位弹窗相对于定位点位置用的,一般使用SuperMap.Icon对象,它不会在弹窗任何位置添加一个图标,使用它是因为不需要再构造一个包含大小信息和偏移量信息的对象,使用它可以使你的弹窗停靠在点图标图片的上方而不至于让小尾巴与图标重叠,效果对比如下↓:
有了上面的例子,那么其他Geometry对象就都ok了,只要参数给对了就行。
另外,有的朋友不想使用客户端图层再弹窗,那怎么办呢?iServer 7C开始支持属性瓦片,同时客户端也有相关对接的类,即:SuperMap.Layer.UTFGrid。JS API有这两个图层使用的相关示例,这里稍稍提示下:
UTFGrid使用SuperMap.Control.UTFGrid控件注册事件,支持的事件类型有点击(click)、悬停(hover)和拖拽(move)。
再补充个,为处理海量数据而生的麻点图,使用SuperMap.Control.GOIs控件注册其事件。
3.其他
- 视具体弹窗类型不同,其构造函数的参数数量有所不同,FramedCloud的构造函数已包含了别的类型弹窗的所有参数,所以其余弹窗类型不再赘述。
- 了解一下它们的继承关系,子类继承父类的属性和方法。
二、 进阶
类参考里的方法和属性及其组合不能做到你想要做的效果?总之就是想做通过iClient for JavaScript做不到的弹窗效果?看这里就对了,之所以是进阶而不是高级,是因为我下面要说的其实很简单,也不需要去对JS API的源码进行修改、重写和扩展。好了我就不卖关子了,一句话就可以说清楚:
添加到地图上的弹窗是div。
好了,我说完了,下课。
就这样?就这样!早该想到的是不是?这句话说完其实就已经很好的总结了接下来的内容了,那么接下来就简单的介绍下,然后小伙伴们就可以愉快地玩耍、尽情地发挥想象力了。
1. 弹窗内边距、滚动条、边框、阴影、半透明等等效果和动画效果
看图↓:
想起什么了吗?弹窗这个div的ID就是我们new这个弹窗时第一个参数给的,而知道了整个弹窗的div及其嵌套关系后这第一个问题就算解决了是吧?虽然类参考里有部分比如边框、透明度样式设置的方法,但根据这个来设置显然更灵活。
另外,通过iClient JS主题包(theme文件夹)中的style.css文件,可以找到部分弹窗类样式的定义:
.smFramedCloudPopupContent {
padding: 5px;
overflow: auto;
}
不建议在原文件修改(实在要改记得备份),你需要的只是定义个CSS样式覆盖或追加到默认样式,为保证覆盖掉默认样式,可以在样式后面加 !important,比如:
.smFramedCloudPopupContent{
overflow:hidden !important;
padding:0 !important;
}
上面的效果就是弹窗内容(你写的那部分的外层div)不显示滚动条,内边距为0。
当然,你可以在style.css(在\theme\default下)文件中搜索Popup相关的样式来设置,但是通过浏览器查看元素更直观方便,之所以要去查看下默认样式的定义是为了避免自定义样式不生效,现在你知道了,加个!important 覆盖掉默认的就好了。
到此,你可以使用各种UI、动画库(推荐animate.css)了,可以尽情发挥了。
2. 实现弹窗随鼠标移动或随地图上点移动的思路
map上加上弹窗后,如何实现移动弹窗?每次位置更改(onlat属性)先移除弹窗再添加可不可以呢?当然是可以的,如果你不需要和用户交互也不考虑弹窗多的情况下的性能的话。这是一种方法,但是不用考虑。
首先,收集必要信息:
1. 我们已经知道弹窗的ID(new 弹窗时自己给的,也可以在浏览器里查看),要用要改变它的位置,只需要设置它样式的left和top值,怎么获取呢?
2.看看popup对象除了是个div外,有没有在map对象里
先看看map控件下有什么属性和方法:
| 属性 | 描述 |
|---|---|
| popups | {Array(SuperMap.Popup)} 地图上的弹窗列表。 |
| 方法 | 描述 |
|---|---|
| getViewPortPxFromLayerPx | 根据图层像素点坐标获取视图窗口像素点坐标 |
| getViewPortPxFromLonLat | 根据指定地理位置,返回其相对于当前地图窗口左上角的像素位置 |
| getPixelFromLonLat | 获取地图上的像素坐标。依照当前baselayer,将指定的地理点位置坐标, 转换成其相对于地图窗口左上角点的像素坐标 |
| getLonLatFromPixel | 根据相对于地图窗口左上角的像素位置,返回其在地图上的地理位置。依据当前baselayer转换成 lon/lat (经度/纬度)形。 |
| getLayerPxFromLonLat | 根据传入的大地坐标获取图层坐标对象 |
| getLayerPxFromViewPortPx | 根据视图窗口像素点坐标获取图层像素点坐标 |
| removeAllPopup | 移除所有弹出窗口。 |
| removePopup | 移除指定的弹出窗口。 |
对于第一种思路要求,使用getLonLatFromPixel和getPixelFromLonLat方法就可以实现了,而且不需要计算地图容器在页面中的位置,不过这样改了后,弹窗对象的lonlat等属性不会变化,需要的话可以手动改下它的属性;另外,自带的阴影(多个div拼合而成)也不会跟着移动,也需要手动改,跟上面的方法一样,或者不使用自带的阴影,而使用用弹窗DIV的CSS阴影样式,这里用setInterval简单模拟了下:
function mouseClickHandler(e){
closeInfoWin();
var framedCloud= new SuperMap.Popup.FramedCloud(
"chicken",
e.object.lonlat,
null,
'这里相当于innerHTML部分',
new SuperMap.Icon('', new SuperMap.Size(21,25), new SuperMap.Pixel(-10, -20)),
true,
null,
true
);
framedCloud.panMapIfOutOfView=true;
infowin = framedCloud;
map.addPopup(framedCloud);
//在一定范围内随机更改弹窗位置
setInterval(function(){
var px=map.getPixelFromLonLat(new SuperMap.LonLat(e.object.lonlat.lon+Math.random()*100000,e.object.lonlat.lat+Math.random()*100000));
document.getElementById("chicken" ).style.left=px.x+"px";
document.getElementById("chicken" ).style.top=document.getElementById("chicken" ).style.height+px.y;
},100);
}
对于第二种思路,当然就是获取到popup对象,改它的lonlat属性,但是你会发现改了之后,弹窗并没有移动,因为你只是改了对象的属性,div并不受影响,除非刷新地图或重绘div。但是,还是有办法的,用SuperMap.Popup.updateSize()方法就可以了:
setInterval(function(){
var lonlat=new SuperMap.LonLat(e.object.lonlat.lon+Math.random()*100000,e.object.lonlat.lat+Math.random()*100000);
map.popups[0].lonlat=lonlat;
map.popups[0].updateSize();
},1000);
}
二者可以结合使用,第一种思路更为灵活。浏览器里多按f12,这很重要。
关于弹窗类,进阶的内容就到这里了,高级的内容大家就自己探索吧。希望本文能给你一些启发、开阔一些思路。
浅谈Supermap iClient for JavaScript 弹窗类的更多相关文章
- SuperMap iClient for JavaScript 新手入门
地理信息系统(英语:Geographic Information System,缩写:GIS)是一门综合性学科,结合地理学与地图学,已经广泛的应用在不同的领域,是用于输入.存储.查询.分析和显示地理数 ...
- SuperMap iClient for JavaScript初入
SuperMap iClient for JavaScript初入 介绍SuperMap for Js的简单使用. 推荐先看下这篇文档:SuperMap iClient for JavaScript ...
- SuperMap iClient for JavaScript 之关联查询
人们常说,计划赶不上变化.同样的,在项目中,使用的数据也是在不断变化的,尤其是属性信息的改变.就比如说,地图上的地物,它的空间信息在比较长的时间内,都不会发生变化,他的属性信息在初期不完整或者与后来的 ...
- SuperMap iClient for JavaScript image出图
SuperMap iClient for JavaScript 客户端基于openlayers 开发. 目前最高版本为811,9D产品后推荐客户使用leaflet.openlayers客户端开发. 问 ...
- 浅谈Kotlin(三):类
浅谈Kotlin(一):简介及Android Studio中配置 浅谈Kotlin(二):基本类型.基本语法.代码风格 浅谈Kotlin(三):类 浅谈Kotlin(四):控制流 前言: 已经学习了前 ...
- 前端网老姚浅谈:怎么学JavaScript?
作者:小不了链接:https://zhuanlan.zhihu.com/p/23265155来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处. 鉴于时不时,有同学私信问我( ...
- 浅谈JS之text/javascript和application/javascript
问题描述: JS在IE8以下浏览器运行异常 代码: <script>标签是这样子写的: <script type="application/javascript" ...
- 浅谈href=#与href=javascript:void(0)的区别
#"包含了一个位置信息 默认的锚点是#top 也就是网页的上端 而javascript:void(0) 仅仅表示一个死链接 这就是为什么有的时候页面很长浏览链接明明是#可是跳动到了页首 而 ...
- 浅谈个人对客户端JavaScript同步、异步、执行顺序等概念的理解
一.同步和异步的概念. 同步:即按代码的顺序执行任务. 在下列代码中,按照同步概念,则是先打印1后打印2. console.log(1); console.log(2); 异步:即执行一个任务的同时执 ...
随机推荐
- 使用jQuery 取文本
<html> <head> <meta charset="UTF-8"> <title>b</title> <sc ...
- 设计模式9---装饰模式(Decorator Pattern)
装饰模式又名包装(Wrapper)模式.装饰模式以对客户端透明的方式扩展对象的功能,是继承关系的一个替代方案. 装饰模式的结构 装饰模式以对客户透明的方式动态地给一个对象附加上一些责任.换言之,客户端 ...
- Mysql主主复制+keepalived
1>环境 Master1 10.0.0.201 Master2 10.0.0.202 2>Master1操作授权 mysql>grant replication slave on * ...
- VS2010 solution中完美的相对路径引用方法
假设您有一个工程叫solar,路径结构是这样的: 公用头路径: d:\solar\public\include公用库路径:d:\solar\public\libmars项目 : d:\solar\ma ...
- 如何轻松学习C语言编程!
C语言是面向过程的,而C++是面向对象的 C和C++的区别: C是一个结构化语言,它的重点在于算法和数据结构.C程序的设计首要考虑的是如何通过一个过程,对输入(或环境条件)进行运算处理得到输出(或实现 ...
- C# Log4.Net日志组件的应用系列(一)
引言 Log4Net应该可以说是.NET中最流行的开源日志组件了.在各种项目框架中可以说是必不可少的组成部分.个人认为Log4Net有下面几个优点: 1. 使用灵活,它可以将日志分不同的等级,以不同的 ...
- SPOJ distinct subtrings
题目链接:戳我 后缀自动机模板? 求不同的子串数量. 直接\(\sum t[i].len-t[t[i].ff].len\)即可 代码如下: #include<iostream> #incl ...
- read_csv 函数
转载自 https://www.cnblogs.com/datablog/p/6127000.html pandas.read_csv参数整理 读取CSV(逗号分割)文件到DataFrame也支持文件 ...
- php 获取 post 请求体参数
private function getPostData() { $postdata = file_get_contents("php://input"); $data = url ...
- [Swift实际操作]八、实用进阶-(4)通过protocol在两个对象中进行消息传递
本文将演示如何借助协议,实现视图控制器对象和其内部的自定义视图对象之间的数据传递. 首先创建一个自定义视图对象.在项目名称文件夹点击鼠标右键New File ->Cocoa Touch Clas ...