Взаимодействие с мышью для перетаскивания точек данных в Vega - PullRequest
0 голосов
/ 07 декабря 2018

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

{
  "$schema": "https://vega.github.io/schema/vega/v4.json",
  "width": 500,
  "height": 200,
  "autosize": "none",

  "signals": [
   {
      "name": "movePoint",
      "on": [
        {
          "events": "[mousedown, mouseup] > mousemove",
          "update": "{u: round(100*invert('xscale', x()))/100, v: round(100*invert('yscale', y()))/100}"
        }
      ]
    }
  ],

  "data": [
    {
      "name": "table",
      "values": [
        {"u": 0.1, "v": 0.1},
        {"u": 0.9, "v": 0.1},
        {"u": 0.1, "v": 0.9},
        {"u": 0.9, "v": 0.9},
        {"u": 0.5, "v": 0.5}
      ],
      "on": [
        {"trigger": "movePoint", "modify": "movePoint", "values": "{u: movePoint.u, v: movePoint.v}"}
      ]
    }
  ],

  "scales": [
    {
      "name": "xscale",
      "domain": [0, 1],
      "range": "width"
    },
    {
      "name": "yscale",
      "domain": [0, 1],
      "range": "height"
    }
  ],

  "marks": [
    {
      "name": "points",
      "type": "symbol",
      "zindex": 1,
      "from": {"data": "table"},
      "interactive": false,
      "encode": {
        "enter": {
          "fill": {"value": "black"},
          "size": {"value": 36},
          "x": {"scale": "xscale", "field": "u"},
          "y": {"scale": "yscale", "field": "v"}
        }
      }
    },
    {
      "type": "path",
      "from": {"data": "points"},
      "encode": {
        "enter": {
          "stroke": {"value": "firebrick"},
          "fill": {"value": "transparent"}
        }
      },
      "transform": [
        {
          "type": "voronoi",
          "x": "datum.x", "y": "datum.y",
          "size": [{"signal": "width"}, {"signal": "height"}]
        }
      ]
    }
  ]
}

Кажется, что сигнал уже работает хорошо.Я протестировал его, используя режим отладки Vega, и он, кажется, работает следующим образом:

  • сигнал изменяется только тогда, когда движение мыши происходит во время нажатия мыши
  • значения сигнала находятся вправильная система координат, используемая данными, то есть координаты между 0 и 1

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

1 Ответ

0 голосов
/ 11 декабря 2018

Я узнал, как сделать это для себя.Проблема состояла в том, что сигнал, который я использовал, вычисляет правильные новые координаты, но он не содержит ID объекта, который перетаскивается.Мне было проще всего добавить отдельный сигнал для этого.Таким образом, вместо одного сигнала «MovePoint» у нас теперь есть «NewPointPosition» (тот же сигнал, новое имя) и «WhichPoint», который содержит идентификатор перетаскиваемого объекта.Возможно, это можно объединить в один сигнал, но, возможно, это проще понять следующим образом.

Еще один важный момент, который отсутствовал в моей первой версии, заключался в том, что метки «точки» и «пути» нуждаются в «обновлении».пункт в «кодировать», а не просто «ввести».В противном случае данные изменятся, но визуализация не будет реагировать на это.

Рабочий код выглядит следующим образом:

    {
  "$schema": "https://vega.github.io/schema/vega/v4.json",
  "width": 500,
  "height": 200,
  "autosize": "none",

  "signals": [
   {
      "name": "whichPoint",
      "on": [
        {
          "events": "path:click, path:mousemove[event.buttons]{20}",
          "update": "datum.datum"
        }
      ]
    },
   {
      "name": "newPointPosition",
      "on": [
        {
          "events": "path:click, path:mousemove[event.buttons]{20}",
          "update": "{u: invert('xscale', x()), v: invert('yscale', y())}"
        }
      ]
    }
  ],

  "data": [
    {
      "name": "table",
      "values": [
        {"u": 0.1, "v": 0.1},
        {"u": 0.9, "v": 0.1},
        {"u": 0.1, "v": 0.9},
        {"u": 0.9, "v": 0.9},
        {"u": 0.5, "v": 0.5}
      ],
      "on": [
        {"trigger": "whichPoint", "modify": "whichPoint", "values": "{u: newPointPosition.u, v:newPointPosition.v}"}
      ]
    }
  ],

  "scales": [
    {
      "name": "xscale",
      "domain": [0, 1],
      "range": "width"
    },
    {
      "name": "yscale",
      "domain": [0, 1],
      "range": "height"
    }
  ],

  "marks": [
    {
      "name": "points",
      "type": "symbol",
      "zindex": 1,
      "from": {"data": "table"},
      "encode": {
        "enter": {
          "fill": {"value": "black"},
          "size": {"value": 36},
          "x": {"scale": "xscale", "field": "u"},
          "y": {"scale": "yscale", "field": "v"}
        },
        "update": {
          "fill": {"value": "black"},
          "size": {"value": 36},
          "x": {"scale": "xscale", "field": "u"},
          "y": {"scale": "yscale", "field": "v"}
        }
      }
    },
    {
      "type": "path",
      "from": {"data": "points"},
      "encode": {
        "enter": {
          "stroke": {"value": "firebrick"},
          "fill": {"value": "transparent"}
        },
        "update": {
          "stroke": {"value": "firebrick"},
          "fill": {"value": "transparent"}
        }
      },
      "transform": [
        {
          "type": "voronoi",
          "x": "datum.x", "y": "datum.y",
          "size": [{"signal": "width"}, {"signal": "height"}]
        }
      ]
    }
  ]
}
...