Javascript 更改圆柱体的长度或圆的拉伸高度
我试图更改圆柱体的长度或圆的挤出高度,当它被添加到基本体中并显示在cesium小部件/查看器中时。例如,此气缸:Javascript 更改圆柱体的长度或圆的拉伸高度,javascript,cesium,Javascript,Cesium,我试图更改圆柱体的长度或圆的挤出高度,当它被添加到基本体中并显示在cesium小部件/查看器中时。例如,此气缸: var length = 100; var cylinderGeometry = new Cesium.CylinderGeometry({ length : length, topRadius : cylinderradius, bottomRadius : cylinderradius, slices: cylinderslices, v
var length = 100;
var cylinderGeometry = new Cesium.CylinderGeometry({
length : length,
topRadius : cylinderradius,
bottomRadius : cylinderradius,
slices: cylinderslices,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
});
var cylinder = new Cesium.GeometryInstance({
geometry: cylinderGeometry,
modelMatrix: Cesium.Matrix4.multiplyByTranslation(
Cesium.Transforms.eastNorthUpToFixedFrame(ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(lon, lat))),
new Cesium.Cartesian3(0.0, 0.0, length * 0.5)),
attributes: {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
},
id: "Cylinder1"
});
var primitive = new Cesium.Primitive({
geometryInstances : cylinder ,
appearance : new Cesium.PerInstanceColorAppearance({
closed : false,
translucent: true,
flat: false,
faceForward: true
}),
allow3DOnly: true,
vertexCacheOptimize: true,
allowPicking: true,
releaseGeometryInstances: false
});
widget.scene.primitives.add(primitive);
因为它被添加到原语数组中,所以它将显示在小部件中,但例如,在2秒钟后,我收到一个通知,长度应该减半(这意味着设置为50)。有没有办法做到这一点?在cylinderGeometry
中简单地更改它似乎不起作用
我通过创建一个具有新高度的新圆柱体,添加它并移除旧圆柱体,使其工作。然而,在显示新的圆柱体之前,它往往会闪烁圆柱体(消失了几分之一秒)。我修复了这个问题,在添加新实例后的一段时间后删除了旧实例。整个解决方案不是很优雅,并且在具有少量计算能力的设备上不能很好地工作,因此我正在寻找更好的解决方案
我不在乎这是用圆柱体还是挤压圆来实现的。如果您需要更多信息,请在问题下方的评论中询问
编辑
我实现了Matthew建议的第二个解决方案,但在它完美运行一段时间后,圆柱体停止改变高度(这在我使用解决方案时没有发生)。间隔中的回调确实会被调用。下面是一些代码,显示了我的新解决方案是什么(不起作用):
铯的几何体目前针对静态数据进行了优化。某些属性(如可见性、颜色和材质)可以动态更改,但实际修改几何体的项目(如圆柱体高度)除外要求您删除基本体并重新计算几何体。您看到的闪烁是默认情况下启用异步基本体创建的结果。有两种方法可以满足您的需要
[options.asynchronous:false
到基元
构造函数。这意味着当您添加新基元时,铯在准备就绪之前不会渲染。对于一个或两个对象,您不会注意到任何东西。对于许多对象,它将锁定浏览器,直到一切就绪。这确实保证您可以删除旧的/添加新的p没有任何闪烁的原语\u state
属性(我以为这是公共API的一部分,但显然不是)。当\u状态
等于铯基元状态。完成
时,您可以安全地删除旧基元,并保证新基元将呈现(因此不会闪烁)\u state
在可预见的将来应该是可以的。如果我们很快添加一个官方方法,我将更新这个问题
希望有帮助
编辑:由于请求了更多帮助,下面是一个完整的示例。您可以使用将以下代码复制并粘贴到Sandcastle中
基本上,它使用scene.preRender事件而不是超时(在这里,preRender几乎总是更好的答案)。此外,如果在旧更新完成处理之前收到新更新,则在计算新更新之前删除该更新非常重要。如果仍有问题,请告诉我
require(['Cesium'], function(Cesium) {
"use strict";
var widget = new Cesium.CesiumWidget('cesiumContainer');
var ellipsoid = widget.scene.globe.ellipsoid;
var lon = 0;
var lat = 0;
var cylinderradius = 30000;
var length = 10000000;
var cylinderslices = 32;
var newPrimitive;
var currentPrimitive;
//This function creates a new cylinder that is half the length of the old one.
function decreaseLength() {
//If there's a pending primitive already, remove it.
if(Cesium.defined(newPrimitive)){
widget.scene.primitives.remove(newPrimitive);
}
length /= 2;
var cylinderGeometry = new Cesium.CylinderGeometry({
length : length,
topRadius : cylinderradius,
bottomRadius : cylinderradius,
slices: cylinderslices,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
});
var cylinder = new Cesium.GeometryInstance({
geometry: cylinderGeometry,
modelMatrix: Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(lon, lat))),
new Cesium.Cartesian3(0.0, 0.0, length * 0.5)),
attributes: {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
},
id: "Cylinder1"
});
newPrimitive = new Cesium.Primitive({
geometryInstances : cylinder ,
appearance : new Cesium.PerInstanceColorAppearance({
closed : false,
translucent: true,
flat: false,
faceForward: true
}),
allow3DOnly: true,
vertexCacheOptimize: true,
allowPicking: true,
releaseGeometryInstances: false
});
//We add the new cylinder immediately, but don't remove the old one yet.
widget.scene.primitives.add(newPrimitive);
}
//Create the initial cylinder.
decreaseLength();
//Subscribe to the preRender event so we can check the primitive every frame.
widget.scene.preRender.addEventListener(function(scene, time) {
//Remove the old cylinder once the new one is ready.
if(Cesium.defined(newPrimitive) && newPrimitive._state === Cesium.PrimitiveState.COMPLETE){
if(Cesium.defined(currentPrimitive)){
widget.scene.primitives.remove(currentPrimitive);
}
currentPrimitive = newPrimitive;
newPrimitive = undefined;
}
});
Sandcastle.addToolbarButton('Decrease Length', decreaseLength);
Sandcastle.finishedLoading();
});
感谢您的帮助,此时您的第二个选项看起来是最佳解决方案,我不希望我的其他操作因此而停止。我有点难过,因为没有办法动态更改高度,但我想此解决方案是一个很好的替代方案!实现第二个选项效果很好,但成本很高■气缸停止移动的迭代次数(计时器每1.5秒改变一次高度)。我用我现在正在做的事情编辑了我的问题,你能看一下吗?没问题,我添加了一个完整的示例。我得到
未捕获的类型错误:无法读取未定义的属性“addEventListener”
。预渲染是否真的是新的/仅在Sandcastle中可用?
require(['Cesium'], function(Cesium) {
"use strict";
var widget = new Cesium.CesiumWidget('cesiumContainer');
var ellipsoid = widget.scene.globe.ellipsoid;
var lon = 0;
var lat = 0;
var cylinderradius = 30000;
var length = 10000000;
var cylinderslices = 32;
var newPrimitive;
var currentPrimitive;
//This function creates a new cylinder that is half the length of the old one.
function decreaseLength() {
//If there's a pending primitive already, remove it.
if(Cesium.defined(newPrimitive)){
widget.scene.primitives.remove(newPrimitive);
}
length /= 2;
var cylinderGeometry = new Cesium.CylinderGeometry({
length : length,
topRadius : cylinderradius,
bottomRadius : cylinderradius,
slices: cylinderslices,
vertexFormat : Cesium.PerInstanceColorAppearance.VERTEX_FORMAT
});
var cylinder = new Cesium.GeometryInstance({
geometry: cylinderGeometry,
modelMatrix: Cesium.Matrix4.multiplyByTranslation(Cesium.Transforms.eastNorthUpToFixedFrame(ellipsoid.cartographicToCartesian(Cesium.Cartographic.fromDegrees(lon, lat))),
new Cesium.Cartesian3(0.0, 0.0, length * 0.5)),
attributes: {
color : Cesium.ColorGeometryInstanceAttribute.fromColor(Cesium.Color.RED)
},
id: "Cylinder1"
});
newPrimitive = new Cesium.Primitive({
geometryInstances : cylinder ,
appearance : new Cesium.PerInstanceColorAppearance({
closed : false,
translucent: true,
flat: false,
faceForward: true
}),
allow3DOnly: true,
vertexCacheOptimize: true,
allowPicking: true,
releaseGeometryInstances: false
});
//We add the new cylinder immediately, but don't remove the old one yet.
widget.scene.primitives.add(newPrimitive);
}
//Create the initial cylinder.
decreaseLength();
//Subscribe to the preRender event so we can check the primitive every frame.
widget.scene.preRender.addEventListener(function(scene, time) {
//Remove the old cylinder once the new one is ready.
if(Cesium.defined(newPrimitive) && newPrimitive._state === Cesium.PrimitiveState.COMPLETE){
if(Cesium.defined(currentPrimitive)){
widget.scene.primitives.remove(currentPrimitive);
}
currentPrimitive = newPrimitive;
newPrimitive = undefined;
}
});
Sandcastle.addToolbarButton('Decrease Length', decreaseLength);
Sandcastle.finishedLoading();
});