Прокрутка холста, когда фигура, которую вы перемещаете, приближается к его краям - PullRequest
1 голос
/ 18 апреля 2010

Я разрабатываю программу для рисования на основе Python, Whyteboard . У меня есть инструменты, которые пользователь может создавать новые формы на холсте, такие как текст / изображения / прямоугольники / круги / многоугольники. У меня также есть инструмент «Выбор», который позволяет пользователям изменять эти фигуры - например, перемещать позицию фигуры, изменять ее размер или редактировать позиции точек многоугольника.

Я добавляю новую функцию, в которой перемещение или изменение размера точки около края холста автоматически прокручивает холст. Я думаю, что это хорошая идея с точки зрения удобства использования программы, и меня раздражает, когда другие программы не имеют этой функции.

Я добился хорошего прогресса в кодировании этого; ниже приведен код 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 этой точки, чтобы увидеть, находится ли она близко к краю.

Проблема, которую я имею, немного сложна для описания - в основном, если вы переместите фигуру влево и перестанете ее перемещать, если вы поместили фигуру в пределах 50 пикселей от холста, то в следующий раз чтобы переместить форму, код, который говорит: «Хорошо, эта форма близка к концу?» срабатывает, и холст прокручивается влево, даже если вы перемещаете фигуру вправо.

Кто-нибудь может подумать, как это остановить? Я создал видео на YouTube , чтобы продемонстрировать проблему. Примерно в 0:54 я перемещаю многоугольник слева от холста и размещаю его там. В следующий раз, когда я переместлю его, холст прокручивается влево, хотя я и перемещаю его вправо

Еще одна вещь, которую я хотел бы добавить, но я застрял на том, набирает ли скорость прокрутка, чем дольше прокручивается фигура? Таким образом, с большим холстом вы не перемещаете фигуру целую вечность, перемещаясь на 5 пикселей за раз, когда вам нужно преодолеть расстояние в 2000 пикселей. Есть предложения?

Спасибо всем - простите за супер длинный вопрос!

1 Ответ

1 голос
/ 18 апреля 2010

Это может звучать немного из башни из слоновой кости, я надеюсь, что нет ... Если вы будете основывать свой алгоритм не на позиции, а на векторе, то вы можете заметить, в каком направлении перемещается объект. Ваш код запускается, как только две позиции (из которых вы можете сформировать вектор) доступны. Тогда вы сможете выяснить, движется ли пользователь к краю или от него

Еще немного о векторе:

Поскольку у вас есть система координат x, y, вы можете разбить такой вектор на части x, y. Возьмем любые две точки (x1, y1) и (x2, y2), тогда вы можете представить вектор как линию, соединяющую две точки. Эта линия и, например, ось х образует угол, который говорит вам, в каком направлении указывает эта линия. В вашем случае вам не помешает сравнить x2 и x1. Если х2 больше, то пользователь движется вправо. Если у2 больше, чем у1, он движется к вершине и аналогичные сравнения для других направлений ...

...