Cesium 迁徙图,飞线、动态圆。

效果图放前面

  • 符合你预期效果往下看,不符合出门右转,不耽搁大家时间。
    请添加图片描述

流光线

这个流光线网上其实都有很多案例

  • 第一步绘制抛物线
    里面有些配置参数已经添加了说明。
//抛物线绘制
function parabola(twoPoints: number[]) {
  let s: number[] = []
  let startPoint = [twoPoints[0], twoPoints[1], 0]; //起点的经度、纬度
  s = s.concat(startPoint)
  let step = 80;  //线的多少,越多则越平滑(但过多浏览器缓存也会占用越多)
  let heightProportion = 0.125; //最高点和总距离的比值
  let dLon = (twoPoints[2] - startPoint[0]) / step;  //经度差值
  let dLat = (twoPoints[3] - startPoint[1]) / step;  //纬度差值
  let deltaLon = dLon * Math.abs(111000 * Math.cos(twoPoints[1]));  //经度差(米级)
  let deltaLat = dLat * 111000;  //纬度差(米),1纬度相差约111000米
  let endPoint = [0, 0, 0];  //定义一个端点(后面将进行startPoint和endPoint两点画线)
  let heigh: number = step * Math.sqrt(deltaLon * deltaLon + deltaLat * deltaLat) * heightProportion * 2
  let x2 = (10000 * Math.sqrt(dLon * dLon + dLat * dLat)); //小数点扩大10000倍,提高精确度
  let a = (heigh / (x2 * x2));
  function y(x: number, height: number) { return height - a * x * x; }
  for (var i = 1; i <= step; i++) {  //逐“帧”画线
    endPoint[0] = startPoint[0] + dLon; //更新end点经度
    endPoint[1] = startPoint[1] + dLat; //更新end点纬度
    let x = x2 * (2 * i / step - 1);  //求抛物线函数x
    endPoint[2] = y(x, heigh) * 1;  //求end点高度
    s = s.concat(endPoint)

    // end点变为start点
    startPoint[0] = endPoint[0];
    startPoint[1] = endPoint[1];
    startPoint[2] = endPoint[2];
  }
  return Cesium.Cartesian3.fromDegreesArrayHeights(s)
}
  • 第二步添加曲线

就是cesium常用的primitive方式

let mm = parabola(i)
 const polyline = new Cesium.PolylineGeometry({
   positions: mm,
   width: 2
 });
 const instance = new Cesium.GeometryInstance({
   geometry: polyline,
   id: 'flyline',
})
 const pi = viewer.scene.primitives.add(
  new Cesium.Primitive({
     geometryInstances: [instance],
     appearance: getFlylineMaterial1(),
     releaseGeometryInstances: false,
     compressVertices: false,
   })
 )
  • 第三步添加材质

重点来了

变量或函数解释:
czm_frameNumber:cesium内置变量,随时间变化的帧数
mix:混合函数
smoothstep:样条插值
纹理坐标st.s横向,st.t纵向,随着时间不断移动材质的位置

function getFlylineMaterial1() {
  return new Cesium.PolylineMaterialAppearance({
    material: new Cesium.Material({
      fabric: {
        type: 'test',
        uniforms: {
          speed: 20,
          repeat: 1,
          color: Cesium.Color.fromCssColorString('rgba(0, 209, 237,.1)'), // 线段颜色
          flowColor: Cesium.Color.fromCssColorString('rgba(0, 181, 255,1)'), // 流光颜色
          flowSpeed: 0.01, // 流光速度
          flowIntensity: 1.0, // 流光强度
          startTime: Math.random()
        },
        source: /* glsl */ `
        uniform vec4 color;
        uniform vec4 flowColor;
        uniform float speed;
        uniform float repeat;
        uniform float startTime;
        czm_material czm_getMaterial(czm_materialInput materialInput)
          {
            czm_material material = czm_getDefaultMaterial(materialInput);

            //st.s纵向 st.t横向
            vec2 st = materialInput.st;
            float time = fract(czm_frameNumber * speed / 1000.0 + startTime);
            float offset = fract(st.s*repeat - time);
            //mix混合 smoothstep样条插值
            vec4 ackColor = mix(color, flowColor, smoothstep(1.0 - offset, 1.0 + offset, st.s));
            material.diffuse = ackColor.rgb;
            material.alpha = ackColor.a;
            material.emission = ackColor.rgb * 0.5;
            return material;
          }
        `
      }
    })
  })
}

动态扩散圆

逻辑是和上面一致的
着色器中的材质代码:
discard:用于丢弃当前片段(像素)的渲染。当在片段着色器中遇到 discard 关键字时,当前片段将被丢弃,不会参与后续的渲染过程。白话(不渲染)

 viewer.scene.groundPrimitives.add(new Cesium.GroundPrimitive({
      geometryInstances: new Cesium.GeometryInstance({
        geometry: new Cesium.EllipseGeometry({
          center: Cesium.Cartesian3.fromDegrees(i[2], i[3]),
          semiMajorAxis: 30000.0,
          semiMinorAxis: 30000.0,
        }),
        attributes: {
          color: Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.WHITE)
        }
      }),
      appearance: new Cesium.MaterialAppearance({
        vertexShaderSource: `
        `,
        material: new Cesium.Material({
          fabric: {
            type: 'dynamics point',
            uniforms: {
              color: new Cesium.Color(1, 1, 0, 0.7),
              speed: 12.0,
              count: 2,
              gradient: 0.2,
            },
            source: /* glsl */ `
              uniform vec4 color;
              uniform float speed;
              uniform float count;
              uniform float gradient;
              czm_material czm_getMaterial(czm_materialInput materialInput)
              {
              czm_material material = czm_getDefaultMaterial(materialInput);
              material.diffuse = 1.5 * color.rgb;
              vec2 st = materialInput.st;
              float dis = distance(st, vec2(0.5, 0.5));
              float per = fract(czm_frameNumber * speed / 1000.0);
              if(count == 1.0){
                  if(dis > per * 0.5){
                  discard;
                  }else {
                  material.alpha = color.a  * dis / per / 2.0;
                  }
              } else {
                  vec3 str = materialInput.str;
                  if(abs(str.z)  > 0.001){
                    discard;
                  }
                  if(dis > 0.5){
                    discard;
                  } else {
                  float perDis = 0.5 / count;
                  float disNum;
                  float bl = 0.0;
                  // for (int i = 0; i < 5; i++) {
                      // 在循环中执行操作
                  // }
                  for(int i = 0; i <= 5; i++){
                      if(float(i) <= count) {
                        disNum = perDis * float(i) - dis + per / count;
                        if(disNum > 0.0) {
                            if(disNum < perDis){
                              bl = 1.0 - disNum / perDis;
                            }
                            else if(disNum - perDis < perDis){
                              bl = 1.0 - abs(1.0 - disNum / perDis);
                            }
                            material.alpha = pow(bl,(1.0 + 10.0 * (1.0 - gradient)));
                        }
                      }
                  }
                }
              }
              return material;
              }
            `
          },
        }),

      })
    }))
评论 22
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值