<菜鸟> 2023-08-03 11:13 采纳率: 0%
浏览 7

angular中sortable.js和echarts的冲突

我遇到的问题是:使用sortable.js插件进行拖拽列表,列表里使用了echarts插件,多次拖拽同一个echarts会导致echarts内容丢失
使用的技术栈:angular12、sortableJs、echarts

这是我echarts的ts

import { AfterViewInit, Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core';
import { DemandService } from '../demand.service';
import * as echarts from 'echarts';
@Component({
 // eslint-disable-next-line @angular-eslint/component-selector
 selector: 'ori-echarts',
 templateUrl: './echarts.component.html',
 styleUrls: ['./echarts.component.less']
})
export class EchartsComponent implements OnInit, AfterViewInit {
 constructor(private ds: DemandService) { }
 @Input() options;
 @ViewChild('chartContainer') chartContainer!: ElementRef;
 chartInstance
 ngOnInit(): void {}
 ngAfterViewInit(): void {
   this.initEcahrts();

 }
 echartsInstanceIds = [];
 initEcahrts() {
   this.updateEcharts('init');
 }
 refreshEcharts() {
   this.updateEcharts('refresh');
 }

 updateEcharts(optionType: 'init'|'refresh') {
   const chartElement = document.createElement('div');
   chartElement.style.width = '100%';
   chartElement.style.height = '100%';
   chartElement.id = 'ec_' + new Date().getTime();
   if(optionType === 'refresh') {
     if (this.chartContainer.nativeElement.querySelector('div')) {
       this.chartContainer.nativeElement.querySelector('div').remove();
     }
   }
   this.chartContainer.nativeElement.appendChild(chartElement);
   this.chartInstance = echarts.init(chartElement);
   this.chartInstance.setOption(this.options);
   this.chartInstance.resize();
 }
}

这是我echarts的html

<div #chartContainer style="width: 100%; height: 100%;"></div>

我在拖拽文件里写了如下代码片段


addProxyBindingCopyDrag() {
    this.ds.proxySortableListDom = document.getElementById('proxy-sort-list');
    const that = this;
    const sortable = Sortable.create(this.ds.proxySortableListDom, {
      group: {
        name: 'proxyDrag',
        pull: 'clone',
        put: false
      },
      removeCloneOnHide: false,
      filter: '.has-dragged-item',
      animation: 150,
      sort: false,
      onStart: (evt) => {
        const index = evt.clone.getAttribute('index');
        this.dppChartComponent.refreshEcharts();
      },
      onEnd: (evt) => {
        const index = evt.clone.getAttribute('index');
        if (!that.ds.proxyList[index].dragged) {
          that.ds.proxyList[index].dragged = true;
        }
        this.dppChartComponent.refreshEcharts();
      }
    });
  }

结果第一次拖拽是好的

img

但到了第二次拖拽同一个图的时候

img

我本来以为是echarts的实例id相同的问题,但是现在的实现效果,每一次拖拽过来的echarts图实现了_echarts_instance_不同了,echarts还是会丢失

img

现在我不太清楚问题出在哪里了,请各位指点迷津!

  • 写回答

1条回答 默认 最新

  • CSDN-Ada助手 CSDN-AI 官方账号 2023-08-03 15:07
    关注

    【以下回答由 GPT 生成】

    分析

    根据提供的代码,我们可以看到问题出现在拖拽同一个echarts图表时丢失内容。主要原因是每次拖拽都在重新创建一个echarts实例,但是并没有销毁之前的实例,导致页面上存在多个实例,并且重复调用resize方法可能会出现问题。

    解决方案

    解决这个问题的关键在于正确创建和销毁echarts实例,并且避免重复调用resize方法。

    修改EchartsComponent组件

    首先,我们需要在EchartsComponent组件中添加一个销毁echarts实例的方法,并在组件销毁的时候调用该方法。

    import { OnDestroy } from '@angular/core';
    // ...
    
    export class EchartsComponent implements OnInit, AfterViewInit, OnDestroy {
    
      // ...
    
      ngOnDestroy(): void {
        this.destroyEcharts();
      }
    
      destroyEcharts() {
        if (this.chartInstance) {
          this.chartInstance.dispose();
          this.chartInstance = null;
        }
      }
    }
    

    修改拖拽文件中的代码

    在拖拽文件的代码中,我们需要修改refreshEcharts方法,当echarts实例存在时才调用resize方法。

    refreshEcharts() {
      if (this.dppChartComponent.chartInstance) {
        this.dppChartComponent.chartInstance.resize();
      }
    }
    

    修改initEcahrts方法

    原先的initEcahrts方法在每次重新渲染组件时都会调用,导致创建多个echarts实例。我们需要在创建echarts实例前判断是否已经存在实例,如果存在则直接调用setOption方法更新数据。

    initEcahrts() {
      if (!this.chartInstance) {
        this.createEcharts();
      } else {
        this.chartInstance.setOption(this.options);
        this.chartInstance.resize();
      }
    }
    
    createEcharts() {
      const chartElement = document.createElement('div');
      chartElement.style.width = '100%';
      chartElement.style.height = '100%';
      chartElement.id = 'ec_' + new Date().getTime();
    
      if (this.chartContainer.nativeElement.querySelector('div')) {
        this.chartContainer.nativeElement.querySelector('div').remove();
      }
    
      this.chartContainer.nativeElement.appendChild(chartElement);
      this.chartInstance = echarts.init(chartElement);
      this.chartInstance.setOption(this.options);
      this.chartInstance.resize();
    }
    

    完整代码

    import { AfterViewInit, Component, ElementRef, Input, OnDestroy, OnInit, ViewChild } from '@angular/core';
    import { DemandService } from '../demand.service';
    import * as echarts from 'echarts';
    
    @Component({
      selector: 'ori-echarts',
      templateUrl: './echarts.component.html',
      styleUrls: ['./echarts.component.less']
    })
    export class EchartsComponent implements OnInit, AfterViewInit, OnDestroy {
    
      constructor(private ds: DemandService) { }
    
      @Input() options;
      @ViewChild('chartContainer') chartContainer!: ElementRef;
      chartInstance;
    
      ngOnInit(): void {
      }
    
      ngAfterViewInit(): void {
        this.initEcahrts();
      }
    
      ngOnDestroy(): void {
        this.destroyEcharts();
      }
    
      echartsInstanceIds = [];
    
      initEcahrts() {
        if (!this.chartInstance) {
          this.createEcharts();
        } else {
          this.chartInstance.setOption(this.options);
          this.chartInstance.resize();
        }
      }
    
      createEcharts() {
        const chartElement = document.createElement('div');
        chartElement.style.width = '100%';
        chartElement.style.height = '100%';
        chartElement.id = 'ec_' + new Date().getTime();
    
        if (this.chartContainer.nativeElement.querySelector('div')) {
          this.chartContainer.nativeElement.querySelector('div').remove();
        }
    
        this.chartContainer.nativeElement.appendChild(chartElement);
        this.chartInstance = echarts.init(chartElement);
        this.chartInstance.setOption(this.options);
        this.chartInstance.resize();
      }
    
      destroyEcharts() {
        if (this.chartInstance) {
          this.chartInstance.dispose();
          this.chartInstance = null;
        }
      }
    
      refreshEcharts() {
        if (this.chartInstance) {
          this.chartInstance.resize();
        }
      }
    }
    

    总结

    通过以上修改,我们解决了在拖拽同一个echarts图表时导致内容丢失的问题。主要是通过正确创建和销毁echarts实例,并避免重复调用resize方法来解决冲突。希望对你有所帮助!


    如果你已经解决了该问题, 非常希望你能够分享一下解决方案, 写成博客, 将相关链接放在评论区, 以帮助更多的人 ^-^
    评论

报告相同问题?

问题事件

  • 创建了问题 8月3日

悬赏问题

  • ¥15 做一个简单项目,用Python分析共享单车的数据
  • ¥20 在使用CESM2.2.0模型进行case.submit过程中出现如下错误(关键词-Map)
  • ¥15 有办法改变通过wifi进入的网站的设置吗
  • ¥15 所以到底怎么算!算到凌晨五点都算不出来!
  • ¥15 label_studio
  • ¥15 请教如何phython发邮件
  • ¥15 linux系统安装问题
  • ¥15 路径规划如何采用矢量法让他们尽量在一个方向
  • ¥15 crypto 一道rsa解密题
  • ¥15 survIDINRI已将生存时间转为数值变量,仍错误 Time variable is not numeric。