// Change the eye and center through moveCamera to move the scene perspective to the front view of the building
moveCamera (g3d, [134, 399, 1617], [7, 40, 144 ], {
duration: 2000 , easing: t => t * t , finishFunc: () => { // Turn on the transparency of the scene building model as true this.building.eachChild (c => {cs ({'shape3d.transparent': true ,});}); // Building model Wireframe color change tweenColor ( this.building, 'wf.color', 'rgba (72,149,232,1)', 'rgba (56,156,255,0.03)' , {duration: 2000 , easing: t => t}); / / The color change of the overall dyeing of the building model tweenColor ( this.building, 'shape3d.blend', 'rgba (120,180,255,1)', 'rgba (120,180,255,0)', { duration: 2000, easing: t => t, finishFunc: () => { // floor is set to be visible this.floor.eachChild (c => {setNodeVisible (c, true );}); this.floorLighting = 1 ; // display Animation of building construction information this .showBuilding ();}});}});
- node: a primitive node that changes color;
- startColor: rgba value of the start color;
- endColor: rgba value of the changed color;
- animParams: transition animation parameters;
tweenColor(node, property, startColor, endColor, animParams) {
animParams = animParams || {};
if (!animParams.frames && !animParams.duration)
animParams.duration = 5000;
if (!animParams.easing) animParams.easing = t => t; startColor = ht.Default.toColorData(startColor); endColor = ht.Default.toColorData(endColor); const dx = endColor[0] - startColor[0]; const dy = endColor[1] - startColor[1]; const dz = endColor[2] - startColor[2]; const da = endColor[3] - startColor[3]; const postAction = animParams.postAction; animParams.action = (v, t) => { const x = startColor[0] + v * dx; const y = startColor[1] + v * dy; const z = startColor[2] + v * dz; const a = (startColor[3] + v * da) / 255; node.s(property, ('rgba(' + ([x, y, z, a]).join(', ')) + ')'); if (postAction) postAction(('rgba(' + ([x, y, z, a]).join(', ')) + ')'); } return ht.Default.startAnim(animParams); }
// 面板显示
showPanel(data) {
ht.Default.startAnim({
duration: 1000,
easing: t => t,
action: (v,t) => { data.setScaleX(data.getScaleX() + (1 - data.getScaleX()) * v); } }); } // 面板隐藏 hidePanel(data) { ht.Default.startAnim({ duration: 1000, easing: t => t, action: (v,t) => { data.setScaleX(data.getScaleX() + (0 - data.getScaleX()) * v); } }); }
elevatorAnimation (data) {
const g3d = this .g3d;
const tag = data.getTag (); const e = data.getElevation (); const label = data.getChildAt (0 ); // determine the floor where it is now let now = Math.ceil (e / 50 ); // The next floor takes 1 ~ 7 random number let next = randomNumber (1, 7 ); // According to the current floor and the next floor, judge the range of elevator operation let range = numBetween (now, next); this.animationElevatorMap [tag] = ht.Default.startAnim ({duration: range * 800 , easing: t => t, action: (v, t) => { // Elevator running position setting Define data.setElevation (now <next? (E + (range * 50) * v): (e-(range * 50) *v)); // Set the elevator floor panel display and set according to the elevator position if (! label) return ; const floor = Math.ceil (data.getElevation () / 50 ); if (floor === label.a ( 'text')) return ; label.a ('text' , floor); // Manually refresh the elevator panel information g3d.invalidateShape3dCachedImage (label);}, finishFunc: () => { // Destroy the elevator interval animation delete this . timeoutElevatorMap [tag]; // Call back the elevator running animation after performing the elevator interval animation this.timeoutElevatorMap [tag] = setTimeout (() => { this .elevatorAnimation1 (data);}, Math.floor (Math.random () * 5000 ) + 2000 );}});}
park(car, key = 'Path', finishFunc) {
const dm = car.dm();
const tag = car.getTag();
const forwardPath = dm.getDataByTag(tag + '_forward' + key);
const backwardPath = dm.getDataByTag(tag + '_backward' + key);
this.animationMap[tag] = move(car, forwardPath, 'forward', undefined, 24, { pathEndFunc: () => { this.animationMap[tag].stop(); this.animationMap[tag] = move(car, backwardPath, 'backward', undefined, undefined, { pathEndFunc: () => { this.animationMap[tag].stop(); delete this.animationMap[tag]; if (finishFunc) finishFunc(); return true; } }); return true; } }); }
move is a encapsulation function for nodes to move smoothly along the path. The main parameters are:
- node: animation node;
- path: running path;
- direction: The node is forward | backward;
- animParams: animation parameters;
By drawing a pipeline that runs a route, ht.Default.getLineCacheInfo () gets the location and segmentation information cache of this pipeline, and then the pipeline information gets the length of the pipeline through ht.Default.getLineLength (), and through ht.Default.getLineOffset () To obtain the offset information of the specified proportion of the connection or pipeline to achieve the effect of movement. Note that direction is also set here to specify the direction of the animation node, mainly to obtain the node through node.lookAtX () Position information of the next facing direction, and set the position of the node at this time, so as to achieve the effect of smooth movement of the node along the path.
move(node, path, direction, step = 6, interval = 75, animParams) {
let cache = path.__cache__;
if (!cache) cache = path.__cache__ = ht.Default.getLineCacheInfo(path.getPoints(), path.getSegments());
const len = ht.Default.getLineLength(cache); animParams = animParams || {}; const face = direction === 'forward' ? 'front' : direction === 'backward' ? 'back' : direction; let currentLen = 0; const pathEndFunc = animParams.pathEndFunc; const action = animParams.action; animParams.action = (v, t) => { if (currentLen >= len) { // 档 pathEndFunc 返回 true 是,认为是要结束动画,Do not execute the following file actionif (pathEndFunc && pathEndFunc()) return; } currentLen = currentLen % len; const offset = ht.Default.getLineOffset(cache, currentLen); const point = offset.point; node.lookAtX([point.x, node.getElevation(), point.z], face); node.p3(point.x, node.getElevation(), point.z); currentLen = currentLen + step; if (action) action(); }; return loop(animParams.action, interval); }
At the same time, we can also see that when the vehicle is driving to the parking space or leaving, the traffic lights above the parking space indicate the parking information of the parking space. The status of the parking space is set in real time according to the situation of the vehicle. And manually refresh the cache to achieve. The caching mechanism is crucial to the fluency of the overall scene. For some panel information that does not need to be refreshed in real time, we can use the cache method, and call Graph3dView.invalidateShape3dCachedImage (node) to manually refresh this node when the next update , Which greatly improves the performance of the scene. For the properties of the 3D panel, please refer to <HT 3D manual billboard bulletin board> .
updateLight(view, light, color) {
light.s('shape3d.image', 'symbols/parking/' + color + 'Light.json');
view.invalidateShape3dCachedImage(light);
}