封装了一个类似全局动画控制器的类 用于播放所有动画
// 动画播放总控制器class animationSupper {funList = {}//所有的动画//修改动画setAnimationAct(animationAct) {this.funList.map(item => {item.animationAct()})this.setAnimationAct = animationActreturn this}//动画播放方法animationFun() {if (!Object.keys(this.funList).length) returnObject.values(this.funList).map(item => {item()})requestAnimationFrame(() => this.animationFun())}// 修改动画setFun(keyValue, fun) {let key = keyValue ? keyValue : Math.random()this.funList[key] = funthis.animationFun()return key}//添加动画addFun(fun) {let key = Math.random()this.funList[key] = funthis.animationFun()return key}//删除动画removeFun(key) {delete this.funList[key]}}
单个动画控制类
//下面的控制器要用到这个实例化后的类let ani = new animationSupper()// 动画控制器class animation {geometryanimationAct//掩饰时间timer = 1//动画携带数据columnData//播放状态控制status = false//每个动画专有的keyfunKey//入口需要传入图形 和动画方法constructor(geometry, animationAct) {this.geometry = geometrythis.animationAct = animationActreturn this}//修改某个动画携带的数据setCoumnData(columnData) {this.columnData = columnDatareturn this}//修改动画时间setTimer(timer) {this.timer = timerreturn this}//更改动画setAnimationAct(animationAct) {this.animationAct = animationActani.setFun(this.funKey, () => this.animationAct(this.columnData))return this}//开始动画start() {this.status = truesetTimeout(() => {ani.addFun(() => this.animationAct(this.columnData))}, this.timer)return this}//停止动画stop() {ani.removeFun(this.funKey)this.status = false}}
基础地图
let map = new ol.Map({target: "map",view: new ol.View({center: [112.549248, 37.857014],zoom: 5,projection: "EPSG:4326",}),layers: [],})
文字图层相关内容
//新建空的文字图层 名字为了方便控制let textLayer = new ol.layer.Vector({name: "text",zIndex: 3,//进行图层层次控制source: new ol.source.Vector(),})/*** 创建一个文字 返回文字要素 需要传入坐标点 及文字内容* @param {[number,number]} xy 坐标* @param {string} text 渲染的文字* @returns {Feature} 要素*/function addText(xyz, text) {//新建要素 点的位置为let feature = new ol.Feature({//几何为一个点 位置在xygeometry: new ol.geom.Point(xyz)});//修改样式为文字feature.setStyle(new ol.style.Style({text: new ol.style.Text({text: text,//文字内容为传入的textfont: '16px Calibri,sans-serif',//字体大小和字体样式fill: new ol.style.Fill({color: '#fff'}),//填充样式offsetY: -18//位置偏移 有y就有x})}));return feature}map.addLayer(textLayer)
点图层的相关内容
//新建空的点图层 名字为了方便控制 let pointLayer = new ol.layer.Vector({name: "point",zIndex: 2, //进行图层层次控制source: new ol.source.Vector()})/*** 创建一个圆 返回圆的要素 需要传入坐标点* @param {[number,number]} xy 坐标* @returns {Feature} 要素*/function addCircle(xy) {// 创建一个圆点要素let a = new ol.Feature({//几何对象为一个点 位置在xygeometry: new ol.geom.Point(xy),});//修改创建的要素样式为圆a.setStyle(new ol.style.Style({image: new ol.style.Circle({//半径为3radius: 3,//填充颜色fill: new ol.style.Fill({color: 'rgba(255,1,1,0.3)'}),})}))return a}map.addLayer(pointLayer)
行政区划 部分内容 geojson文件地址
//原本样式 这里提出来为了下面的移入样式做准备let geoStyle = new ol.style.Style({stroke: new ol.style.Stroke({color: '#eee',width: 1}),fill: new ol.style.Fill({color: '#d1d1d1'})})//选中的样式 为下面的移入样式做准备let selectStyle = new ol.style.Style({stroke: new ol.style.Stroke({color: '#eee',width: 1}),fill: new ol.style.Fill({color: '#92959e'}),})//新建 行政区划geojson name为了下面选中的时候不影响其他图层let geoLayer = new ol.layer.Vector({name: "geoLayer",index: 1,//进行图层层次控制source: new ol.source.Vector({url: './province.geojson',//放你的地址format: new ol.format.GeoJSON()}),style: geoStyle})map.addLayer(geoLayer)
添加点和文字的方法 不需要的可以在里面删除掉 某个方法的调用 不需要点的动画就直接将addCircle返回的内容添加到pointLayer
//添加点和文字的方法let initTextAndPoint = (event) => {//在所有的要素中遍历event.target.getFeatures().map(item => {//获取要素属性let data = item.getProperties()//获取到各省市的中心点if (data.center || data.centroid) {//在文字图层获取数据源 且在数据源中添加要素 添加的要素为addText的返回内容 传入的文字裁掉 省|特别行政区|自治区textLayer.getSource().addFeature(addText(data.center || data.centroid, data.name.replace(/省|特别行政区|自治区/g, '')))//获取Circle画的圆要素let geometry = addCircle(data.center || data.centroid)//将这个要素添加到点图层pointLayer.getSource().addFeatures([geometry])//使用刚才创建的动画类 创建一个动画let an = new animation(geometry, ({radius, status}) => {//如果我们添加进去的 radius 半径大于10 我们将数据还原为0if (radius > 10)an.setCoumnData({radius: 0})else {//否则将数据++ 这里加的值越大 速度越快an.setCoumnData({radius: radius + 0.005})}//捕获错误try {//获取到圆的style中的自定义styleImage 就是创建出来的样式源更改半径geometry.getStyle().getImage().setRadius(radius)//再更改源的style 实现动画geometry.setStyle(geometry.getStyle())} catch (e) {//如果出错则停止动画an.stop()}})//更改延迟执行时间an.setTimer(Math.random() * 1000)//修改自定义数据 且开始动画an.setCoumnData({radius: 0,}).start()}})// 停止监听数据源更改 否则此方法一直调用geoLayer.getSource().un('change', initTextAndPoint)}//监听数据源修改 调用添加点和文字方法geoLayer.getSource().on('change', initTextAndPoint)
鼠标移入 更改颜色 代码
//鼠标移入的选中项let selectFeature = nulllet selectId = null//监听鼠标移动map.on('pointermove', function (event) {//从map中获取到像素位置下的要素map.forEachFeatureAtPixel(event.pixel, (feature, layer) => {//如果图层为geoLayer并且不是上一次选中的要素if (selectId != feature.ol_uid && layer.get('name') == 'geoLayer' && feature) {//如果选中的要素有则还原style 且将其他设置为空if (selectFeature) {selectFeature.setStyle(geoStyle)selectFeature = nullselectId = null}// 将唯一id提出来 进行性能优化 避免下一次再更改样式selectId = feature.ol_uid//将给要素给到选中要素 为了下一次恢复使用selectFeature = feature//修改要素样式feature.setStyle(selectStyle)}});});