如何用ManimCE实现正弦波从屏幕左上角进入并向中间移动?
问题分析
你的代码中,sine_function添加了更新器update_wave,每次更新时都会调用get_sine_wave生成全新的FunctionGraph对象,而新生成的FunctionGraph默认锚点在屏幕中心,之前执行的shift(2*LEFT+UP)会被完全覆盖,所以不管怎么初始移动,动画过程中图形都会回到中心。
解决方案
下面提供两种可行的修改方式:
方案一:在更新时同步控制位置
修改update_wave函数,每次生成新正弦波后,根据进度同步调整位置,实现从左上角到中心的平滑移动:
from manim import * import numpy as np class SineWave(Scene): def get_sine_wave(self, dx=0): return FunctionGraph( lambda x: np.sin(4*x + dx), x_range=[-2, 2] ) def construct(self): # 初始位置:左上角区域 start_pos = 3*LEFT + 2*UP # 目标位置:屏幕中心 target_pos = ORIGIN sine_function = self.get_sine_wave() d_theta = ValueTracker(0) # 用ValueTracker控制位置过渡进度(0到1) pos_tracker = ValueTracker(0) def update_wave(func): # 生成新的正弦波 new_wave = self.get_sine_wave(dx=d_theta.get_value()) # 根据进度计算当前位置,从起始点过渡到中心 current_pos = start_pos + pos_tracker.get_value()*(target_pos - start_pos) new_wave.move_to(current_pos) func.become(new_wave) return func sine_function.add_updater(update_wave) # 初始移动到起始位置 sine_function.move_to(start_pos) self.add(sine_function) self.play(Create(sine_function)) # 同时播放波形滚动和位置移动动画 self.play( d_theta.animate.increment_value(4 * PI), pos_tracker.animate.set_value(1), rate_func=linear, run_time=3 ) self.wait()
方案二:修改正弦波生成逻辑,预设位置
让get_sine_wave生成时直接基于指定位置,避免每次更新后重置到中心:
from manim import * import numpy as np class SineWave(Scene): def get_sine_wave(self, dx=0, position=ORIGIN): wave = FunctionGraph( lambda x: np.sin(4*x + dx), x_range=[-2, 2] ) # 生成后直接定位到指定位置 wave.move_to(position) return wave def construct(self): start_pos = 3*LEFT + 2*UP target_pos = ORIGIN sine_function = self.get_sine_wave(position=start_pos) d_theta = ValueTracker(0) pos_tracker = ValueTracker(0) def update_wave(func): current_pos = start_pos + pos_tracker.get_value()*(target_pos - start_pos) func.become( self.get_sine_wave(dx=d_theta.get_value(), position=current_pos) ) return func sine_function.add_updater(update_wave) self.add(sine_function) self.play(Create(sine_function)) self.play( d_theta.animate.increment_value(4 * PI), pos_tracker.animate.set_value(1), rate_func=linear, run_time=3 ) self.wait()
关键说明
- 你可以调整
start_pos的数值,精准控制波形初始进入屏幕的左上角位置。 - 如果不需要平滑移动,也可以拆分动画:先播放波形从左上角移入的位置动画,再播放波形滚动动画。
内容的提问来源于stack exchange,提问作者Austin
相关产品推荐
相关产品推荐

