目录
- 1.前言
- 2.olext官方示例
- 3.重写Transform.js
- 4.自定义样式
- 5.自定义选中机制
- 6.拓展思考
- 6.1包围框的角度问题
- 6.2不选中要素如何平移
- 7总结
1.前言
首先OpenLayers
本身是支持旋转、平移、缩放的。olext
只是在 OpenLayers
的基础上又做了一层封装,使得看起来比较好看,用起来也比较好用。当然,olext
里的功能可不止旋转、平移缩放,还有很多,比如样式、动画、过滤器、控制器、各类要素交互、重做撤销、图例、搜索、路径规划、等高线以及移动端适配等等。官方示例地址为 GitHub ,ES6版本可以参考 olext4.0.14 ,ES5及以下版本可以参考 olext3.1.5
2.olext官方示例
olext 的使用很简单,只需要引入olext,初始化一下就 ok 了。
import ExtTransform from 'ol-ext/interaction/Transform'
import {always} from 'ol/events/condition'
const transform = new ExtTransform({hitTolerance: 2,//点选容差,即将鼠标所在位置扩大2px进行选择translate: false, // 平移-点击要素的中心触发translateFeature: true,//平移-点击要素任意位置触发stretch: false, // 拉伸scale: true, // 缩放rotate: true, // 旋转noFlip: true,//禁止翻转keepRectangle:true,//保持包围框为矩形状态keepAspectRation:always //保持要素宽高比(缩放时)})
this.map.addInteraction(transform)
3.重写Transform.js
现在我们知道了是 Transform
这个类在控制这图形的变换。那我们就来看下源码就知道是怎么回事了。
原来是重写了ol/interaction/Pointer.js
这个类。那我们怎么重写这个类呢?抄呗!不会写还不会抄么?代码原封不动,我们自己写个类,把它的代码复制过去。文件就叫olPaintingTransform.js
,然后引入我们自己的文件, new
的时候就 new
我们自己的类,然后加上事件的监听。
// import ExtTransform from 'ol-ext/interaction/Transform'
import olPaintTransfrom from './olPaintTransform'
const transform = new olPaintTransfrom({hitTolerance: 2,//点选容差,即将鼠标所在位置扩大2px进行选择translate: false, // 平移-点击要素的中心触发translateFeature: true,//平移-点击要素任意位置触发stretch: true, // 拉伸scale: true, // 缩放rotate: true, // 旋转noFlip: true,//禁止翻转keepRectangle:true,//保持包围框为矩形状态keepAspectRation:always //保持要素宽高比(缩放时)
})map.addInteraction(transform)//开始事件transform.on(['rotatestart','translatestart'], function(e){// Rotationlet startangle = e.feature.get('angle')||0;// Translationconsole.log(xxx);console.log(startangle);});//旋转transform.on('rotating', function (e){console.log(xxx);console.log("rotate: "+((e.angle*180/Math.PI -180)%360+180).toFixed(2));console.log(e);});//移动transform.on('translating', function (e){console.log(xxx);console.log(e.delta);console.log(e);});//拖拽事件transform.on('scaling', function (e){console.log(xxx);console.log(e.scale);console.log(e);});//事件结束transform.on(['rotateend', 'translateend', 'scaleend'], function (e) {console.log(xxx);});
4.自定义样式
现在我觉的这个样式不好看,缩放和拉伸我不想要方框了,我要改成实心圆,并且加上颜色来区分功能,修改 setDefaultStyle
方法中bigpt
和 samllpt
的样式即可。
setDefaultStyle(options) {options = options || {}// Stylevar stroke = options.pointStroke || new ol_style_Stroke({ color: [255, 0, 0, 1], width: 1 })var strokedash = options.stroke || new ol_style_Stroke({ color: [255, 0, 0, 1], width: 1, lineDash: [4, 4] })var fill0 = options.fill || new ol_style_Fill({ color: [255, 0, 0, 0.01] })var fillScale = options.pointFill || new ol_style_Fill({ color: [255, 255, 255, 0.8] })var fill = options.pointFill || new ol_style_Fill({ color: [255, 255, 255, 0.8] })var circle = new ol_style_RegularShape({fill: fill,stroke: stroke,radius: this.isTouch ? 12 : 6,displacement: this.isTouch ? [24, -24] : [12, -12],points: 15})// Old version with no displacementif (!circle.setDisplacement)circle.getAnchor()[0] = this.isTouch ? -10 : -5var bigpt = new ol_style_RegularShape({fill: new ol_style_Fill({ color: '#0029f3' }),stroke: new ol_style_Stroke({ color: '#0029f3' , width: 1 }),radius: this.isTouch ? 12 : 6,points: 18,angle: Math.PI / 4})var smallpt = new ol_style_RegularShape({fill: new ol_style_Fill({ color: '#00f31e' }),stroke: new ol_style_Stroke({ color: '#00f31e' , width: 1 }),radius: this.isTouch ? 12 : 6,points: 18,angle: Math.PI / 4})function createStyle(img, stroke, fill) {return [new ol_style_Style({ image: img, stroke: stroke, fill: fill })]}/** Style for handles */this.style = {'default': createStyle(bigpt, strokedash, fill0),'translate': createStyle(bigpt, stroke, fill),'rotate': createStyle(circle, stroke, fill),'rotate0': createStyle(bigpt, stroke, fill),'scale': createStyle(bigpt, stroke, fill),'scale1': createStyle(bigpt, stroke, fill),'scale2': createStyle(bigpt, stroke, fill),'scale3': createStyle(bigpt, stroke, fill),'scalev': createStyle(smallpt, stroke, fill),'scaleh1': createStyle(smallpt, stroke, fill),'scalev2': createStyle(smallpt, stroke, fill),'scaleh3': createStyle(smallpt, stroke, fill),}this.drawSketch_()}
这个旋转点位置也看起来怪怪的,移动正上方去吧,修改画草图方法drawSketch_
中的Rotate
的计算方式和setDefaultStyle
中的circle
的样式
// Rotate
if (!this.iscircle_ && this.get('rotate')) {f = new ol_Feature({ geometry: new ol_geom_Point([(g[0][0]+g[2][0])/2,g[2][1]]), handle: 'rotate' })features.push(f)
}
var circle = new ol_style_RegularShape({fill: fill,stroke: stroke,radius: this.isTouch ? 12 : 6,//displacement: this.isTouch ? [24, -24] : [12, -12],displacement: [0, 30],points: 15
})
5.自定义选中机制
现在我们已经改完样式了,接下要做的是我不想通过鼠标点选来设置。为什么?因为鼠标点选只能选择一个,我们要做的是,通过代码设置,想设置选中多少个就设置选中多少个。首先设置多个选中在olext
里是提供了方法的,叫做setSelection
。
那么我们要做的就是取消olext
默认的选中事件就行了。而默认选中事件的逻辑是在handleDownEvent
中处理,我们只需要注销掉最后一个else if
就可以了。
6.拓展思考
6.1包围框的角度问题
当我的要素旋转了以后,我希望olext
画出来的包围框角度也跟着变化一下该怎么做呢?
答:当前也是在画草图方法drawSketch_
中找到new Polygon
的地方,设置角度即可。
6.2不选中要素如何平移
olext
唯一不好的地方就是不选中就不能进行旋转、平移、缩放。但是一些情况下需要不选中也能平移要素。这种应该怎么实现?
答:自然也是用ol/interaction/Pointer
类来实现,因为这里能处理mouseDown
事件,具体可以参考OpenLayers
官网的不选中平移例子
7总结
本篇中我们深刻的剖析了olext
中的Transform
类,修改了默认的样式,默认的选中事件等等。还提出了拓展思考及对应的解决方案,希望能对后来者有所启发,回见~。