You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 12:37:16