ApexChart Ridar Drag Response input type range

agnusdei·2023년 7월 6일

npm install apexcharts --save
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import ApexCharts from 'apexcharts';

@Component({
  selector: 'app-chart',
  template: `
    <div class="w-full h-full" #chartContainer></div>
  `,
})
export class ChartComponent implements OnInit {
  @ViewChild('chartContainer') chartContainer!: ElementRef;

  chartOptions: any = {
    // Chart options here
  };

  ngOnInit() {
    this.initChart();
  }

  private initChart() {
    const chart = new ApexCharts(
      this.chartContainer.nativeElement,
      this.chartOptions
    );

    chart.render();
  }
}
  1. apexChart rerender
<section
  class="flex flex-col gap-5 p-5 text-sm border border-gray-200 rounded-20"
>
  <div class="flex items-start gap-2 font-semibold text-gray-800">
    <ng-content />
    <div *ngIf="required" class="w-2 h-2 bg-red-500 rounded-full"></div>
  </div>
  <div class="flex items-center justify-between text-gray-400">
    <div>{{ min }}점</div>
    <div>{{ max }}점</div>
  </div>
  <div class="relative range">
    <input
      #range
      type="range"
      class="appearance-none cursor-pointer"
      [min]="min"
      [max]="max"
      [value]="value"
      (input)="handleRange($event)"
      [ngStyle]="{ background: progress() }"
    />
    <div
      #indicator
      class="absolute flex items-center justify-center w-12 h-10 text-white rounded-full pointer-events-none select-none bg-primary -top-1/2"
      [ngStyle]="{ left: indicatorLeft }"
    >
      {{ value }}점
    </div>
  </div>
</section>
  1. dragable score bar
import { CommonModule } from '@angular/common';
import {
  AfterViewInit,
  Component,
  ElementRef,
  Input,
  OnInit,
  Optional,
  Self,
  ViewChild,
} from '@angular/core';
import { FormsModule, NgControl } from '@angular/forms';
import { ToastService } from '../../../services/toast.service';
import { CustomValueAccessor } from '../../custom-value-accessor';

@Component({
  selector: 'app-input-range',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './input-range.component.html',
  styleUrls: ['./input-range.component.scss'],
})
export class InputRangeComponent
  extends CustomValueAccessor<number>
  implements OnInit, AfterViewInit
{
  @ViewChild('indicator') indicator: ElementRef<HTMLDivElement> | undefined;
  @ViewChild('range') range: ElementRef<HTMLInputElement>;

  @Input() min = 1;
  @Input() max = 10;
  @Input() maximumValue = 35;
  @Input() default: number = 1;
  @Input() override required = false;
  @Input() sum?: number;
  override disabled = false;

  middle: number = Math.ceil((this.max - this.min) / 2);
  timer: NodeJS.Timer;
  constructor(
    @Self() @Optional() public ngControl: NgControl,
    private readonly toastService: ToastService
  ) {
    super();
    if (this.ngControl) {
      this.ngControl.valueAccessor = this;
    }
  }

  ngAfterViewInit(): void {
    if (this.default) {
      this.value = this.default;
    }
  }

  ngOnInit(): void {
    if (this.default) {
      this.value = this.default;
    }
  }

  handleRange(ev: any) {
    const value: number = +ev.target.value;
    if (
      this.sum + (value - this.value - 1) >= this.maximumValue &&
      value > this.value
    ) {
      clearTimeout(this.timer);
      this.timer = setTimeout(() => {
        this.toastService.show('총합 35점을 넘을 수 없습니다.', 'danger');
      }, 500);
      return false;
    } else {
      this.value = value;
      return true;
    }
  }

  progress() {
    return `linear-gradient(to right, #7D3CAB ${this.indicatorLeft}, #F3F4F6 ${this.indicatorLeft})`;
  }

  get indicatorLeft(): string {
    const ratio = ((this.value - 1) / (this.max - 1)) * 100;
    const indicatorWidth = this.indicator?.nativeElement.offsetWidth ?? 0;
    return `calc(${ratio}% - ${(indicatorWidth * ratio) / 100}px)`;
  }
}

progress() 함수는 슬라이더의 배경색을 결정하는데 사용되는 CSS linear-gradient 속성 값을 반환하는 함수입니다. 해당 코드에서는 to right 방향으로 그라데이션을 설정하고 있습니다. 아래는 코드에서 사용된 각 부분의 설명입니다:

  • linear-gradient: CSS의 그라데이션을 생성하는 함수입니다.
  • to right: 그라데이션의 방향을 수평으로 설정합니다.
  • #7D3CAB: 그라데이션의 시작 색상을 나타냅니다. 이 경우, 보라색(#7D3CAB)이 시작 색상으로 사용됩니다.
  • ${this.indicatorLeft}: 그라데이션의 위치를 결정하는 값입니다. this.indicatorLeft는 슬라이더의 현재 위치를 나타내는 문자열입니다.
  • #F3F4F6: 그라데이션의 종료 색상을 나타냅니다. 이 경우, 밝은 회색(#F3F4F6)이 종료 색상으로 사용됩니다.
  • ${this.indicatorLeft}: 그라데이션의 위치를 결정하는 값으로, 시작과 종료 색상 사이의 위치와 동일한 값이 사용됩니다.

위 코드에서 this.indicatorLeftget indicatorLeft() 메서드를 통해 계산된 값을 사용합니다. indicatorLeft는 슬라이더의 현재 값을 기반으로 슬라이더의 미리보기 위치를 계산하는 데 사용됩니다. 따라서 progress() 함수는 슬라이더의 현재 위치에 따라 배경 그라데이션을 동적으로 변경합니다.

결과적으로, progress() 함수는 슬라이더의 배경색을 시작 색상과 종료 색상으로 그라데이션하며, 그라데이션의 위치는 슬라이더의 현재 위치에 따라 결정됩니다.

profile
DevSecOps Pentest🚩

0개의 댓글