xieziyu / ngx-echarts

An angular (ver >= 2.x) directive for ECharts (ver >= 3.x)
https://xieziyu.github.io/ngx-echarts/
MIT License
1.1k stars 195 forks source link

Series Type Custom - access data source in calling component #166

Closed lbe closed 5 years ago

lbe commented 5 years ago

NOTE: This problem is solved by implementing the renderItem callback as a closure and lexically defining a copy of the data needed needed within the renderItem function within the closure lbe - 2019/01/18

I apologize in advance if I am missing something in newness to Angular.

I am using eCharts to draw a diagram much as you would on HTML5 Canvas. My reason for using eCharts is that is result needs to be scaled with other line charts that appear in the same frame.

I have created working model in pure javascript in the REPL on the eCharts demo site. It is based off the demo chart "Custom Cartesian Polygon". As in the example, I define a variable data using var data = []. In the REPL, the variable data is global and is accessible in the for loop beginning on line 19.

I have built out an angular app.component.ts that attempts to match my javascript version. In it, everything works fine until eCharts calls the renderItem callback. Since the process is outside of the scope of app.component, it cannot see my custom data. Is there a pattern in ngx-echarts and/or angular that I should be using to handle this?

FYI, I am familiar with the more out of the box option of using api.value(n) to access data values. This only works for numeric values. My data element is an Object that I parse to create a polygon graphic.

Thanks in advance for your help!

lbe

xieziyu commented 5 years ago

@lbe I think you can write a service to provide your custom data and inject it into your app component.

lbe commented 5 years ago

@xieziyu I gave the service a try but ran into the same scoping problem.

I was able to get around the scope problem by creating an enclosure.

createRenderItem() { // function to create the closure
    const d = this.d; //this.d is where my data exists
    const echarts = this.echarts;
    return function (params, api) {
      const dCur = d.renderData[params.seriesId][params.dataIndex];
      return {
        type: 'polygon',
        ...
        shape: {
           points: completeset
         }
      },
      ...
  }
}

public loadChart() {
  const rederItem = this.createRenderItem(); // the closure
  this.options = {
    ...
    series: [
      ...
      {
        name: 'Earth Model',
        id: 'EarthModel',
        data: this.d.renderData.EarthModel,
        type: 'custom',
        renderItem: renderItem // the closure in use
      },
      ...
  }
}   

Unfortunately, if I try to call echarts.graphic.clipPointsByRect in the shape definition, I receive the following error screen shot 2019-01-17 at 5 31 49 pm It appears that I now lose access to the echarts.* since I either can not or do not know how to do this.

I cannot share my specific project code and data since it is the property of one of my customers. I have created a gist with representative Angular code that produces the same result as my project code. To use this gist, start with ngx-echarts-starter. Add exampleData1.json to the assets directory. Replace the app.component html and ts files in ngx-echarts-starter and you should be able to get a succesful chart.

To get the error result, change the true to false at line 49 of the app.component.ts file.

Overall this approach should work, unless one needs to clip because of the use of DataZoom. In that case, they will need to write their own clipping function since echarts.* cannot be accessed.

Is there a way to preserve the access to echarts.*?

Is there a change that can be made to ngx-echarts to support the renderItem callback without needing to use a closure?

Thanks again for your response and assistance.

lbe

xieziyu commented 5 years ago

@lbe You should not access echarts.*. Instead, you can import them from echarts.

import { EChartOption, graphic } from 'echarts';

And then use graphic.clipPointsByRect directly in your methods.

lbe commented 5 years ago

@xieziyu

Thanks for the information on changing my import. To my current degree of testing, everything appears to work properly.

Thanks for your guidance!!

lbe