小程序界面怎样的_OpenLayer学习之自界说测量控件

OpenLayer学习之自定义测量控件       这篇文章主要为大家详细 介绍了OpenLayer学习之自定义测量控件,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

OpenLayer 学习之自定义测量控件(目前ol3的版本不会抛异常)

一、自定义控件是在继承基类空间基础上实现的,控件不是我写的(毕竟技术有限)最近也在一直在研究源码进行模仿想写出自己的功能更为强大的控件。

二、控件源码

1、css样式设置

.tooltip {
 position: relative;
 background: rgba(0, 0, 0, 0.5);
 border-radius: 4px;
 color: white;
 padding: 4px 24px 4px 8px;
 opacity: 0.7;
 white-space: nowrap;
.tooltip-measure {
 opacity: 1;
 font-weight: bold;
.tooltip-static {
 background-color: #ffcc33;
 color: black;
 border: 1px solid white;
.tooltip-measure:before,
.tooltip-static:before {
 border-top: 6px solid rgba(0, 0, 0, 0.5);
 border-right: 6px solid transparent;
 border-left: 6px solid transparent;
 content: "";
 position: absolute;
 bottom: -6px;
 margin-left: -7px;
 left: 50%;
.tooltip-static:before {
 border-top-color: #ffcc33;
.ol-popup-closer {
 text-decoration: none;
 position: absolute;
 top: 4px;
 right: 8px;
 color: red;
.ol-popup-closer:after {
 content: " ";
/*MeasureTool*/
.MeasureTool{
 position: absolute;
 top: 2.0em;
 right: 5em;
 text-align: left;
 padding: 0;
.MeasureTool .ulbody{
 display: none;
.MeasureTool.shown .ulbody{
 display: block;
.ulbody li input:focus, .ulbody li input:hover {
 background-color: white;
 color: blue;
 font-weight: bold;
.MeasureTool ul {
 padding: 0;
 list-style: none;
 margin: 0;
.MeasureTool ul li{
 text-align: center;
.MeasureTool ul li input{
 background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAABiUlEQVRIS8WUQU7CQBSG/ze6lxsoJxCPYMpePIG4almJW2giJq1xJ6ykbuAG6p6GIwgnkBsYtwb7zGsZLKUk0tI4m6btzP/N/+bNTyh4UMH6+D+ymhrQGYxL86/gIw50TCM7gBkz1zLKWrD16NeVwgCMqXaRGcDgTwIdzANVvm+czgTS9kZDAl0AkLO5WZxTNgfM/EpEZwxcu6bRjQD+jIDDgNSJ4uAtFyAIcCnlEJBrVWutp3FFRMWZa1ZLuhkyl0hKs6+Cd73Ltuc3CXjQwNwA2ZkuibQrM+pSMnF21zCGOwHYfb8LwhUY凡科抠图auxw99N4Do1j7/3jtMHcuoyHsegESFxET4lN7Hnpoo/j6Kvkc3exEpy3nJSCk+7OKhtinYton0pB6thlooFZYkx1hZnwbIob2+NA2wlv1bEsNs0kMAK5Z012wpupye1Cu+i7Lu9K/rCnfwA90A1i8VnCB2AAAAAElFTkSuQmCC') /*logo.png*/;
 background-position: center center;
 background-repeat: no-repeat;
.MeasureTool input[type="button"]{
 background-color: rgba(255, 255, 255, 0.4);
 width: 60px;
 height: 26px;
 border: 0;
.MeasureTool .ulbody li{
 border-top: 1px solid rgba(221, 221, 221, 0.4);
}

2、JS源码

 * OpenLayers 3 MeasureTool Control.
 * See [the examples](./examples) for usage.
 * @constructor
 * @extends {ol.control.Control}
 * @param {Object} opt_options Control options, extends olx.control.ControlOptions adding:
 * **`tipLabel`** `String` - the button tooltip.
//构造函数
ol.control.MeasureTool = function(opt_options) {
 var options = opt_options || {};
 this.sphereradius = options.sphereradius 
 options.sphereradius : 6378137;
 this.mapListeners = [];
 // hiddenclass
 this.hiddenClassName = 'ol-control MeasureTool';
 if (ol.control.MeasureTool.isTouchDevice_()) {
 this.hiddenClassName += ' touch';
 // shownClass
 this.shownClassName = this.hiddenClassName + ' shown';
 var element = document.createElement('div');
 element.className = this.hiddenClassName;
 this.panel = document.createElement('ul');
 element.appendChild(this.panel);
 var ulheader = document.createElement('li');
 this.panel.appendChild(ulheader);
 var inputMeasure = document.createElement('input');
 inputMeasure.type = "button";
 ulheader.appendChild(inputMeasure);
 var ulbody = document.createElement('li');
 this.panel.appendChild(ulbody);
 var html = '';
 html += ' ul 
 html += ' li input type="button" value="Line" /li 
 html += ' li input type="button" value="Area" /li 
 html += ' li input type="checkbox" value="no" /li 
 html += ' /ul 
 ulbody.innerHTML = html;
 var this_ = this;
 inputMeasure.onmouseover = function(e) {
 this_.showPanel();
 inputMeasure.onclick = function(e) {
 e = e || window.event;
 this_.showPanel();
 e.preventDefault();
 var lis = ulbody.getElementsByTagName("li");
 this.sourceMesure = new ol.source.Vector();
 this.vectorMesure = new ol.layer.Vector({
 source: this.sourceMesure,
 style: new ol.style.Style({
 fill: new ol.style.Fill({
 color: 'rgba(255, 255, 255, 0.2)'
 stroke: new ol.style.Stroke({
 color: '#ffcc33',
 width: 2
 image: new ol.style.Circle({
 radius: 7,
 fill: new ol.style.Fill({
 color: '#ffcc33'
 //type length or area
 var typeSelect={};
 //Line start
 lis[0].onclick = function(e) {
 typeSelect.value = 'length';
 typeSelect.check = lis[2].getElementsByTagName("input")[0].checked;
 this_.mapmeasure(typeSelect);
 //Area start
 lis[1].onclick = function(e) {
 typeSelect.value = 'area';
 typeSelect.check = lis[2].getElementsByTagName("input")[0].checked;
 this_.mapmeasure(typeSelect);
 this_.panel.onmouseout = function(e) {
 e = e || window.event;
 if (!this_.panel.contains(e.toElement || e.relatedTarget)) {
 this_.hidePanel();
 ol.control.Control.call(this, {
 element: element,
ol.inherits(ol.control.MeasureTool, ol.control.Control);
ol.control.MeasureTool.prototype.mapmeasure = function(typeSelect) {
 var source = this.sourceMesure;
 var vector = this.vectorMesure;
 var wgs84Sphere = new ol.Sphere(this.sphereradius);
 var sketch;
 var helpTooltipElement;
 var measureTooltipElement;
 var measureTooltip;
 var map = this.getMap();
 map.addLayer(vector);
 map.getViewport().addEventListener('mouseout', function() {
 helpTooltipElement.classList.add('hidden');
 var draw; // global so we can remove it later
 var formatLength = function(line) {
 var length;
 if (typeSelect.check) {
 var coordinates = line.getCoordinates();
 length = 0;
 var sourceProj = map.getView().getProjection();
 for (var i = 0, ii = coordinates.length - 1; i ++i) {
 var c1 = ol.proj.transform(coordinates[i], sourceProj, 'E凡科抠图G:4326');
 var c2 = ol.proj.transform(coordinates[i + 1], sourceProj, 'E凡科抠图G:4326');
 length += wgs84Sphere.haversineDistance(c1, c2);
 } else {
 var sourceProj = map.getView().getProjection();
 var geom = /** @type {ol.geom.Polygon} */(line.clone().transform(
 sourceProj, 'E凡科抠图G:3857'));
 length = Math.round(geom.getLength() * 100) / 100;
 // length = Math.round(line.getLength() * 100) / 100;
 var output;
 if (length 100) {
 output = (Math.round(length / 1000 * 100) / 100) +
 ' ' + 'km';
 } else {
 output = (Math.round(length * 100) / 100) +
 ' ' + 'm';
 return output;
 var formatArea = function(polygon) {
 if (typeSelect.check) {
 var sourceProj = map.getView().getProjection();
 var geom = /** @type {ol.geom.Polygon} */(polygon.clone().transform(
 sourceProj, 'E凡科抠图G:4326'));
 var coordinates = geom.getLinearRing(0).getCoordinates();
 area = Math.abs(wgs84Sphere.geodesicArea(coordinates));
 } else {
 var sourceProj = map.getView().getProjection();
 var geom = /** @type {ol.geom.Polygon} */(polygon.clone().transform(
 sourceProj, 'E凡科抠图G:3857'));
 area = geom.getArea();
 // area = polygon.getArea();
 var output;
 if (area 10000) {
 output = (Math.round(area / 1000000 * 100) / 100) +
 ' ' + 'km sup 2 /sup 
 } else {
 output = (Math.round(area * 100) / 100) +
 ' ' + 'm sup 2 /sup 
 return output;
 var popupcloser = document.createElement('a');
 popupcloser.href = 'javascript:void(0);';
 popupcloser.classList.add('ol-popup-closer');
 function addInteraction() {
 var type = (typeSelect.value == 'area' 'Polygon' : 'LineString');
 draw = new ol.interaction.Draw({
 source: source,
 type: /** @type {ol.geom.GeometryType} */ (type),
 style: new ol.style.Style({
 fill: new ol.style.Fill({
 color: 'rgba(255, 255, 255, 0.2)'
 stroke: new ol.style.Stroke({
 color: 'rgba(0, 0, 0, 0.5)',
 lineDash: [10, 10],
 width: 2
 image: new ol.style.Circle({
 radius: 5,
 stroke: new ol.style.Stroke({
 color: 'rgba(0, 0, 0, 0.7)'
 fill: new ol.style.Fill({
 color: 'rgba(255, 255, 255, 0.2)'
 map.addInteraction(draw);
 createMeasureTooltip();
 createHelpTooltip();
 var listener;
 draw.on('drawstart',
 function(evt) {
 // set sketch
 sketch = evt.feature;
 /** @type {ol.Coordinate|undefined} */
 var tooltipCoord = evt.coordinate;
 listener = sketch.getGeometry().on('change', function(evt) {
 try {
 var geom = evt.target;
 var output;
 if (geom instanceof ol.geom.Polygon) {
 output = formatArea(geom);
 tooltipCoord = geom.getInteriorPoint().getCoordinates();
 } else if (geom instanceof ol.geom.LineString) {
 output = formatLength(geom);
 tooltipCoord = geom.getLastCoordinate();
 measureTooltipElement.innerHTML = output;
 measureTooltip.setPosition(tooltipCoord);
 } catch (e) {
 map.removeInteraction(draw);
 } finally {
 }, this);
 draw.on('drawend',
 function() {
 measureTooltipElement.appendChild(popupcloser);
 measureTooltipElement.className = 'tooltip tooltip-static';
 measureTooltip.setOffset([0, -7]);
 // unset sketch
 sketch = null;
 // unset tooltip so that a new one can be created
 measureTooltipElement = null;
 createMeasureTooltip();
 ol.Observable.unByKey(listener);
 //end
 map.removeInteraction(draw);
 // map.getInteractions().item(1).setActive(false);
 }, this);
 function createHelpTooltip() {
 if (helpTooltipElement) {
 helpTooltipElement.parentNode.removeChild(helpTooltipElement);
 helpTooltipElement = document.createElement('div');
 helpTooltipElement.className = 'tooltip hidden';
 function createMeasureTooltip() {
 if (measureTooltipElement) {
 measureTooltipElement.parentNode.removeChild(measureTooltipElement);
 measureTooltipElement = document.createElement('div');
 measureTooltipElement.className = 'tooltip tooltip-measure';
 measureTooltip = new ol.Overlay({
 element: measureTooltipElement,
 offset: [0, -15],
 positioning: 'bottom-center'
 map.addOverlay(measureTooltip);
 //clear
 popupcloser.onclick = function(e) {
 map.getOverlays().clear();
 vector.getSource().clear();
 // map.removeLayer(vector);
 addInteraction();
 * Show the MeasureTool.
ol.control.MeasureTool.prototype.showPanel = function() {
 if (this.element.className != this.shownClassName) {
 this.element.className = this.shownClassName;
 * Hide the MeasureTool.
ol.control.MeasureTool.prototype.hidePanel = function() {
 if (this.element.className != this.hiddenClassName) {
 this.element.className = this.hiddenClassName;
 * Set the map instance the control is associated with.
 * @param {ol.Map} map The map instance.
ol.control.MeasureTool.prototype.setMap = function(map) {
 // Clean up listeners associated with the previous map
 for (var i = 0, key; i this.mapListeners.length; i++) {
 this.getMap().unByKey(this.mapListeners[i]);
 this.mapListeners.length = 0;
 // Wire up listeners etc. and store reference to new map
 ol.control.Control.prototype.setMap.call(this, map);
 if (map) {
 var this_ = this;
 this.mapListeners.push(map.on('pointerdown', function() {
 this_.hidePanel();
 }));
 * Generate a UUID
 * @returns {String} UUID
 * Adapted from a/2117523/526860
ol.control.MeasureTool.uuid = function() {
 return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
 var r = Math.random()*16|0, v = c == 'x' r : (r 0x3|0x8);
 return v.toString(16);
* @private
* @desc Apply workaround to enable scrolling of overflowing content within an
* element. Adapted from chrismbarr/4107472
ol.control.MeasureTool.enableTouchScroll_ = function(elm) {
 if(ol.control.MeasureTool.isTouchDevice_()){
 var scrollStartPos = 0;
 elm.addEventListener("touchstart", function(event) {
 scrollStartPos = this.scrollTop + event.touches[0].pageY;
 }, false);
 elm.addEventListener("touchmove", function(event) {
 this.scrollTop = scrollStartPos - event.touches[0].pageY;
 }, false);
 * @private
 * @desc Determine if the current browser supports touch events. Adapted from
 * chrismbarr/4107472
ol.control.MeasureTool.isTouchDevice_ = function() {
 try {
 document.createEvent("TouchEvent");
 return true;
 } catch(e) {
 return false;
};

三、使用控件

1、js控件引入

 script src="ol3-measuretool-master/measuretool.js" /script 

2、声明控件

new ol.control.MeasureTool( {sphereradius : 6378137}),

其中的参数sphereradius 是用来支持geodesic测量设置球体半径的,可根据不同的模型设置不同的半径大小,默认大小为6378137,在引入时也可以不传入该参数。

NOTE:测量工具中的checkbox选中为使用geodesic测量,未选中为不使用geodesic测量,默认为未选中。

四、总结

通过这几天的研究我发现如果要实现自定义控件,里面有部分函数我们不需要改动,在构造函数那一部分我们需要创建自己定义的标签,其他后面最后的几个函数是不需要改动的,待下次继续完善