Задать вопрос
@frontAng

Как расставить значения по оси x на канвасе?

проблема в функции XaxiosDrawing
https://stackblitz.com/edit/angular-8-getting-star...
  • Вопрос задан
  • 83 просмотра
Подписаться 1 Простой 7 комментариев
Решения вопроса 1
twobomb
@twobomb
Вообщем всё плохо, пришлось переписать
import {
  AfterViewInit,
  Component,
  ElementRef,
  Input,
  OnInit,
  ViewChild,
} from '@angular/core';

@Component({
  selector: 'app-line-chart',
  templateUrl: './line-chart.component.html',
  styleUrls: ['./line-chart.component.css'],
})
export class ProductListComponent {
  @ViewChild('elemCanvas') canvasValue: ElementRef | undefined;
  @Input() color: string = '';
  @Input() data: any = [];
  width: number = 600;
  height: number = 200;
  padding: number = 40;
  dpi_width: number = this.width * 2;
  dpi_height: number = this.height * 2;
  view_height: number = this.dpi_height - this.padding * 2;
  view_width: number = this.dpi_width- this.padding * 2;
  rows_count: number = 5;
  ymin: number = 0;
  ymax: number = 0;
  xmin: number = 0;
  xmax: number = 0;
  value: any = 0;
  yRatio: number = 0;
  xRatio: number = 0;
  DEBUG_MODE = true;//ПОСТАВИТЬ false чтобы убрать границы и значения

  constructor() {
    window.addEventListener('resize', () => {
      this.chart();
    });
  }

  ngOnInit() {
    this.value = [this.ymin, this.ymax,this.xmin, this.xmax] = this.computeBoundaries(this.data);
    this.yRatio = this.view_height / (this.ymax - this.ymin);
    this.xRatio = this.view_width / (this.xmax - this.xmin);
  }

  ngAfterViewInit() {
    this.chart();
  }

  chart(): void {
    const elem = (this.canvasValue?.nativeElement as HTMLCanvasElement) || null;
    if (elem) {
      this.initChart(elem);
      const ctx = elem.getContext('2d');
      if (ctx) {
        this.YaxiosDrawing(ctx);
        this.XaxiosDrawing(ctx);
        this.lineDrawing(ctx);
        if(this.DEBUG_MODE)
          this.innerBorder(ctx);
      }
    }
  }

  initChart(elem: any): void {
    this.width = this.canvasValue?.nativeElement.offsetWidth;
    this.dpi_width = this.width * 2;
    elem.width = this.dpi_width;
    elem.height = this.dpi_height;
  }
  innerBorder(ctx: any): void {    
    ctx.beginPath();
    ctx.strokeStyle = 'red';
    ctx.moveTo(this.padding,this.padding);
    ctx.lineTo(this.padding + this.view_width, this.padding);    
    ctx.lineTo(this.padding + this.view_width, this.padding + this.view_height);
    ctx.lineTo(this.padding , this.padding + this.view_height);
    ctx.closePath();
    ctx.stroke();
  }
  YaxiosDrawing(ctx: any): void {    
    const step = this.view_height / (this.rows_count - 1); //отступ между каждой линией    
    const textStep = (this.ymax - this.ymin) / (this.rows_count - 1);
    ctx.beginPath();
    ctx.strokeStyle = '#bbb';
    ctx.font = 'normal 20px Helvetica, sans-serif';    
    ctx.fillStyle = '#96a2aa';
    for (let i = 0; i <= this.rows_count; i++) {
      const y = step * i;      
      const text = this.ymin + Math.round(textStep * i);
      ctx.fillText(text.toString(), 5, this.view_height + this.padding - y);
      ctx.moveTo(0, this.view_height + this.padding - y);
      ctx.lineTo(this.dpi_width, this.view_height + this.padding - y);
    }
    ctx.stroke();
    ctx.closePath();
  }

  XaxiosDrawing(ctx: any): void {   
     const step = this.view_width / (this.rows_count - 1);
    const textStep = (this.xmax - this.xmin) / (this.rows_count - 1);
    ctx.beginPath();
    ctx.strokeStyle = '#bbb';
    ctx.font = 'normal 20px Helvetica, sans-serif';    
    ctx.fillStyle = '#96a2aa';
    
    for (let i = 0; i <= this.rows_count; i++) {
      const x = step * i;      
      const text = this.xmin + Math.round(textStep * i);
      ctx.fillText(text.toString(), 
      this.padding + x - ctx.measureText(text).width/2, 
      this.view_height + this.padding + 25 );
    }
    ctx.stroke();
    ctx.closePath();
  }

  lineDrawing(ctx: any): void {
    ctx.beginPath();
    ctx.lineWidth = 4;
    ctx.strokeStyle = this.color;
    
    
    for (const [x, y] of this.data) {
      
      ctx.lineTo(
        this.padding + x * this.xRatio - this.xmin*this.xRatio, 
        this.view_height + this.padding - y * this.yRatio + this.ymin* this.yRatio
        );
      if(this.DEBUG_MODE){
          ctx.font = 'Arial 16px';
          ctx.fillStyle = 'red';
          ctx.fillText(
            x + ',' + y,
            this.padding + x * this.xRatio - this.xmin*this.xRatio - 100, 
            this.view_height + this.padding - y * this.yRatio + this.ymin* this.yRatio
          );
      }
    }
    ctx.stroke();
  }

  computeBoundaries(data: any) {
    let min, max;
    let minx = this.data[0][0],maxx = this.data[0][0];
    for (const [x, y] of this.data) {
      if (typeof min !== 'number') min = y;
      if (typeof max !== 'number') max = y;
      if (min > y) min = y;
      if (max < y) max = y;
      if(x < minx)
        minx = x;
      if(x > maxx)
        maxx = x;
    }
    return [min, max, minx,maxx];
  }
}
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы