通过传图片,实现一个可以设置重复次数和持续时间的流动线条。是在常见的流动线条效果上面更改了一些代码。找了很多,但都是单一的流动效果,不能设置重复次数,于是就自己重新改动了一点。
- function FlowLineMaterial(opt) {
- this.defaultColor = new Cesium.Color(0, 0, 0, 0);
- opt = opt || {};
- this._definitionChanged = new Cesium.Event();
- this._color = undefined;
- this.color = opt.color || this.defaultColor; //颜色
- this._duration = opt.duration || 1000; //时长
- this.url = opt.url; //材质图片
- this._time = undefined;
- }
-
- FlowLineMaterial.prototype.getType = function (time) {
- return "FlowLine";
- };
-
- FlowLineMaterial.prototype.getValue = function (time, result) {
- if (!Cesium.defined(result)) {
- result = {};
- }
- result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, this.defaultColor, result.color);
- result.image = this.url;
- if (this._time === undefined) {
- this._time = new Date().getTime();
- }
- result.time = (new Date().getTime() - this._time) / this._duration;
-
- return result;
- };
-
- FlowLineMaterial.prototype.equals = function (other) {
- return this === other ||
- other instanceof FlowLineMaterial && Cesium.Property.equals(this._color, other._color);
- };
-
- Object.defineProperties(FlowLineMaterial.prototype, {
- isConstant: {
- get: function get() {
- return false;
- }
- },
- definitionChanged: {
- get: function get() {
- return this._definitionChanged;
- }
- },
- color: Cesium.createPropertyDescriptor('color')
- });
-
-
- Cesium.Material._materialCache.addMaterial("FlowLine", {
- fabric: {
- type: "FlowLine",
- uniforms: {
- color: new Cesium.Color(1, 0, 0, 1.0),
- image: '',
- time: 0,
- repeat: new Cesium.Cartesian2(1.0, 1.0)
- },
-
- source: "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
- {\n\
- czm_material material = czm_getDefaultMaterial(materialInput);\n\
- vec2 st = repeat * materialInput.st;\n\
- vec4 colorImage = texture2D(image, vec2(fract(st.s - time), st.t));\n\
- if(color.a == 0.0)\n\
- {\n\
- material.alpha = colorImage.a;\n\
- material.diffuse = colorImage.rgb; \n\
- }\n\
- else\n\
- {\n\
- material.alpha = colorImage.a * color.a;\n\
- material.diffuse = max(color.rgb * material.alpha * 3.0, color.rgb); \n\
- }\n\
- return material;\n\
- }"
- },
- translucent: function translucent() {
- return true;
- }
- });
使用起来的话也很简单,只不过要注意repeat的值,并不是普通的数字,而是Cartesian2类型的值。
用法如下;重复两次
- viewer.entities.add({
- name: 'PolylineTrail',
- polyline: {
- positions: Cesium.Cartesian3.fromDegreesArrayHeights([
- 110,30, 100000,
- 114, 30, 100000,
- 114, 50, 1000000]),
- width: 5,
- material: new FlowLineMaterial({
- color: Cesium.Color.fromCssColorString('#00ff00'),
- duration: 5000,
- repeat: new Cesium.Cartesian2(2.0,1.0),
- url: 'img/lineArrow2.png'
- })
- }
- });
-
-
- viewer.zoomTo(viewer.entities);
效果图:

如果完善一下的话,就可以只传数字,从而实现在x方向或者y方向上的重复。
主要原理是fabric的source里面。
materialInput.st 是一个vec2类型的值,repeat最后也会变成vec2类型的值。两个相乘,应该就是向量的乘法。
materialInput.st的第一个值可以看成是沿线的方向,第二个值是线的垂直方向。沿线的方向重复了两次。
对于流动墙体,则有两种情况。一种是环形围绕墙的动画,一种是在垂直方向上的动画。
如果将这种思路应用到环绕墙效果上,那么repeat也是一样的设置,对于垂直墙动画,也是一样的,只不过方向不同而已。
环绕墙在原先基础上显示两个环绕效果:

代码如下:
- function PolylineTrailLinkMaterialProperty(color, duration, repeat) {
- this._definitionChanged = new Cesium.Event();
- this._color = undefined;
- this._repeat = undefined;
- this._colorSubscription = undefined;
- this.color = color;
- this.repeat = repeat;
- this.duration = duration;
- this._time = (new Date()).getTime();
- }
- Object.defineProperties(PolylineTrailLinkMaterialProperty.prototype, {
- isConstant: {
- get: function () {
- return false;
- }
- },
- definitionChanged: {
- get: function () {
- return this._definitionChanged;
- }
- },
- color: Cesium.createPropertyDescriptor('color'),
- repeat: Cesium.createPropertyDescriptor('repeat')
- });
- PolylineTrailLinkMaterialProperty.prototype.getType = function (time) {
- return 'PolylineTrailLink';
- }
- PolylineTrailLinkMaterialProperty.prototype.getValue = function (time, result) {
- if (!Cesium.defined(result)) {
- result = {};
- }
- result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
- result.repeat = Cesium.Property.getValueOrClonedDefault(this._repeat, time,new Cesium.Cartesian2(1.0,1.0), result.repeat);
- result.image = Cesium.Material.PolylineTrailLinkImage;
- result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration;
- return result;
- }
- PolylineTrailLinkMaterialProperty.prototype.equals = function (other) {
- return this === other ||
- (other instanceof PolylineTrailLinkMaterialProperty &&
- Property.equals(this._color, other._color))
- }
- Cesium.PolylineTrailLinkMaterialProperty = PolylineTrailLinkMaterialProperty;
- Cesium.Material.PolylineTrailLinkType = 'PolylineTrailLink';
- Cesium.Material.PolylineTrailLinkImage = "./img/colors.png";
- Cesium.Material.PolylineTrailLinkSource = "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
- {\n\
- czm_material material = czm_getDefaultMaterial(materialInput);\n\
- vec2 st = repeat * 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.PolylineTrailLinkType, {
- fabric: {
- type: Cesium.Material.PolylineTrailLinkType,
- uniforms: {
- color: new Cesium.Color(1.0, 0.0, 0.0, 1),
- image: Cesium.Material.PolylineTrailLinkImage,
- time: 0,
- repeat: new Cesium.Cartesian2(1.0,1.0)
- },
- source: Cesium.Material.PolylineTrailLinkSource
- },
- translucent: function (material) {
- return true;
- }
- });
-
- var redWall = viewer.entities.add({
- name: "Red wall from surface with outline",
- wall: {
- positions: Cesium.Cartesian3.fromDegreesArray([
- -107.0,
- 43.0,
- -97.0,
- 43.0,
- -97.0,
- 40.0,
- -107.0,
- 40.0,
- -107.0,
- 43.0,
- ]),
- maximumHeights: [10000, 10000, 10000, 10000, 10000],
- minimumHeights: [43.9, 49.4, 38.7, 40, 54],
- material: new Cesium.PolylineTrailLinkMaterialProperty(Cesium.Color.RED, 3000, new Cesium.Cartesian2(2.0,1.0))
- },
- });
-
- viewer.zoomTo(viewer.entities)
只是和上面流动线略有不同的设置方式。
垂直流动墙效果:

上面是在垂直方向重复两次的,下面是不重复的效果

材质代码如下,和环绕墙材质很多代码一样,唯一不同的就是glsl语言略有不同,重复的方向从s的水平方向变成了t的垂直方向。
-
- function PolylineTrailLinkMaterialProperty(color, duration, repeat) {
- this._definitionChanged = new Cesium.Event();
- this._color = undefined;
- this._colorSubscription = undefined;
- this.color = color;
- this._repeat = undefined;
- this.repeat = repeat;
- this.duration = duration;
- this._time = (new Date()).getTime();
- }
- Object.defineProperties(PolylineTrailLinkMaterialProperty.prototype, {
- isConstant: {
- get: function () {
- return false;
- }
- },
- definitionChanged: {
- get: function () {
- return this._definitionChanged;
- }
- },
- color: Cesium.createPropertyDescriptor('color'),
- repeat: Cesium.createPropertyDescriptor('repeat')
- });
- PolylineTrailLinkMaterialProperty.prototype.getType = function (time) {
- return 'PolylineTrailLink';
- }
- PolylineTrailLinkMaterialProperty.prototype.getValue = function (time, result) {
- if (!Cesium.defined(result)) {
- result = {};
- }
- result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color);
- result.repeat = Cesium.Property.getValueOrClonedDefault(this._repeat, time, new Cesium.Cartesian2(1.0,1.0), result.repeat);
- result.image = Cesium.Material.PolylineTrailLinkImage;
- result.time = (((new Date()).getTime() - this._time) % this.duration) / this.duration;
- return result;
- }
- PolylineTrailLinkMaterialProperty.prototype.equals = function (other) {
- return this === other ||
- (other instanceof PolylineTrailLinkMaterialProperty &&
- Property.equals(this._color, other._color))
- }
- Cesium.PolylineTrailLinkMaterialProperty = PolylineTrailLinkMaterialProperty;
- Cesium.Material.PolylineTrailLinkType = 'PolylineTrailLink';
- // Cesium.Material.PolylineTrailLinkImage = "./img/colors.png";
- Cesium.Material.PolylineTrailLinkImage = "./img/fence.png";
- // Cesium.Material.PolylineTrailLinkSource = "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.PolylineTrailLinkSource = "czm_material czm_getMaterial(czm_materialInput materialInput)\n\
- {\n\
- czm_material material = czm_getDefaultMaterial(materialInput);\n\
- vec2 st = repeat * materialInput.st;\n\
- vec4 colorImage = texture2D(image, vec2(fract((st.t - time)), st.t));\n\
- vec4 fragColor;\n\
- fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\
- fragColor = czm_gammaCorrect(fragColor);\n\
- material.alpha = colorImage.a * color.a;\n\
- material.diffuse = (colorImage.rgb+color.rgb)/2.0;\n\
- return material;\n\
- }";
- // vec4 fragColor;\n\
- // fragColor.rgb = (colorImage.rgb+color.rgb) / 1.0;\n\
- // fragColor = czm_gammaCorrect(fragColor);\n\
- Cesium.Material._materialCache.addMaterial(Cesium.Material.PolylineTrailLinkType, {
- fabric: {
- type: Cesium.Material.PolylineTrailLinkType,
- uniforms: {
- color: new Cesium.Color(0.0, 0.0, 0.0, 1),
- image: Cesium.Material.PolylineTrailLinkImage,
- repeat: new Cesium.Cartesian2(1.0,1.0),
- time: 0
- },
- source: Cesium.Material.PolylineTrailLinkSource
- },
- translucent: function (material) {
- return true;
- }
- });
-
- var redWall = viewer.entities.add({
- name: "Green wall from surface with outline",
- wall: {
- positions: Cesium.Cartesian3.fromDegreesArray([
- -107.0,
- 43.0,
- -97.0,
- 43.0,
- -97.0,
- 40.0,
- -107.0,
- 40.0,
- -107.0,
- 43.0,
- ]),
- maximumHeights: [1000000, 1000000, 1000000, 1000000, 1000000],
- material: new Cesium.PolylineTrailLinkMaterialProperty(Cesium.Color.GREEN, 3000, new Cesium.Cartesian2(1.0,2.0))
- },
- });
-
- viewer.zoomTo(viewer.entities)
传入new Cesium.Cartesian2(1.0,2.0)就是重复两次的效果了。
如果对于glsl有了解,下面这个文档就很有帮助。它解释了cesium在渲染过程中使用到的glsl语言,以及哪些参数也传入了通道中。
czm_material - Cesium Documentation
如果对webgl渲染了解,并且对cesium的材质感兴趣,希望对你有帮助。