将画布滚动为您正在移动的形状接近其边缘

时间:2010-04-18 14:05:11

标签: math wxpython canvas scroll

我开发了一个基于Python的绘图程序Whyteboard。我有工具,用户可以在画布上创建新的形状,如文本/图像/矩形/圆形/多边形。我还有一个Select工具,允许用户修改这些形状 - 例如,移动形状的位置,调整大小或编辑多边形的点位置。

我正在添加一个新功能,其中移动或调整画布边缘附近的点将自动滚动画布。我认为在程序可用性方面这是个好主意,当其他程序没有这个功能时,我会很烦。

我在编码方面取得了一些进展;下面是一些Python代码来演示我正在做的事情。这些函数演示了一些形状如何计算它们的“边缘”:

def find_edges(self):
    """A line."""
    self.edges = {EDGE_TOP: min(self.y, self.y2), EDGE_RIGHT: max(self.x, self.x2),
                  EDGE_BOTTOM: max(self.y, self.y2), EDGE_LEFT: min(self. x, self.x2)}


def find_edges(self):
   """An image"""
    self.edges = {EDGE_TOP: self.y, EDGE_RIGHT: self.x + self.image.GetWidth(),
                  EDGE_BOTTOM: self.y + self.image.GetWidth(), EDGE_LEFT: self.x}


def find_edges(self):
    """Get the bounding rectangle for the polygon"""
    xmin = min(x for x, y in self.points)
    ymin = min(y for x, y in self.points)
    xmax = max(x for x, y in self.points)
    ymax = max(y for x, y in self.points)
    self.edges = {EDGE_TOP: ymin, EDGE_RIGHT: xmax, EDGE_BOTTOM: ymax, EDGE_LEFT: xmin}

这是我到目前为止在形状接近边缘时实现滚动的代码:

def check_canvas_scroll(self, x, y, moving=False):
    """
    We check that the x/y coords are within 50px from the edge of the canvas
    and scroll the canvas accordingly. If the shape is being moved, we need
    to check specific edges of the shape (e.g. left/right side of rectangle)
    """

    size = self.board.GetClientSizeTuple()  # visible area of the canvas
    if not self.board.area > size:  # canvas is too small to need to scroll
        return

    start = self.board.GetViewStart()  # user's starting "viewport"
    scroll = (-1, -1)  # -1 means no change

    if moving:
        if self.shape.edges[EDGE_RIGHT] > start[0] + size[0] - 50:
            scroll = (start[0] + 5, -1)
        if self.shape.edges[EDGE_BOTTOM] > start[1] + size[1] - 50:
            scroll = (-1, start[1] + 5)
        # snip others

    else:
        if x > start[0] + size[0] - 50:
            scroll = (start[0] + 5, -1)
        if y > start[1] + size[1] - 50:
            scroll = (-1, start[1] + 5)
        # snip others

    self.board.Scroll(*scroll)

这段代码实际上效果很好。如果我们移动一个形状,那么我们需要知道它的边缘以计算它们何时接近画布边缘。如果我们只调整一个点的大小,那么我们只需使用该点的x / y坐标来查看它是否接近边缘。

我遇到的问题有点难以描述 - 基本上,如果你向左移动一个形状,并停止移动它,如果你将形状定位在离画布50px的范围内,那么下次你去移动形状,代码说“好吧,这个形状接近结束?”被触发,画布向左滚动,即使你将形状向右移动。

有谁能想到如何制止这个?我创建了一个youtube video来演示这个问题。在大约0:54,我将一个多边形移动到画布的左侧并将其定位在那里。下次我移动它时,即使我正在移动它,画布也会向左滚动

我想添加的另一件事,但我坚持认为滚动获得动力的形状滚动的时间越长?因此,对于大型画布,当你需要覆盖2000px的距离时,你不会移动多年的形状,一次移动5px。有什么建议吗?

谢谢大家 - 抱歉这个超长的问题!

1 个答案:

答案 0 :(得分:1)

这听起来有点像象牙塔,我希望不是...... 如果您的算法不是基于位置而是基于矢量,那么您可以注意到对象拖动的方向。一旦两个位置(可以形成向量)可用,您的代码就会启动。然后你应该能够弄清楚用户是朝向还是远离边缘

关于向量的更多内容:

由于您拥有x,y坐标系,因此可以将这样的矢量分解为x,y部分。取任意两点(x1,y1)和(x2,y2),然后你可以将矢量想象成连接两点的线。该行和例如x轴形成一个角度,告诉你该线指向的方向。在你的情况下,你会比较x2和x1。 x2更大,然后用户向右移动。 y2是否大于y1,它正在向顶部移动,而其他方向的类似比较......