首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >画布显示最终的stroke_lines思想动画

画布显示最终的stroke_lines思想动画
EN

Stack Overflow用户
提问于 2022-01-09 06:03:58
回答 1查看 97关注 0票数 1

所以我在玩一些Bezier曲线的动画--只是学习如何使用ipy画布(0,10,2)的一部分--我制作的动画真的让我头疼。我希望看到的是在4个Bezier控制点之间的一组直线,随着Bezier曲线的移动,它们在画布上“弹跳”。

我确实得到了移动的Bezier曲线--但是控制点保持不变。更奇怪的是,他们在最后的位置上是静止的,而曲线则是为了与他们相遇。

有时候Python的结构和引用会变得有点棘手,所以如果你没有认真考虑的话,你有时会得到令人困惑的结果--这完全可能是正在发生的事情--但我很困惑。

因此,为了确保我没有感到困惑,我在开始时打印了控制点( at ),然后将它们显示在画布上。这证实了我的怀疑。通过量子隧穿或其他神奇的时间旅行,线canvas.stroke_lines(pts)到达未来,抓住pts阵列,因为它将存在于未来,并使控制点处于最终状态。

pts的其他每一种使用都使用当前的时态。

所以我需要知道的是,A)物理定律是安全的,我太笨了,无法理解我自己的代码。有一些奇怪的错误,我应该报告。( C)如何将这种时间旅行代码货币化--比如,我们能用它来计算大量的数字吗?

代码语言:javascript
复制
from ipycanvas import Canvas, hold_canvas
import numpy as np

def rgb_to_hex(rgb):
    if len(rgb) == 3:
        return '#%02x%02x%02x' % rgb
    elif len(rgb) == 4:
        return '#%02x%02x%02x%02x' % rgb

def Bezier4(t, pts):
    p = t**np.arange(0, 4,1)
    M=np.matrix([[0,0,0,1],[0,0,3,-3],[0,3,-6,3],[1,-3,3,-1]])
    return np.asarray((p*M*pts))

canvas = Canvas(width=800, height=800)
display(canvas) # display the canvas in the output cell..
pts = np.random.randint(50, 750, size=[4, 2])   #choose random starting point
print(pts) #print so we can compare with ending state
d =  np.random.uniform(-4,4,size=[4,2])  #some random velocity vectors
c = rgb_to_hex(tuple(np.random.randint(75, 255,size=3)))  #some random color
canvas.font = '16px serif'  #font for displaying the changing pts array
with hold_canvas(canvas):
    for ani in range(300):
        #logic to bounce the points about...
        for n in range(0,len(pts)):
            pts[n]=pts[n] + d[n]
            if pts[n][0] >= 800 or pts[n][0] <= 0 :
                d[n][0] = - d[n][0]
            if pts[n][1] >= 800 or pts[n][1] <= 0 :
                d[n][1] = - d[n][1]
        #calculate the points needed to display a bezier curve
        B = [(Bezier4(i, pts)).ravel() for i in np.linspace(0,1,15)]
        #begin display output....
        canvas.clear()
        #first draw bezier curve...
        canvas.stroke_style = c
        canvas.stroke_lines(B)
        
        #Now draw control points
        canvas.stroke_style = rgb_to_hex((255,255,128, 50))
        canvas.stroke_lines(pts)
        
        #print the control points to the canvas so we can see them move
        canvas.stroke_style = rgb_to_hex((255,255,128, 150))
        canvas.stroke_text(str(pts), 10, 32)
        
        canvas.sleep(20)

认真地说,我已经试着想清楚到底会发生什么事,现在我正处于空白状态。由于ipy画布正在与browser/javascript对话,所以可能首先呈现框架的所有数据,用于保存stroke_linesstroke_lines数据的数组最终得到最后的值.而B数组是在每个循环中重新创建的。只是猜测而已。

EN

回答 1

Stack Overflow用户

发布于 2022-01-09 07:47:02

有两种方法可以让代码像预期的那样运行,并避免那些难看的时间旅行代码。第一种方法是将行with hold_canvas(canvas):的位置切换到循环内。然而,这使得canvas.sleep(20)行变得相当无用。

代码语言:javascript
复制
canvas = Canvas(width=800, height=800)
display(canvas)
pts = np.random.randint(50, 750, size=[4, 2])
print(pts)
d =  np.random.uniform(-8,8,size=[4,2])
c = rgb_to_hex(tuple(np.random.randint(75, 255,size=3)))
canvas.font = '16px serif'
#with hold_canvas(canvas):
for ani in range(300):
    with hold_canvas(canvas):
        for n in range(0,len(pts)):
            if pts[n][0] > 800 or pts[n][0] < 0 :
                d[n][0] = -d[n][0]
            if pts[n][1] > 800 or pts[n][1] < 50 :
                d[n][1] = -d[n][1]
            pts[n]=pts[n] + d[n]

        B = [(Bezier4(i, pts)).ravel() for i in np.linspace(0,1,25)]
        canvas.clear()
        canvas.stroke_style = c
        canvas.stroke_lines(B)
        canvas.stroke_style = rgb_to_hex((255,255,128, 50))
        #pts2 = np.copy(pts)
        canvas.stroke_lines(pts)
        canvas.fill_style = rgb_to_hex((255,255,255, 150))
        canvas.fill_circles(pts.T[0], pts.T[1],np.array([4]*4))
        canvas.stroke_style = rgb_to_hex((255,255,128, 150))
        canvas.fill_text(str(pts), 10, 32)
        sleep(20/1000)
        #canvas.sleep(20)

在此版本中,控制线将按预期更新。这个版本有点“实时”,因此需要sleep(20/1000)

另一种方法是确保pts的副本被制作并传递给canvas.stroke_lines

代码语言:javascript
复制
canvas = Canvas(width=800, height=800)
display(canvas)
pts = np.random.randint(50, 750, size=[4, 2])
print(pts)
d =  np.random.uniform(-8,8,size=[4,2])
c = rgb_to_hex(tuple(np.random.randint(75, 255,size=3)))
canvas.font = '16px serif'
with hold_canvas(canvas):
    for ani in range(300):
    #with hold_canvas(canvas):
        for n in range(0,len(pts)):
            if pts[n][0] > 800 or pts[n][0] < 0:
                d[n][0] = -d[n][0]
            if pts[n][1] > 800 or pts[n][1] < 50:
                d[n][1] = -d[n][1]
            pts[n]=pts[n] + d[n]

        B = [(Bezier4(i, pts)).ravel() for i in np.linspace(0,1,35)]
        canvas.clear()
        canvas.stroke_style = c
        canvas.stroke_lines(B)
        canvas.stroke_style = rgb_to_hex((255,255,128, 50))
        pts2 = np.copy(pts)
        canvas.stroke_lines(pts2)
        canvas.fill_style = rgb_to_hex((255,255,255, 150))
        canvas.fill_circles(pts.T[0], pts.T[1],np.array([4]*4))
        canvas.stroke_style = rgb_to_hex((255,255,128, 150))
        canvas.fill_text(str(pts), 10, 32)
        #sleep(20/1000)
        canvas.sleep(20)

我实际上找不到在python和浏览器之间传递的数据,但似乎非常符合逻辑的是,python在发送要绘制什么的小部件说明之前正在完成它的工作(和ani循环),并且发送的pts值是最后的值。

(是的,我知道弹跳逻辑中有一个错误)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70638846

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档