xieziyu/ngx-echarts

No coordinate system that supports convertToPixel found by the given finder >>> I can not drag the nodes of a graph

baarbaracrr opened this issue · 4 comments

Hello, I am trying to create a graph and move the nodes of it, but I can not. So I leave my code here to see if you can help me.
The bug is the next:
image
And It fail in the line position: myChart.convertToPixel({ gridIndex: 0 }, [item.x, item.y]),

HTML:
<div echarts (chartInit)="onChartReady($event)" [options]="options" id="main" class="mapDiagram nodes">

TypeScript:

import { Component, OnDestroy } from '@angular/core';
import { EChartsOption } from 'echarts';
import * as util from 'zrender/lib/core/util';

const SymbolSize = 50;
const Data =  [
  {
    name: 'Node 1',
    x: 300,
    y: 300
  },
  {
    name: 'Node 2',
    x: 800,
    y: 300
  },
  {
    name: 'Node 3',
    x: 550,
    y: 100
  },
  {
    name: 'Node 4',
    x: 550,
    y: 500
  }
];
const Links = [
  {
    source: 0,
    target: 1,
    symbolSize: [5, 20],
    label: {
      show: true
    },
    lineStyle: {
      width: 5,
      curveness: 0.2
    }
  },
  {
    source: 'Node 2',
    target: 'Node 1',
    label: {
      show: true
    },
    lineStyle: {
      curveness: 0.2
    }
  },
  {
    source: 'Node 1',
    target: 'Node 3'
  },
  {
    source: 'Node 2',
    target: 'Node 3'
  },
  {
    source: 'Node 2',
    target: 'Node 4'
  },
  {
    source: 'Node 1',
    target: 'Node 4'
  }
];

@Component({
  selector: 'app-layout-graph',
  templateUrl: './layout-graph.component.html',
  styleUrls: ['./layout-graph.component.css']
})
export class LayoutGraphComponent implements OnDestroy {
  public updatePosition: () => void = () => {};
  public options: EChartsOption = {
    grid: {},
    series: [
      {
        id: 'a',
        type: 'graph',
        layout: 'none',
        roam: true,
        label: {
          show: true
        },
        edgeSymbol: ['circle', 'arrow'],
        edgeSymbolSize: [4, 10],
        edgeLabel: {
          fontSize: 20
        },
        lineStyle: {
          opacity: 0.9,
          width: 2,
          curveness: 0
        },
        symbolSize: SymbolSize,
        data: Data,
        links: Links
      },
    ],
  };

  constructor() {}

  ngOnDestroy(): void {
    if (this.updatePosition) {
      window.removeEventListener('resize', this.updatePosition);
    }
  }

  onChartReady(myChart: any) {
    const onPointDragging = function (dataIndex: any, position: any) {
      let node = myChart.convertFromPixel({ gridIndex: 0 }, position) as number[];
      Data[dataIndex].x = node[0];
      Data[dataIndex].y = node[1];

      // Update data
      myChart.setOption({
        series: [
          {
            id: 'a',
            data: Data,
          },
        ],
      });
    };

    const showTooltip = (dataIndex: any) => {
      myChart.dispatchAction({
        type: 'showTip',
        seriesIndex: 0,
        dataIndex,
      });
    };

    const hideTooltip = () => {
      myChart.dispatchAction({
        type: 'hideTip',
      });
    };

    const updatePosition = () => {
      myChart.setOption({
        graphic: util.map(Data, (item) => ({
          position: myChart.convertToPixel({ gridIndex: 0 }, item),
        })),
      });
    };

    window.addEventListener('resize', updatePosition);
    myChart.on('dataZoom', updatePosition);

    // save handler and remove it on destroy
    this.updatePosition = updatePosition;

    setTimeout(() => {
      myChart.setOption({
        graphic: util.map(Data, (item, dataIndex) => {
          return {
            type: 'circle',
            position: myChart.convertToPixel({ gridIndex: 0 }, [item.x, item.y]),
            shape: {
              cx: 0,
              cy: 0,
              r: SymbolSize / 2,
            },
            invisible: true,
            draggable: true,
            ondrag: function (dx: any, dy: number) {
              onPointDragging(dataIndex, [dx.offsetX, dx.offsetY]);
            },
            onmousemove: util.curry<(dataIndex: any) => void, number | undefined>(showTooltip, dataIndex),
            onmouseout: util.curry<(dataIndex: any) => void, number | undefined>(hideTooltip, dataIndex),
            z: 100,
          };
        }),
      });
    }, 0);
  }

}

Thanks in advance!

Please try to replace gridIndex: 0 with seriesId: 'a' or seriesIndex: 0

Please try to replace gridIndex: 0 with seriesId: 'a' or seriesIndex: 0

Hello! Thanks for your answer. I have tried with the two options that you have told me and there are nodes that do allow me to drag them and others that do not, I do not understand why.
And one question, is there a doc where convertToPixel and its properties (seriesIndex, etc) are explained?

Solved!

import { Component, OnDestroy } from '@angular/core';
import { EChartsOption } from 'echarts';
import * as util from 'zrender/lib/core/util';

const SymbolSize = 50;
const Data =  [
  {
    name: 'Node 1',
    x: 300,
    y: 300
  },
  {
    name: 'Node 2',
    x: 800,
    y: 300
  },
  {
    name: 'Node 3',
    x: 550,
    y: 100
  },
  {
    name: 'Node 4',
    x: 550,
    y: 500
  }
];
const Links = [
  {
    source: 'Node 1',
    target: 'Node 3'
  },
  {
    source: 'Node 2',
    target: 'Node 3'
  },
  {
    source: 'Node 2',
    target: 'Node 4'
  },
  {
    source: 'Node 1',
    target: 'Node 4'
  }
];

@Component({
  selector: 'app-layout-graph',
  templateUrl: './layout-graph.component.html',
  styleUrls: ['./layout-graph.component.css']
})
export class LayoutGraphComponent implements OnDestroy {
  public updatePosition: () => void = () => {};
  public options: EChartsOption = {
    series: [
      {
        id: 'a',
        type: 'graph',
        layout: 'none',
        label: {
          show: true
        },
        edgeLabel: {
          fontSize: 20
        },
        symbolSize: SymbolSize,
        data: Data,
        links: Links
      },
    ],
  };

  constructor() {}

  ngOnDestroy(): void {
    if (this.updatePosition) {
      window.removeEventListener('resize', this.updatePosition);
    }
  }

  onChartReady(myChart: any) {
    const onPointDragging = function (dataIndex: any, position: any) {
      let node = myChart.convertFromPixel({ seriesIndex: 0 }, position) as number[];
      Data[dataIndex].x = node[0];
      Data[dataIndex].y = node[1];

      // Update data
      myChart.setOption({
        series: [
          {
            id: 'a',
            data: Data,
          },
        ],
      });
    };

    const showTooltip = (dataIndex: any) => {
      myChart.dispatchAction({
        type: 'showTip',
        seriesIndex: 0,
        dataIndex,
      });
    };

    const hideTooltip = () => {
      myChart.dispatchAction({
        type: 'hideTip',
      });
    };

    const updatePosition = () => {
      myChart.setOption({
        graphic: util.map(Data, (item, dataIndex) => {
          return {
            type: 'circle',
            position: myChart.convertToPixel({ seriesIndex: 0 }, [item.x, item.y]),
            shape: {
              r: SymbolSize / 2,
            },
            invisible: true,
            draggable: true,
            z: 100,
            ondrag: function (data: any) {
              onPointDragging(dataIndex, [data.event.x, data.event.y]);
              updatePosition();
            },
            onmousemove: util.curry<(dataIndex: any) => void, number | undefined>(showTooltip, dataIndex),
            onmouseout: util.curry<(dataIndex: any) => void, number | undefined>(hideTooltip, dataIndex)
          };
        }),
      });
    };

    window.addEventListener('resize', updatePosition);
    myChart.on('dataZoom', updatePosition);

    // save handler and remove it on destroy
    this.updatePosition = updatePosition;

    setTimeout(() => {
      updatePosition();
    }, 0);
  }

}