cesium流动材质应用特效


采用vue+cesium实现

引入js部分

import Cesium from "cesium/Cesium";

export class PolylineTrailMaterialProperty {

    constructor(options) {

        options = Cesium.defaultValue(options, Cesium.defaultValue.EMPTY_OBJECT);

        this._definitionChanged = new Cesium.Event();

        this._color = undefined;

        this._colorSubscription = undefined;

        this.color = options.color;

        this.duration = options.duration;

        this.trailImage = options.trailImage;

        this._time = performance.now();

    }

}

Cesium.defineProperties(PolylineTrailMaterialProperty.prototype, {

    isConstant: {

        get: function() {

            return false;

        }

    },

    definitionChanged: {

        get: function() {

            return this._definitionChanged;

        }

    },

    color: Cesium.createPropertyDescriptor('color')

});

PolylineTrailMaterialProperty.prototype.getType = function(time) {

    return 'PolylineTrail';

}

PolylineTrailMaterialProperty.prototype.getValue = function(time, result) {

    if (!Cesium.defined(result)) {

        result = {};

    }

    result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);

    //result.image = Cesium.Material.PolylineTrailImage;

    result.image = this.trailImage;

    result.time = ((performance.now() - this._time) % this.duration) / this.duration;

    return result;

}

PolylineTrailMaterialProperty.prototype.equals = function(other) {

    return this === other ||

        (other instanceof PolylineTrailMaterialProperty &&

            Cesium.Property.equals(this._color, other._color))

}

Cesium.Material.PolylineTrailType = 'PolylineTrail';

Cesium.Material.PolylineTrailImage = "images/colors.png";

Cesium.Material.PolylineTrailSource = "czm_material czm_getMaterial(czm_materialInput materialInput)\n" +

                                                      "{\n" + 

                                                        "czm_material material = czm_getDefaultMaterial(materialInput);\n" +

                                                          "vec2 st = materialInput.st;\n" +

                                                          "vec4 colorImage = texture2D(image, vec2(fract(st.s - time), st.t));\n" +

                                                          "material.alpha = colorImage.a * color.a;\n"+

                                                          "material.diffuse = (colorImage.rgb+color.rgb)/2.0;\n"+

                                                          "return material;\n" +

                                                      "}";

Cesium.Material._materialCache.addMaterial(Cesium.Material.PolylineTrailType, {

    fabric: {

        type: Cesium.Material.PolylineTrailType,

        uniforms: {

            color: new Cesium.Color(1.0, 0.0, 0.0, 0.5),

            image: Cesium.Material.PolylineTrailImage,

            time: 0

        },

        source: Cesium.Material.PolylineTrailSource

    },

    translucent: function(material) {

        return true;

    }

});

Cesium.PolylineTrailMaterialProperty = PolylineTrailMaterialProperty;

vue应用部分

<template>

  <div class="fullSize" id="cesiumContainer"></div>

</template>

<script>

import "cesium/Widgets/widgets.css";

import Cesium from "cesium/Cesium";

import PolylineTrailMaterialProperty from "@/unit/PolylineTrailMaterialProperty";

export default {

  name: "CesiumDynamicLine1",

  //

  data() {

    return {

      viewer: null

    };

  },

  mounted() {

    let viewerOption = {

      geocoder: false, // 地理位置查询定位控件

      homeButton: false, // 默认相机位置控件

      timeline: false, // 时间滚动条控件

      navigationHelpButton: false, // 默认的相机控制提示控件

      fullscreenButton: false, // 全屏控件

      scene3DOnly: true, // 每个几何实例仅以3D渲染以节省GPU内存

      baseLayerPicker: false, // 底图切换控件

      shouldAnimate: true, //是否开始动画

      // useDefaultRenderLoop : true,//如果需要控制渲染循环,则设为true

      selectionIndicator: true, //是否显示选取指示器组件

      // targetFrameRate:60,

      vrButton: true,

      showRenderLoopErrors: true,

      requestAnimationFrame: true,

      // showRenderLoopErrors : false,

      animation: false // 控制场景动画的播放速度控件

    };

    this.viewer = new Cesium.Viewer(this.$el, viewerOption);

    this.create();

  },

  methods: {

    create() {

      //创建射线

      var data = {

        startPoint: {

          id: 0,

          lon: 114.302312702,

          lat: 30.598026044,

          size: 20,

          height: 0,

          url:"3d/leida/leida.gltf",

          color: Cesium.Color.PURPLE

        },

        center: 

          {

            id: 1,

            lon: 115.028495718,

            lat: 30.200814617,

            height: 100000,

            color: Cesium.Color.YELLOW,

            url:"3d/weixing_1.gltf",

            size: 15

          },

        endPoint: {

          id: 0,

          lon: 116.302312702,

          lat: 30.598026044,

          size: 20,

          height: 0,

          url:"3d/junjian/junjian.gltf",

          color: Cesium.Color.PURPLE

        },

        options: {

          name: "",

          polyline: {

            width: 2,

            trailImage: "images/color.png",  

            trailImage1: "images/green.png",  

            material: [Cesium.Color.GREEN, 3000]

          }

        }

      };

      this.createFlyLines(data);

    },

    createFlyLines(data) {

      var self = this;

        /***** 创建发送目标*****/

      const hpRoll = new Cesium.HeadingPitchRoll(Cesium.Math.toRadians(-90), 0, 0);

      const startPoint = Cesium.Cartesian3.fromDegrees(

                data.startPoint.lon,

                data.startPoint.lat,

                data.startPoint.height

        );

      const centerPoint = Cesium.Cartesian3.fromDegrees(

                data.center.lon,

                data.center.lat,

                data.center.height

        );

      const endPoint = Cesium.Cartesian3.fromDegrees(

        data.endPoint.lon,

        data.endPoint.lat,

        data.endPoint.height

        );

      this.viewer.entities.add({

        position: startPoint,

        orientation: this.Cesium.Transforms.headingPitchRollQuaternion(startPoint, hpRoll),

        model:{

          uri: data.startPoint.url,

          minimumPixelSize: 32

        }

      }); 

      //大批量操作时,临时禁用事件可以提高性能

      this.viewer.entities.suspendEvents(); //散点


        // 创建材质

        let material = new Cesium.PolylineTrailMaterialProperty({ //创建材质

          color: Cesium.Color.GREEN.withAlpha(0.5),

          duration: 3000,

          trailImage: data.options.polyline.trailImage1

        });

        let material1 = new Cesium.PolylineTrailMaterialProperty({ //创建材质1

          color: Cesium.Color.YELLOW.withAlpha(0.5),

          duration: 3000,

          trailImage: data.options.polyline.trailImage

        });

        // 创建中转目标

        this.viewer.entities.add({

          position: centerPoint,

          orientation: this.Cesium.Transforms.headingPitchRollQuaternion(centerPoint, hpRoll),

          model: {

          uri: data.center.url,

          minimumPixelSize: 128

        }

        });

        // 创建接收目标

        this.viewer.entities.add({

          position:  Cesium.Cartesian3.fromDegrees(

                data.endPoint.lon,

                data.endPoint.lat,

                data.endPoint.height

          ),

          orientation: this.Cesium.Transforms.headingPitchRollQuaternion(endPoint, hpRoll),

          model: {

          uri: data.endPoint.url,

          minimumPixelSize: 128

        }

        });

        // 创建第一条信号线

        this.viewer.entities.add({

          polyline: {

            positions: self.generateCurve(startPoint, centerPoint),

            width: 2,

            material: material

          }

        });

        this.viewer.entities.add({

          polyline: {

            positions: self.generateCurve(centerPoint, endPoint),

            width: 2,

            material: material1

          }

        });

      this.viewer.entities.resumeEvents();

      //镜头顺时针旋转九十度,即东向

      var heading = Cesium.Math.toRadians(0);

      //镜头倾斜30度俯视

      var pitch = Cesium.Math.toRadians(-0);

      this.viewer.zoomTo(

        this.viewer.entities,

        new Cesium.HeadingPitchRange(heading, pitch,490000)

      );

    } 

   /**

    * 生成流动曲线

    * @param startPoint 起点

    * @param endPoint 终点

    * @returns {Array}

    */,

    generateCurve(startPoint, endPoint) {

      let addPointCartesian = new Cesium.Cartesian3();

      Cesium.Cartesian3.add(startPoint, endPoint, addPointCartesian);

      let midPointCartesian = new Cesium.Cartesian3();

      Cesium.Cartesian3.divideByScalar(addPointCartesian, 2, midPointCartesian);

      let midPointCartographic = Cesium.Cartographic.fromCartesian(

        midPointCartesian

      );

      midPointCartographic.height =

        Cesium.Cartesian3.distance(startPoint, endPoint) / 2.5;

      let midPoint = new Cesium.Cartesian3();

      Cesium.Ellipsoid.WGS84.cartographicToCartesian(

        midPointCartographic,

        midPoint

      );

      let spline = new Cesium.CatmullRomSpline({

        times: [0.0, 0.5, 1.0],

        points: [startPoint, midPoint, endPoint]

      });

      let curvePoints = [];

      for (let i = 0, len = 200; i < len; i++) {

        curvePoints.push(spline.evaluate(i / len));

      }

//       console.log(curvePoints);

      return curvePoints;

    }

  }

};

</script>

<style lang="scss" >

</style>

总结:此特效为三者传递信号,以流动材质作为传递信号源。注:材质图片采用渐变色,尽量与材质本事颜色色差凸显出来,否则效果不明显。在此也非常感谢Cesium流动线纹理的作者-happy_port。给我在他效果的基本上实现此效果的灵感。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,491评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,856评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,745评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,196评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,073评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,112评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,531评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,215评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,485评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,578评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,356评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,215评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,583评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,898评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,497评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,697评论 2 335