楼层动画
要求:
- 楼层数据的展示
- 楼层动画,当选中一个楼层时:
- 如果楼层没有展开,那么高于这个楼层的要自动展开
- 如果楼层已经展开了,那么当前楼层和小于该楼层的要自动闭合
楼层效果
这个没有要多说的,不同的楼层设置图形为不同的海拔即可,这里我使用的threelayer,直接贴代码了
WARNING
为了方便做楼层悬浮动画,我把楼层的原始海拔值用_altitude
记录,这个值不会随着更新图形的海拔值而改变的,如果直接用图形的 altitude
因为这个值随动画不断的变化,在使用起来比较复杂,容易出错
因为同一个楼层房间的边框线一般不用交互纯展示效果,我们可以使用toLines
来批量展示,这样可以有更好的性能的
js
function addFloors(buildingGeoJSON, roomGeoJSON) {
const floorGeoJSON = buildingGeoJSON.features[0];
let baseObjects = [];
for (let i = 1; i <= floorCount; i++) {
const altitude = (i - 1) * floorHeight;
const floor = threeLayer.toExtrudePolygon(
floorGeoJSON,
{
height: 0.5,
topColor: "#fff",
altitude,
_altitude: altitude, //原始的海拔
},
material,
);
baseObjects.push(floor);
const rooms = roomGeoJSON.features.map((f) => {
return threeLayer.toExtrudePolygon(
f,
{
height: roomHeight,
topColor: "#fff",
altitude,
_altitude: altitude,
},
material1,
);
});
baseObjects = baseObjects.concat(rooms);
const lines = roomGeoJSON.features.map((f) => {
return new maptalks.LineString(f.geometry.coordinates[0]);
});
const border = threeLayer.toLines(
lines,
{
topColor: "#fff",
altitude: altitude + roomHeight,
_altitude: altitude + roomHeight,
},
borderMaterial,
);
baseObjects.push(border);
floorCache[i] = {
floorNum: i,
open: false,
floors: [floor],
altitude,
rooms,
borders: [border],
};
}
threeLayer.addMesh(baseObjects);
}
楼层悬浮状态判断
楼层动画,当选中一个楼层时:
- 如果楼层没有展开,那么高于这个楼层的要自动展开
- 如果楼层已经展开了,那么当前楼层和小于该楼层的要自动闭合
楼层状态数据了我们添加
open
字段来记录当前楼层的展开状态,当选中一个楼层时根据这个状态值来判断楼层时需要展开还是闭合楼层究竟是展开还是闭合和快关一样,
open=true/false
而已楼层从展开->闭合时其自身也要加入更新海拔的数据列表中
js
function selectChange(e) {
const selectFloor = parseInt(e.target.value);
const floorItem = floorCache[selectFloor];
if (!floorItem) {
return;
}
const open = floorItem.open;
const isDown = open;
const needsUpdateFloors = [];
if (isDown) {
floorItem.open = false;
needsUpdateFloors.push(floorItem);
}
for (const key in floorCache) {
const floorItem = floorCache[key];
const { floorNum, open } = floorItem;
if (isDown) {
//小于选中楼层并且是打开状态
if (floorNum < selectFloor && open) {
needsUpdateFloors.push(floorItem);
floorItem.open = false;
}
} else {
//大于选中楼层并且是关闭状态
if (floorNum > selectFloor && !open) {
needsUpdateFloors.push(floorItem);
floorItem.open = true;
}
}
}
const allMeshes = getAllMeshes(needsUpdateFloors);
allMeshes.forEach((mesh) => {
//记录当前图形的实时海拔
mesh.options._altitude = mesh.options.altitude;
});
animationFloor(allMeshes, isDown);
}
楼层这个动画
这里直接使用maptalks自带的animate()
函数即可,关于animate()
的使用,请参阅 高级/动画
章节
js
function animationFloor(allMeshes, isDown) {
if (player) {
player.finish();
}
const update = (alitutde) => {
allMeshes.forEach((mesh) => {
const _altitude = mesh.options._altitude;
mesh.setAltitude(_altitude + alitutde);
});
};
var targetStyles = {
symbol: {
alitutde: offsetHeight,
},
};
// animate by maptalks.animation.Animation
player = maptalks.animate(
targetStyles,
{
duration: 1000,
easing: "out",
repeat: false,
},
// callback of each frame
function step(frame) {
let alitutde = frame.symbol.alitutde;
if (isDown) {
alitutde = -alitutde;
}
update(alitutde);
},
);
player.play();
}