vue中,使用openlayers实现四屏幕卷帘对比+点击给每一块区域加载图层

<template>
  <div>
    <div id="map"></div>
    <!-- 水平分割线 -->
    <div class="ol-control ol-unselectable my-swipe-horizontal" ref="mySwipeHorizontal">
      <div class="my-swipe-line swipe-horizontal" :style="{ left: swipeHorizontalVal + '%' }"></div>
    </div>

    <!-- 垂直分割线 -->
    <div class="ol-control ol-unselectable my-swipe-vertical" ref="mySwipeVertical">
      <div class="my-swipe-line swipe-vertical" :style="{ top: swipeVerticalVal + '%' }"></div>
    </div>

    <!-- 交叉点控制点 -->
    <div class="ol-control ol-unselectable my-swipe-cross" ref="mySwipeCross" @mousedown="mouseDownCross">
      <div class="my-swipe-cross-point" :style="{
        left: swipeHorizontalVal + '%',
        top: swipeVerticalVal + '%'
      }">
        <span class="my-swipe-cross-btn">拖动</span>
      </div>
    </div>


    <div class="layers">
      <div class="layerItem">第一象限添加图层</div>
      <div class="layerItem">第二象限添加图层</div>
      <div class="layerItem">第三象限添加图层</div>
      <div class="layerItem" @click="addLayers">第四象限添加图层</div>
    </div>
  </div>
</template>

<script>
import "ol/ol.css"
import Map from "ol/Map"
import XYZ from "ol/source/XYZ"
import TileLayer from "ol/layer/Tile"
import View from "ol/View"
import GeoJSON from "ol/format/GeoJSON.js"
import VectorLayer from "ol/layer/Vector.js"
import VectorSource from "ol/source/Vector.js"
import { Fill, Style } from "ol/style.js"
import Control from "ol/control/Control"

export default {
  data() {
    return {
      swipeLayer: null,
      isMoving: false,
      swipeHorizontalVal: 50,
      swipeVerticalVal: 50,
      map: null,
      startX: 0,
      startY: 0,
      startHVal: 0,
      startVVal: 0,
      ctx: null
    }
  },
  methods: {
    setSwipeLayer(layer) {
      this.unsetSwipeLayer()
      if (layer) {
        layer.on("prerender", this.prerender)
        layer.on("postrender", this.postrender)
        this.swipeLayer = layer
      }
    },
    unsetSwipeLayer() {
      if (this.swipeLayer) {
        this.swipeLayer.un("prerender", this.prerender)
        this.swipeLayer.un("postrender", this.postrender)
        this.swipeLayer = null
      }
    },
    prerender(e) {
      this.ctx = e.context
      this.ctx.save()

      const width = this.ctx.canvas.width
      const height = this.ctx.canvas.height
      const hVal = (width * this.swipeHorizontalVal) / 100
      const vVal = (height * this.swipeVerticalVal) / 100

      this.ctx.beginPath()
      this.ctx.rect(0, 0, hVal, vVal)
      this.ctx.clip()
    },
    postrender(e) {
      const ctx = e.context
      ctx.restore()
    },
    mouseDownCross(e) {
      this.isMoving = true
      this.startX = e.clientX
      this.startY = e.clientY
      this.startHVal = this.swipeHorizontalVal
      this.startVVal = this.swipeVerticalVal

      document.addEventListener('mousemove', this.mouseMoveCross)
      document.addEventListener('mouseup', this.mouseUpCross)

      e.preventDefault()
      e.stopPropagation()
    },
    mouseMoveCross(e) {
      if (!this.isMoving) return

      const mapElement = this.$refs.mySwipeHorizontal
      const rect = mapElement.getBoundingClientRect()
      const width = rect.width
      const height = rect.height

      const deltaX = e.clientX - this.startX
      const deltaY = e.clientY - this.startY

      this.swipeHorizontalVal = Math.min(100, Math.max(0, this.startHVal + (deltaX / width) * 100))
      this.swipeVerticalVal = Math.min(100, Math.max(0, this.startVVal + (deltaY / height) * 100))

      this.map.render()
    },
    mouseUpCross() {
      this.isMoving = false
      document.removeEventListener('mousemove', this.mouseMoveCross)
      document.removeEventListener('mouseup', this.mouseUpCross)
    }
    ,
    addLayers() {
      const style1 = new Style({
        fill: new Fill({
          color: "#eeeeee",
        }),
      })

      const vectorLayer1 = new VectorLayer({
        source: new VectorSource({
          url: "https://openlayers.org/data/vector/ecoregions.json",
          format: new GeoJSON(),
        }),
        style: function (feature) {
          const color = feature.get("COLOR") || "#eeeeee"
          style1.getFill().setColor(color)
          return style1
        },
      })

      // 为新增图层添加裁剪逻辑
      vectorLayer1.on('prerender', (e) => {
        const ctx = e.context
        const width = ctx.canvas.width
        const height = ctx.canvas.height
        const hVal = (width * this.swipeHorizontalVal) / 100
        const vVal = (height * this.swipeVerticalVal) / 100

        ctx.save()
        ctx.beginPath()
        ctx.rect(hVal, vVal, width - hVal, height - vVal)
        ctx.clip()
      })

      vectorLayer1.on('postrender', (e) => {
        e.context.restore()
      })

      this.map.addLayer(vectorLayer1)
    }
  },
  mounted() {
    const layer = new TileLayer({
      source: new XYZ({
        attributions: 'Tiles © <a href="https://services.arcgisonline.com/ArcGIS/' +
          'rest/services/World_Topo_Map/MapServer">ArcGIS</a>',
        url: "https://server.arcgisonline.com/ArcGIS/rest/services/" +
          "World_Topo_Map/MapServer/tile/{z}/{y}/{x}",
      }),
    })

    const style = new Style({
      fill: new Fill({
        color: "#eeeeee",
      }),
    })

    const vectorLayer = new VectorLayer({
      source: new VectorSource({
        url: "https://openlayers.org/data/vector/ecoregions.json",
        format: new GeoJSON(),
      }),
      style: function (feature) {
        const color = feature.get("COLOR") || "#eeeeee"
        style.getFill().setColor(color)
        return style
      },
    })

    this.map = new Map({
      layers: [layer, vectorLayer],
      target: "map",
      view: new View({
        center: [0, 0],
        zoom: 2,
      }),
    })

    this.setSwipeLayer(vectorLayer)

    // 添加控件
    this.map.addControl(new Control({
      element: this.$refs.mySwipeHorizontal
    }))

    this.map.addControl(new Control({
      element: this.$refs.mySwipeVertical
    }))

    this.map.addControl(new Control({
      element: this.$refs.mySwipeCross
    }))
  },
  beforeDestroy() {
    this.unsetSwipeLayer()
    document.removeEventListener('mousemove', this.mouseMoveCross)
    document.removeEventListener('mouseup', this.mouseUpCross)
    if (this.map) {
      this.map.setTarget(undefined)
    }
  }
}
</script>

<style>
#map {
  width: 1980px;
  height: 800px;
  position: relative;
}

.my-swipe-horizontal,
.my-swipe-vertical,
.my-swipe-cross {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  z-index: 1000;
  background: none !important;
  padding: 0;
  pointer-events: none;
}

.my-swipe-cross {
  pointer-events: auto;
}

.swipe-horizontal {
  position: absolute;
  width: 2px;
  height: 100%;
  background: white;
  pointer-events: none;
}

.swipe-vertical {
  position: absolute;
  width: 100%;
  height: 2px;
  background: white;
  pointer-events: none;
}

.my-swipe-cross-point {
  position: absolute;
  width: 30px;
  height: 30px;
  margin-left: -15px;
  margin-top: -15px;
  pointer-events: auto;
  cursor: move;
}

.my-swipe-cross-btn {
  display: block;
  width: 100%;
  height: 100%;
  background: white;
  border: 1px solid #ccc;
  border-radius: 15px;
  text-align: center;
  line-height: 30px;
  font-size: 12px;
  color: #333;
  user-select: none;
}

.layers {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 9999999;
  height: 200px;
}
.layerItem{
  width: 100%;
  padding: 4px;
  background: #333;
  margin: 2px 0;
  color: #fff;
  cursor: pointer;
}
</style>

安装 :npm install ol

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值