(ctx, projection, flight, fps)
| 102 | } |
| 103 | |
| 104 | function drawFlight(ctx, projection, flight, fps) { |
| 105 | const base_speed = (10 + 0.001 * flight.total) * (60 / fps); |
| 106 | const progress = flight.progress / flight.total; |
| 107 | const ease_out = (0.8 < progress && progress < 1.0) ? (-20 * progress ** 2 + 32 * progress - 11.8) : 1.0; |
| 108 | flight.progress += base_speed * ease_out; |
| 109 | flight.tail_progrss += base_speed; |
| 110 | const gradient_start_position = shanghai_projected; |
| 111 | const flight_end_position = projection([flight.longitude, flight.latitude]); |
| 112 | |
| 113 | const gradient_1_progress = progress; |
| 114 | const gradient_1_position = [ |
| 115 | gradient_start_position[0] + (flight_end_position[0] - gradient_start_position[0]) * gradient_1_progress, |
| 116 | gradient_start_position[1] + (flight_end_position[1] - gradient_start_position[1]) * gradient_1_progress |
| 117 | ]; |
| 118 | const gradient_0_progress = flight.tail_progrss / flight.total; |
| 119 | const gradient_0_position = [ |
| 120 | gradient_start_position[0] + (flight_end_position[0] - gradient_start_position[0]) * gradient_0_progress, |
| 121 | gradient_start_position[1] + (flight_end_position[1] - gradient_start_position[1]) * gradient_0_progress |
| 122 | ]; |
| 123 | const linear_gradient = ctx.createLinearGradient(...gradient_0_position, ...gradient_1_position); |
| 124 | linear_gradient.addColorStop(0, "rgba(255, 172, 41, 0)"); |
| 125 | linear_gradient.addColorStop(1, "rgba(255, 172, 41, 1)"); |
| 126 | |
| 127 | // Create a mapping, [360, 0] => shanghai, [0, 0] => flight_end_position |
| 128 | const coord_x = [ |
| 129 | (gradient_start_position[0] - flight_end_position[0]) / 360, |
| 130 | (gradient_start_position[1] - flight_end_position[1]) / 360 |
| 131 | ]; |
| 132 | const coord_y = [-coord_x[1], coord_x[0]]; |
| 133 | |
| 134 | function get_position([x, y]) { |
| 135 | return [ |
| 136 | flight_end_position[0] + coord_x[0] * x + coord_y[0] * y, |
| 137 | flight_end_position[1] + coord_x[1] * x + coord_y[1] * y |
| 138 | ]; |
| 139 | } |
| 140 | |
| 141 | const control_point_1_coord = get_position([260, 40]); |
| 142 | const control_point_2_coord = get_position([100, 40]); |
| 143 | |
| 144 | function get_position_slope(t) { |
| 145 | const t_3_0 = (1 - t) ** 3; |
| 146 | const t_3_1 = 3 * (1 - t) ** 2 * t; |
| 147 | const t_3_2 = 3 * (1 - t) * t ** 2; |
| 148 | const t_3_3 = t ** 3; |
| 149 | const position = [ |
| 150 | t_3_0 * gradient_start_position[0] + t_3_1 * control_point_1_coord[0] + t_3_2 * control_point_2_coord[0] + t_3_3 * flight_end_position[0], |
| 151 | t_3_0 * gradient_start_position[1] + t_3_1 * control_point_1_coord[1] + t_3_2 * control_point_2_coord[1] + t_3_3 * flight_end_position[1] |
| 152 | ] |
| 153 | const t_2_0 = -3 * (1 - t) ** 2; |
| 154 | const t_2_1 = 3 * (1 - 4 * t + 3 * t ** 2); |
| 155 | const t_2_2 = 3 * (2 * t - 3 * t ** 2); |
| 156 | const t_2_3 = 3 * t ** 2; |
| 157 | const direction = Math.atan2( |
| 158 | -(t_2_0 * gradient_start_position[1] + t_2_1 * control_point_1_coord[1] + t_2_2 * control_point_2_coord[1] + t_2_3 * flight_end_position[1]), |
| 159 | -(t_2_0 * gradient_start_position[0] + t_2_1 * control_point_1_coord[0] + t_2_2 * control_point_2_coord[0] + t_2_3 * flight_end_position[0]) |
| 160 | ); |
| 161 | return [position, direction]; |
no test coverage detected