悬停在图表切片上时不显示相关信息

时间:2021-04-21 11:29:54

标签: javascript html css angular

我在我的项目中使用 HTML、CSS 和 Angular 创建了一个图表。

这是我的问题:

我想当用户将鼠标悬停在图表切片上时,只显示用户悬停的切片,但在我的代码中,这不会发生,它会显示其他切片信息。

您可以在此处看到 Demo

这是CSS 代码

@keyframes bake-pie {
  from {
    transform: rotate(0deg) translate3d(0, 0, 0);
  }
}

body {
  font-family: "Open Sans", Arial;
  background: #eee;
}

main {
  width: 400px;
  margin: 30px auto;
}

section {
  margin-top: 30px;
}

.pieID {
  display: inline-block;
  vertical-align: top;
}

.pie {
  height: 200px;
  width: 200px;
  position: relative;
  margin: 100px 30px 30px 200px;
}

.pie::before {
  content: "";
  display: block;
  position: absolute;
  z-index: 1;
  width: 192px;
  height: 192px;
  background: #fff;
  border-radius: 50%;
  top: 4px;
  left: 4px;
}

.pie::after {
  content: "";
  display: block;
  width: 120px;
  height: 2px;
  background: rgba(0, 0, 0, 0.1);
  border-radius: 50%;
  margin: 220px auto;
}

.slice {
  position: absolute;
  width: 200px;
  height: 200px;
  cursor: pointer;
  clip: rect(0px, 200px, 200px, 101px);
  animation: bake-pie 1s;
}

.slice-content::before {
  /* content: "";
  display: block;
  position: absolute;
  z-index: 0;
  width: var(--visible-width);
  height: var(--visible-height);
  background: #fff;
  transition: 150ms;
  border-radius: 50%;
  top: 15px;
  left: 16px;
  visibility: visible; */
}

.slice div {
  display: block;
  position: absolute;
  top: 0;
  left: 0;
  background-color: black;
  width: 200px;
  height: 200px;
  border-radius: 50%;
  clip: rect(0px, 200px, 200px, 104px);
}

p {
  font-family: Lato;
}

canvas {
  border: 2px solid rgba(0, 0, 0, 0.12);
  transition: 300ms;
  border-radius: 4px;
}

canvas:hover {
  border: 2px solid rgba(0, 0, 0, 0.54);
}

body {
  font: 16px/1.4em "Montserrat", Arial, sans-serif;
}

* {
  -webkit-box-sizing: border-box;
  -moz-box-sizing: border-box;
  box-sizing: border-box;
}

.chart-text {
  /*font: 16px/1.4em "Montserrat", Arial, sans-serif;*/
  fill: #000;
  -moz-transform: translateY(0.25em);
  -ms-transform: translateY(0.25em);
  -webkit-transform: translateY(0.25em);
  transform: translateY(0.25em);
}

.chart-number {
  font-size: 0.6em;
  line-height: 1;
  text-anchor: middle;
  -moz-transform: translateY(-0.25em);
  -ms-transform: translateY(-0.25em);
  -webkit-transform: translateY(-0.25em);
  transform: translateY(-0.25em);
}

.chart-label {
  font-size: 0.2em;
  text-transform: uppercase;
  text-anchor: middle;
  -moz-transform: translateY(0.7em);
  -ms-transform: translateY(0.7em);
  -webkit-transform: translateY(0.7em);
  transform: translateY(0.7em);
}

figure {
  display: flex;
  justify-content: space-around;
  flex-direction: column;
  margin-left: -15px;
  margin-right: -15px;
}

@media (min-width: 768px) {
  figure {
    flex-direction: row;
  }
}

.figure-content,
.figure-key {
  flex: 1;
  padding-left: 15px;
  padding-right: 15px;
  align-self: center;
}

.figure-content svg {
  height: auto;
}

.figure-key {
  min-width: calc(8 / 12);
}

.figure-key [class*="shape-"] {
  margin-right: 6px;
}

.figure-key-list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.figure-key-list li {
  margin: 0 0 8px;
  padding: 0;
}

.shape-circle {
  display: inline-block;
  vertical-align: middle;
  width: 32px;
  height: 32px;
  -webkit-border-radius: 50%;
  -moz-border-radius: 50%;
  border-radius: 50%;
}

.shape-fuschia {
  background-color: #ce4b99;
}

.shape-lemon-lime {
  background-color: #b1c94e;
}

.shape-blue {
  background-color: #377bbc;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  border: 0;
}

.donut-segment {
  cursor: pointer;
}

.annytab-tooltip {
  text-align: left;
  color: #ffffff;
  background: #000000;
  position: absolute;
  z-index: 100;
  font-size: 16px;
  line-height: 24px;
  padding: 15px;
  max-width: 100%;
  border-radius: 4px;
  border: 1px solid #000000;
}

.annytab-tooltip.bottom::after {
  position: absolute;
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-bottom: 10px solid #000000;
  content: "";
  top: -11px;
  right: 10px;
}

.annytab-tooltip.top::after {
  position: absolute;
  width: 0;
  height: 0;
  border-left: 10px solid transparent;
  border-right: 10px solid transparent;
  border-top: 10px solid #000000;
  content: "";
  bottom: -11px;
  right: 10px;
}

#tooltip {
  position: absolute;
  z-index: 99999;
  flex-grow: 0;
  visibility: hidden;
  line-height: 1.5;
  flex-direction: row;
  justify-content: flex-start;
  align-items: flex-start;
  gap: 4px;
  padding: 2px 8px;
  border-radius: 5px;
  background-color: #f8f9fb;
  color: #000;
}

.middle {
  background-color: red;
  position: absolute;
  width: 273px;
  height: 264px;
  border-radius: 50%;
  top: 58px;
  left: 132px;
}

HMTL:

    <div #PieID class="pieID pie">

  <div *ngFor="let item of cryptoArray;let i=index" (mouseleave)="tooltipRemove(i)" [id]="'slice'+i"
    (mousemove)="coordinates($event,item,color[i],i)" [class]="'slice '+ 's-'+i"
    [ngStyle]="{'transform': 'rotate(' + item.percent  + 'deg) translate3d(0,0,0)'}">

    <div [id]="'s-'+i" class="slice-content" data-content="Something is happening"
      [ngStyle]="{'transform': 'rotate(' +  item.offset  + 'deg) translate3d(0,0,0)' ,'background-color':color[i] }">
    </div>

  </div>

</div>


<div id="tooltip">
  <div>{{tooltipName}}</div>
  <div>{{tooltipValue}} USD</div>
</div>

TS:

  cryptoArray: ChartModel[] = [
    {
      name: "ETH",
      value: 400
    },
    {
      name: "ETH",
      value: 500
    },
    {
      name: "ETH",
      value: 300
    },
    {
      name: 'ETH',
      value: 700
    },
    {
      name: 'XRP',
      value: 200
    },
    {
      name: 'ADA',
      value: 200
    },
    {
      name: 'BNB',
      value: 1000
    }
  ];

  color = [
    "cornflowerblue",
    "olivedrab",
    "orange",
    "tomato",
    "crimson",
    "purple",
    "turquoise",
    "forestgreen",
    "navy",
    "gray"
  ];

  tooltipName: string;
  tooltipValue: number;
  constructor() { }
  ngAfterViewInit(): void {
    this.drawChart();
  }

  ngOnInit(): void {
    // this.cryptoArray = this.calculatePercent(this.cryptoArray);
  }

  coordinates(
    event: MouseEvent,
    item: ChartModel,
    color: string,
    index: number
  ): void {
    // let pixelData = canvas.getContext('2d').getImageData(event.offsetX, event.offsetY, 1, 1).data;
    let canvas = document.createElement('canvas');
    let context = canvas.getContext('2d');
    let myData = context.getImageData(event.offsetX, event.offsetY, 1, 1).data;
    console.log(myData)
    this.tooltipName = item.name;
    this.tooltipValue = item.value;
    const slice = document.getElementById("slice" + index);
    slice.style.visibility = "visible";
    slice.style.setProperty("--visible-width", "166px");
    slice.style.setProperty("--visible-height", "166px");
    slice.style.zIndex = "2";
    this.tooltip(item.name, event.clientX, event.clientY, color);
  }

  tooltip(title: string, x: number, y: number, color: string): void {
    const item = document.getElementById("tooltip");
    item.style.visibility = "visible";
    item.style.top = y + "px";
    item.style.left = x + "px";
    item.style.backgroundColor = color;
  }

  tooltipRemove(index: number): void {
    let item = document.getElementById("tooltip");
    item.style.visibility = "hidden";

    const slice = document.getElementById("slice" + index);
    slice.style.setProperty("--visible-width", "171px");
    slice.style.setProperty("--visible-height", "171px");
    slice.style.strokeWidth = "3";
    slice.style.zIndex = "0";
  }

  public findTotalValue(valueArray: ChartModel[]): number {
    let listTotal = 0;
    // tslint:disable-next-line:prefer-for-of
    for (let i = 0; i < valueArray.length; i++) {
      listTotal += valueArray[i].value;
    }
    return listTotal;
  }

  // tslint:disable-next-line:typedef
  public drawChart() {
    let percent = 0;
    let offset = 0;
    const total = this.findTotalValue(this.cryptoArray);
    this.cryptoArray.forEach((element, i) => {
      // percent = (element.value / total) * 360;
      percent = this.sliceSize(element.value, total);
      // element.percent = percent;
      const itrationInfo = this.itrationSlice(percent, offset);
      element.percent = itrationInfo.offset;
      element.offset = itrationInfo.sizeRotation;
      offset += percent;
      const slice = document.getElementById("slice" + i);
      slice.style.visibility = "visible";
      slice.style.setProperty("--visible-width", "171px");
      slice.style.setProperty("--visible-height", "171px");
    });
  }

  public itrationSlice(sliceSize, offset): any {
    const maxSize = 179;

    if (sliceSize <= maxSize) {
      return this.addSlice(offset, sliceSize);
    } else {
      return this.addSlice(offset, maxSize);
    }
  }

  public addSlice(offset, sliceSize): any {
    const offsett = offset - 1;
    const sizeRotation = -179 + sliceSize;
    return { offset: offsett, sizeRotation };
  }

  public sliceSize(dataNum, dataTotal): number {
    return (dataNum / dataTotal) * 360;
  }
}

有什么问题吗?我该如何解决这个问题???

1 个答案:

答案 0 :(得分:0)

我不知道如何修复它,但我知道它为什么会发生。 问题是 slice 形状并不是它们看起来的真实形状。它们实际上是矩形。因此,当您尝试将鼠标悬停在一个切片上时,实际上您将鼠标悬停在另一个切片上。

将此行添加到 coordinates 函数:

slice.style.backgroundColor = color;

tooltipRemove 这一行:

slice.style.backgroundColor = 'transparent';

你会在工作中看到问题。

你必须找到一种方法让切片看起来就像它们在 SVG 中的样子。