mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 09:14:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			507 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			507 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
import { currentData } from './CurrentData.js'
 | 
						||
 | 
						||
function RenderDynamicCurrent(viewer, Cesium) {
 | 
						||
  this.particles = []
 | 
						||
  this.particleCount = []
 | 
						||
  this._field = undefined
 | 
						||
  this._scale = 1// 1.0 //生成粒子的缩放因子
 | 
						||
  this._imageMask = undefined
 | 
						||
  this._particleNum = undefined
 | 
						||
  this._mapCenter = undefined
 | 
						||
  this._mapScale = undefined
 | 
						||
  this._windowWidth = undefined
 | 
						||
  this._windowheight = undefined
 | 
						||
  this._bounds = {
 | 
						||
    x: 0,
 | 
						||
    y: 0,
 | 
						||
    xMax: 0,
 | 
						||
    yMax: 0,
 | 
						||
    width: 0,
 | 
						||
    height: 0
 | 
						||
  }
 | 
						||
 | 
						||
  this._viewer = viewer
 | 
						||
  this._cancel = false
 | 
						||
  this._centerPnt = new Cesium.Cartographic()
 | 
						||
 | 
						||
  this.densityScale = 1// 1 //密度比例系数
 | 
						||
  this.velocityScale = 1 //1 //速度比例系数
 | 
						||
  this.builder = null
 | 
						||
}
 | 
						||
RenderDynamicCurrent.prototype.parseData = function (data) {
 | 
						||
  this.uvData = data
 | 
						||
}
 | 
						||
RenderDynamicCurrent.prototype.setData = (renderObject, data) => {
 | 
						||
  var bounds = data.params.bounds
 | 
						||
  var columns = data.columns
 | 
						||
  var maskImageData = data.pixels
 | 
						||
  var mask = maskImageData
 | 
						||
  const that = renderObject
 | 
						||
  that._imageMask = mask
 | 
						||
  that._field = currentData.createField(columns, bounds, false)
 | 
						||
 | 
						||
  //lxl发现粒子在原位置时没生成,移到此位置
 | 
						||
  that.particleCount = Math.round(
 | 
						||
    data.params.clientHeight *
 | 
						||
      data.params.clientWidth *
 | 
						||
      currentData.PARTICLE_MULTIPLIER *
 | 
						||
      that._scale
 | 
						||
  )
 | 
						||
 | 
						||
  if (that._field != null) {
 | 
						||
    for (var i = 0; i < that.particleCount; i++) {
 | 
						||
      that.particles.push(
 | 
						||
        that._field.randomize({
 | 
						||
          age: currentData.random(0, currentData.MAX_PARTICLE_AGE)
 | 
						||
        })
 | 
						||
      )
 | 
						||
    }
 | 
						||
  }
 | 
						||
 | 
						||
  var canvas, canvasOverLay
 | 
						||
  if (document.getElementById('fullScreen')) {
 | 
						||
    canvas = document.getElementById('fullScreen')
 | 
						||
    canvasOverLay = document.getElementById('image-canvas')
 | 
						||
  } else {
 | 
						||
    canvasOverLay = document.createElement('CANVAS')
 | 
						||
    // document.body.appendChild(canvasOverLay);
 | 
						||
    that._viewer.container.appendChild(canvasOverLay)
 | 
						||
    canvasOverLay.id = 'image-canvas'
 | 
						||
    canvasOverLay.width = bounds.width
 | 
						||
    canvasOverLay.height = bounds.height
 | 
						||
    canvasOverLay.style.position = 'absolute'
 | 
						||
    canvasOverLay.style.top = 0
 | 
						||
    canvasOverLay.style.left = 0
 | 
						||
    canvasOverLay.style.zIndex = 100
 | 
						||
    canvasOverLay.style.pointerEvents = 'none'
 | 
						||
 | 
						||
    canvas = document.createElement('CANVAS')
 | 
						||
    // document.body.appendChild(canvas);
 | 
						||
    that._viewer.container.appendChild(canvas)
 | 
						||
    canvas.id = 'fullScreen'
 | 
						||
    canvas.style.position = 'absolute'
 | 
						||
    canvas.style.top = 0
 | 
						||
    canvas.style.left = 0
 | 
						||
    canvas.style.right = 0
 | 
						||
    canvas.style.bottom = 0
 | 
						||
    canvas.style.width = '100%'
 | 
						||
    canvas.style.height = '100%'
 | 
						||
    canvas.style.zIndex = 100
 | 
						||
    canvas.style.pointerEvents = 'none'
 | 
						||
    canvas.width = bounds.width
 | 
						||
    canvas.height = bounds.height
 | 
						||
  }
 | 
						||
  var g = canvas.getContext('2d')
 | 
						||
  g.clearRect(0, 0, canvas.width, canvas.height)
 | 
						||
 | 
						||
  that._lineCanvas = canvas
 | 
						||
  that._lineCanvas.style.display = 'block'
 | 
						||
  that._g = g
 | 
						||
  that._g.lineWidth = that.lineWidth || 1
 | 
						||
  that._g.fillStyle = currentData.fadeFillStyle
 | 
						||
 | 
						||
  var gOverlay = canvasOverLay.getContext('2d')
 | 
						||
  gOverlay.clearRect(0, 0, canvasOverLay.width, canvasOverLay.height)
 | 
						||
 | 
						||
  that._imageCanvas = canvasOverLay
 | 
						||
  that._imageCanvas.style.display = 'none'
 | 
						||
  that._imageG = gOverlay
 | 
						||
}
 | 
						||
RenderDynamicCurrent.prototype.dealData = (renderObject, params) => {
 | 
						||
  if (!renderObject.builder) {
 | 
						||
    let uvData = params.uvData
 | 
						||
    let [header, uData, vData] = uvData
 | 
						||
    renderObject.builder = new currentData.buildGrid({
 | 
						||
      header,
 | 
						||
      data: function (i) {
 | 
						||
        return [uData[i], vData[i]]
 | 
						||
      },
 | 
						||
      interpolate: currentData.bilinearInterpolateVector
 | 
						||
    })
 | 
						||
  }
 | 
						||
  if (params.velocityScale_o)
 | 
						||
    currentData.velocityScale_o = params.velocityScale_o
 | 
						||
  let result = currentData.reCreate(params, renderObject.builder, true)
 | 
						||
 | 
						||
  let data = {
 | 
						||
    params,
 | 
						||
    columns: result.columns,
 | 
						||
    pixels: result.mask.imageData
 | 
						||
  }
 | 
						||
  return data
 | 
						||
}
 | 
						||
 | 
						||
RenderDynamicCurrent.prototype.reCreate = function (renderObject) {
 | 
						||
  var scene = this._viewer.scene
 | 
						||
  var canvas = scene.canvas
 | 
						||
  var camera = scene.camera
 | 
						||
 | 
						||
  var width = renderObject._viewer.scene.canvas.clientWidth
 | 
						||
  var height = renderObject._viewer.scene.canvas.clientHeight
 | 
						||
  renderObject._windowWidth = width
 | 
						||
  renderObject._windowheight = height
 | 
						||
  renderObject._bounds.xMax = width
 | 
						||
  renderObject._bounds.yMax = height
 | 
						||
  renderObject._bounds.width = width
 | 
						||
  renderObject._bounds.height = height
 | 
						||
  if (renderObject._field != null) {
 | 
						||
    renderObject._field.release()
 | 
						||
  }
 | 
						||
 | 
						||
  var params = {}
 | 
						||
  params.clientWidth = canvas.clientWidth
 | 
						||
  params.clientHeight = canvas.clientHeight
 | 
						||
  params.viewMatrix = camera.viewMatrix
 | 
						||
  params.projectionMatrix = camera.frustum.projectionMatrix
 | 
						||
  params.fovy = camera.frustum.fovy
 | 
						||
  params.aspectRatio = camera.frustum.aspectRatio
 | 
						||
  params.near = camera.frustum.near
 | 
						||
  params.positionWC = camera.positionWC
 | 
						||
  params.directionWC = camera.directionWC
 | 
						||
  params.rightWC = camera.rightWC
 | 
						||
  params.upWC = camera.upWC
 | 
						||
  params.center = renderObject._centerPnt
 | 
						||
  params.bounds = renderObject._bounds
 | 
						||
  params.uvData = this.uvData
 | 
						||
  params.velocityScale_o = renderObject.velocityScale_o
 | 
						||
 | 
						||
  const data = renderObject.dealData(renderObject, params)
 | 
						||
  renderObject.setData(renderObject, data)
 | 
						||
}
 | 
						||
RenderDynamicCurrent.prototype.getVelocityScaleByHeight = function (height) {
 | 
						||
  let extent = this.getCurrentExtent()
 | 
						||
  let mapBounds = {
 | 
						||
    south: this.deg2rad(extent[1]),
 | 
						||
    north: this.deg2rad(extent[3]),
 | 
						||
    east: this.deg2rad(extent[2]),
 | 
						||
    west: this.deg2rad(extent[0])
 | 
						||
  }
 | 
						||
  let mapArea =
 | 
						||
    (mapBounds.south - mapBounds.north) * (mapBounds.west - mapBounds.east)
 | 
						||
  let scale = 0.0001 * this.velocityScale
 | 
						||
  if (height < 630000) scale = 0.00005 * this.velocityScale
 | 
						||
  let velocityScale_o =
 | 
						||
    scale *
 | 
						||
    (Math.pow(window.devicePixelRatio, 1 / 3) || 1) *
 | 
						||
    Math.pow(mapArea, 0.2)
 | 
						||
  return velocityScale_o
 | 
						||
}
 | 
						||
RenderDynamicCurrent.prototype.getScaleByHeight = function (height) {
 | 
						||
  // console.log('当前相机高度', height)
 | 
						||
  if (height <= 7798950) {
 | 
						||
    return this.densityScale * 0.5
 | 
						||
  } else {
 | 
						||
    return this.densityScale * 0.9
 | 
						||
  }
 | 
						||
}
 | 
						||
RenderDynamicCurrent.prototype.getCurrentExtent = function () {
 | 
						||
  let _self = this
 | 
						||
  //获取当前三维地图范围
 | 
						||
  var Rectangle = _self._viewer.camera.computeViewRectangle()
 | 
						||
  //地理坐标(弧度)转经纬度坐标
 | 
						||
  var extent = [
 | 
						||
    (Rectangle.west / Math.PI) * 180,
 | 
						||
    (Rectangle.south / Math.PI) * 180,
 | 
						||
    (Rectangle.east / Math.PI) * 180,
 | 
						||
    (Rectangle.north / Math.PI) * 180
 | 
						||
  ]
 | 
						||
  return extent
 | 
						||
}
 | 
						||
RenderDynamicCurrent.prototype.deg2rad = function (deg) {
 | 
						||
  return (deg / 180) * Math.PI
 | 
						||
}
 | 
						||
RenderDynamicCurrent.prototype.Render = function () {
 | 
						||
  var scene = this._viewer.scene
 | 
						||
  var renderObject = this
 | 
						||
  renderObject.start = true
 | 
						||
  renderObject.velocityScale_o = renderObject.getVelocityScaleByHeight(
 | 
						||
    scene.camera.positionCartographic.height
 | 
						||
  )
 | 
						||
  renderObject._isRender = true
 | 
						||
  this.reCreate(renderObject)
 | 
						||
  renderObject._scale = renderObject.getScaleByHeight(
 | 
						||
    scene.camera.positionCartographic.height
 | 
						||
  )
 | 
						||
 | 
						||
  scene.camera.moveEnd.addEventListener(function () {
 | 
						||
    //获取当前相机高度
 | 
						||
    renderObject.start1 = true
 | 
						||
    //获取当前相机高度
 | 
						||
    var newCenter = scene.camera.positionCartographic
 | 
						||
    // if (newCenter.height < 1263951.9408551503) {
 | 
						||
    //   for (let i = window.aalayers.length - 1; i >= 0; i--) {
 | 
						||
    //     let layers = window.aalayers[i]
 | 
						||
    //     if (layers._opt.name === '海流场信息') {
 | 
						||
    //       if (layers.visible === true) {
 | 
						||
    //         layers.visible = false
 | 
						||
    //       }
 | 
						||
    //     }
 | 
						||
    //   }
 | 
						||
    // } else {
 | 
						||
    //   for (let i = window.aalayers.length - 1; i >= 0; i--) {
 | 
						||
    //     let layers = window.aalayers[i]
 | 
						||
    //     if (layers._opt.name === '海流场信息') {
 | 
						||
    //       if (layers.visible === false) {
 | 
						||
    //         layers.visible = true
 | 
						||
    //       }
 | 
						||
    //     }
 | 
						||
    //   }
 | 
						||
    // }
 | 
						||
    if (!renderObject.start) return
 | 
						||
 | 
						||
    if (newCenter != renderObject._centerPnt) {
 | 
						||
      renderObject.velocityScale_o = renderObject.getVelocityScaleByHeight(
 | 
						||
        scene.camera.positionCartographic.height
 | 
						||
      )
 | 
						||
      renderObject.reCreate(renderObject)
 | 
						||
      renderObject._isRender = true
 | 
						||
      renderObject._scale = renderObject.getScaleByHeight(newCenter.height)
 | 
						||
      renderObject.particles = []
 | 
						||
      renderObject.particleCount = Math.round(
 | 
						||
        renderObject._windowheight *
 | 
						||
          currentData.PARTICLE_MULTIPLIER *
 | 
						||
          renderObject._windowWidth *
 | 
						||
          renderObject._scale
 | 
						||
      )
 | 
						||
      if (renderObject._field != null) {
 | 
						||
        for (var i = 0; i < renderObject.particleCount; i++) {
 | 
						||
          if (!renderObject.start1) {
 | 
						||
            i = renderObject.particleCount - 1
 | 
						||
            return
 | 
						||
          }
 | 
						||
          renderObject.particles.push(
 | 
						||
            renderObject._field.randomize({
 | 
						||
              age: currentData.random(0, currentData.MAX_PARTICLE_AGE)
 | 
						||
            })
 | 
						||
          )
 | 
						||
        }
 | 
						||
      }
 | 
						||
    }
 | 
						||
  })
 | 
						||
 | 
						||
  scene.camera.moveStart.addEventListener(function () {
 | 
						||
    //获取当前相机高度
 | 
						||
    var newCenter = scene.camera.positionCartographic
 | 
						||
 | 
						||
    if (newCenter != renderObject._centerPnt) {
 | 
						||
      if (renderObject._field != null) {
 | 
						||
        renderObject._field.release()
 | 
						||
      }
 | 
						||
      renderObject.start1 = false
 | 
						||
      renderObject._isRender = false
 | 
						||
      if (renderObject._imageG) {
 | 
						||
        renderObject._imageG.clearRect(
 | 
						||
          0,
 | 
						||
          0,
 | 
						||
          renderObject._windowWidth,
 | 
						||
          renderObject._windowheight
 | 
						||
        )
 | 
						||
        renderObject._g.clearRect(
 | 
						||
          0,
 | 
						||
          0,
 | 
						||
          renderObject._windowWidth,
 | 
						||
          renderObject._windowheight
 | 
						||
        )
 | 
						||
      }
 | 
						||
    }
 | 
						||
  })
 | 
						||
  // currentData.maxIntensity is the velocity at which particle color intensity is maximum
 | 
						||
  var colorStyles = currentData.windIntensityColorScale(
 | 
						||
    currentData.INTENSITY_SCALE_STEP,
 | 
						||
    currentData.maxIntensity
 | 
						||
  )
 | 
						||
  var buckets = colorStyles.map(function () {
 | 
						||
    return []
 | 
						||
  })
 | 
						||
 | 
						||
  function evolve() {
 | 
						||
    buckets.forEach(function (bucket) {
 | 
						||
      bucket.length = 0
 | 
						||
    })
 | 
						||
    renderObject.particles.forEach(function (particle) {
 | 
						||
      if (particle.age > currentData.MAX_PARTICLE_AGE) {
 | 
						||
        renderObject._field.randomize(particle).age = 0
 | 
						||
      }
 | 
						||
      var x = particle.x
 | 
						||
      var y = particle.y
 | 
						||
      var v = renderObject._field(x, y) // vector at current position
 | 
						||
      var m = v[2]
 | 
						||
      if (m === null) {
 | 
						||
        particle.age = currentData.MAX_PARTICLE_AGE // particle has escaped the grid, never to return...
 | 
						||
      } else {
 | 
						||
        var xt = x + v[0] * currentData.WindScale
 | 
						||
        var yt = y + v[1] * currentData.WindScale
 | 
						||
        if (renderObject._field.isDefined(xt, yt)) {
 | 
						||
          // Path from (x,y) to (xt,yt) is visible, so add this particle to the appropriate draw bucket.
 | 
						||
          particle.xt = xt
 | 
						||
          particle.yt = yt
 | 
						||
          buckets[colorStyles.indexFor(m)].push(particle)
 | 
						||
        } else {
 | 
						||
          // Particle isn't visible, but it still moves through the field.
 | 
						||
          particle.x = xt
 | 
						||
          particle.y = yt
 | 
						||
        }
 | 
						||
      }
 | 
						||
      particle.age += 1
 | 
						||
    })
 | 
						||
  }
 | 
						||
 | 
						||
  function draw() {
 | 
						||
    if (!renderObject.start) return
 | 
						||
 | 
						||
    var g = renderObject._g
 | 
						||
    if (g == null || renderObject._imageMask == null) {
 | 
						||
      return
 | 
						||
    }
 | 
						||
    var bounds = renderObject._bounds
 | 
						||
 | 
						||
    var prev = g.globalCompositeOperation
 | 
						||
    g.globalCompositeOperation = 'destination-in'
 | 
						||
    g.fillRect(bounds.x, bounds.y, bounds.width, bounds.height)
 | 
						||
    //g.putImageData(renderObject._imageMask.imageData,0,0)
 | 
						||
    g.globalCompositeOperation = prev
 | 
						||
 | 
						||
    // Draw new particle trails.
 | 
						||
    buckets.forEach(function (bucket, i) {
 | 
						||
      if (bucket.length > 0) {
 | 
						||
        g.beginPath()
 | 
						||
        g.strokeStyle = colorStyles[i]
 | 
						||
        bucket.forEach(function (particle) {
 | 
						||
          g.moveTo(particle.x, particle.y)
 | 
						||
          g.lineTo(particle.xt, particle.yt)
 | 
						||
          particle.x = particle.xt
 | 
						||
          particle.y = particle.yt
 | 
						||
        })
 | 
						||
        g.stroke()
 | 
						||
      }
 | 
						||
    })
 | 
						||
  }
 | 
						||
 | 
						||
  ;(function frame() {
 | 
						||
    evolve()
 | 
						||
    draw()
 | 
						||
 | 
						||
    if (renderObject._isRender && renderObject._imageMask) {
 | 
						||
      //renderObject._imageG.putImageData(renderObject._imageMask,0,0);
 | 
						||
    }
 | 
						||
    if (renderObject.start) {
 | 
						||
      setTimeout(frame, 10 / 0.8)
 | 
						||
    }
 | 
						||
  })()
 | 
						||
}
 | 
						||
 | 
						||
RenderDynamicCurrent.prototype.remove = function () {
 | 
						||
  var renderObject = this
 | 
						||
  if (
 | 
						||
    renderObject._lineCanvas != undefined &&
 | 
						||
    renderObject._lineCanvas.style != null
 | 
						||
  ) {
 | 
						||
    renderObject._lineCanvas.style.display = 'none'
 | 
						||
  }
 | 
						||
  if (
 | 
						||
    renderObject._imageCanvas != undefined &&
 | 
						||
    renderObject._imageCanvas.style != null
 | 
						||
  ) {
 | 
						||
    renderObject._imageCanvas.style.display = 'none'
 | 
						||
  }
 | 
						||
  renderObject.start = false
 | 
						||
  if (document.getElementById('image-canvas'))
 | 
						||
    document.getElementById('image-canvas').remove()
 | 
						||
  if (document.getElementById('fullScreen'))
 | 
						||
    document.getElementById('fullScreen').remove()
 | 
						||
 | 
						||
  this.particles = []
 | 
						||
}
 | 
						||
 | 
						||
RenderDynamicCurrent.prototype.clone = function () {}
 | 
						||
RenderDynamicCurrent.prototype.update = function () {
 | 
						||
  var RTOD = 180.0 / 3.1415926
 | 
						||
  var canvas = document.getElementById('animation')
 | 
						||
  var g = canvas.getContext('2d')
 | 
						||
  g.fillStyle = 'rgba(0, 0, 0, 0.97)'
 | 
						||
  g.lineWidth = 20
 | 
						||
 | 
						||
  function draw() {
 | 
						||
    // Fade existing particle trails.
 | 
						||
    var prev = 'source-over'
 | 
						||
    g.globalCompositeOperation = 'destination-in'
 | 
						||
    g.fillRect(0, 0, 800, 600)
 | 
						||
    g.globalCompositeOperation = prev
 | 
						||
    g.beginPath()
 | 
						||
    g.strokeStyle = 0x111111
 | 
						||
    for (var i = 0; i < 100; i++) {
 | 
						||
      var x = Math.floor(Math.random() * 800)
 | 
						||
      var y = Math.floor(Math.random() * 600)
 | 
						||
 | 
						||
      g.moveTo(x, y)
 | 
						||
      g.lineTo(x + 5, y + 5)
 | 
						||
    }
 | 
						||
    g.stroke()
 | 
						||
  }
 | 
						||
 | 
						||
  ;(function frame() {
 | 
						||
    try {
 | 
						||
      draw()
 | 
						||
      setTimeout(frame, 40)
 | 
						||
    } catch (e) {}
 | 
						||
  })()
 | 
						||
}
 | 
						||
RenderDynamicCurrent.prototype.updateO = function (options) {
 | 
						||
  const renderObject = this
 | 
						||
  var scene = renderObject._viewer.scene
 | 
						||
  renderObject.lineWidth = options.lineWidth || renderObject.lineWidth
 | 
						||
  renderObject.densityScale = options.densityScale || renderObject.densityScale
 | 
						||
  renderObject.velocityScale =
 | 
						||
    options.velocityScale || renderObject.velocityScale
 | 
						||
  if (renderObject._field != null) {
 | 
						||
    renderObject._field.release()
 | 
						||
  }
 | 
						||
  renderObject.start1 = false
 | 
						||
  renderObject._isRender = false
 | 
						||
  if (renderObject._imageG) {
 | 
						||
    renderObject._imageG.clearRect(
 | 
						||
      0,
 | 
						||
      0,
 | 
						||
      renderObject._windowWidth,
 | 
						||
      renderObject._windowheight
 | 
						||
    )
 | 
						||
    renderObject._g.clearRect(
 | 
						||
      0,
 | 
						||
      0,
 | 
						||
      renderObject._windowWidth,
 | 
						||
      renderObject._windowheight
 | 
						||
    )
 | 
						||
  }
 | 
						||
  if (!renderObject.start) return
 | 
						||
  //获取当前相机高度
 | 
						||
  renderObject.start1 = true
 | 
						||
  renderObject._isRender = true
 | 
						||
  renderObject._height = scene.camera.positionCartographic.height
 | 
						||
  renderObject._scale = renderObject.getScaleByHeight(renderObject._height)
 | 
						||
  renderObject.velocityScale_o = renderObject.getVelocityScaleByHeight(
 | 
						||
    renderObject._height
 | 
						||
  )
 | 
						||
  renderObject.reCreate(renderObject)
 | 
						||
  renderObject.particles = []
 | 
						||
  renderObject.particleCount = Math.round(
 | 
						||
    renderObject._windowheight *
 | 
						||
      currentData.PARTICLE_MULTIPLIER *
 | 
						||
      renderObject._windowWidth *
 | 
						||
      renderObject._scale
 | 
						||
  )
 | 
						||
  if (renderObject._field != null) {
 | 
						||
    for (var i = 0; i < renderObject.particleCount; i++) {
 | 
						||
      if (!renderObject.start1) {
 | 
						||
        i = renderObject.particleCount - 1
 | 
						||
        return
 | 
						||
      }
 | 
						||
      renderObject.particles.push(
 | 
						||
        renderObject._field.randomize({
 | 
						||
          age: currentData.random(0, currentData.MAX_PARTICLE_AGE)
 | 
						||
        })
 | 
						||
      )
 | 
						||
    }
 | 
						||
  }
 | 
						||
}
 | 
						||
export default RenderDynamicCurrent
 |