将工具提示位置强制设置在弹药上

时间:2020-10-07 14:44:18

标签: javascript tooltip amcharts4

我希望这里有一些amcharts用户,可以为我遇到的问题提供帮助。

简而言之:我想强制工具提示始终显示在直线系列上的悬停点上方,即使它超出图表区域也是如此。工具提示适用于所有系列。示例可以在这里看到:

const {useRef, useState} = React;
const CHART_CONTAINER = 'campaign-budget-chart';
const CHART_COLORS = {
  value1: '#05a8fa',
  value2: '#ed3434',
  value3: '#0ec76a',
}

function getRandomNumber(max){
  return Math.floor(Math.random() * Math.floor(max))
}

const initialData = [{
  timestamp: new Date(2020, 09, 25),
  value1: 0,
  value2: getRandomNumber(50),
  value3: getRandomNumber(250),
},{
  timestamp: new Date(2020, 09, 26),
  value1: getRandomNumber(100),
  value2: getRandomNumber(50),
  value3: getRandomNumber(250),
},{
  timestamp: new Date(2020, 09, 27),
  value1: getRandomNumber(100),
  value2: getRandomNumber(50),
  value3: getRandomNumber(250),
},
           {
  timestamp: new Date(2020, 09, 28),
  value1: getRandomNumber(100),
  value2: getRandomNumber(50),
  value3: getRandomNumber(250),
}];
let i = 0;

function BudgetChart() {
  const chartRef = useRef(null);
  const [data, setData] = useState(initialData);
  const [cursor, setCursor] = React.useState({ x: 0, y: 0 });
  const [cursorVisible, setCursorVisible] = React.useState(false);

  function createSeries(
    fieldX,
    fieldY,
    name,
    lineColor,
  ) {
    if (!chartRef.current) return;
    console.log('Create series');
    // Init series
    let series = chartRef.current.series.push(new am4charts.LineSeries());
    series.name = name;
    series.dataFields.valueY = fieldY;
    series.dataFields.dateX = fieldX;
    series.strokeWidth = 3;
    series.stroke = am4core.color(lineColor);
    series.tooltip.pointerOrientation = 'down';
    series.tooltip.background.filters.clear(); // remove shadow
    series.tooltip.getFillFromObject = false;
    series.tooltip.background.fill = am4core.color('#2a2b2e');
    series.tooltip.background.stroke = am4core.color('#2a2b2e');
    series.tooltip.label.fontSize = 12;
    series.tooltip.background.pointerLength = 0;
    series.tooltip.dy = -5;
    series.tooltipText = '{valueY}';
    series.tensionX = 0.8;
    series.showOnInit = false;

    // Add bullet for optimization
    let circleBullet = series.bullets.push(new am4charts.CircleBullet());
    circleBullet.circle.radius = 6;
    circleBullet.circle.fill = lineColor;
    circleBullet.circle.stroke = am4core.color('#fff');
    circleBullet.circle.strokeWidth = 3;
    circleBullet.propertyFields.disabled = 'optimizationTooltipDisabled';
      // Set up tooltip
  series.adapter.add("tooltipText", function(ev) {
    var text = "[bold]{dateX}[/]\n"
    chartRef.current.series.each(function(item) {
      text += "[" + item.stroke.hex + "]●[/] " + item.name + ": {" + item.dataFields.valueY + "}\n";
    });
    return text;
  });

    // Bullet shadow
    let shadow = circleBullet.filters.push(new am4core.DropShadowFilter());
    shadow.opacity = 0.1;

  }

  React.useEffect(() => {
    if (!chartRef.current) {
      chartRef.current = am4core.create(CHART_CONTAINER, am4charts.XYChart);

      chartRef.current.paddingLeft = 0;

      // Add date axis
      let dateAxis = chartRef.current.xAxes.push(new am4charts.DateAxis());
      dateAxis.renderer.labels.template.fontSize = 12;
      dateAxis.renderer.labels.template.fill = am4core.color(
        'rgba(183,186,199,0.8)'
      );
      dateAxis.renderer.grid.template.strokeOpacity = 0;

      // Add value axis
      let valueAxis = chartRef.current.yAxes.push(new am4charts.ValueAxis());
      valueAxis.renderer.grid.template.stroke = am4core.color(
        '#f0f2fa'
      );
      valueAxis.renderer.grid.template.strokeOpacity = 1;
      valueAxis.renderer.labels.template.fill = am4core.color(
        'rgba(183,186,199,0.8)'
      );
      valueAxis.renderer.labels.template.fontSize = 12;

      // Add cursor
      chartRef.current.cursor = new am4charts.XYCursor();
      chartRef.current.cursor.maxTooltipDistance = -1;

      // Add legend
      chartRef.current.legend = new am4charts.Legend();
      chartRef.current.legend.position = 'bottom';
      chartRef.current.legend.contentAlign = 'left';
      chartRef.current.legend.paddingTop = 20;

      // Disable axis lines
      chartRef.current.cursor.lineX.disabled = true;
      chartRef.current.cursor.lineY.disabled = true;

      // Disable axis tooltips
      dateAxis.cursorTooltipEnabled = false;
      valueAxis.cursorTooltipEnabled = false;

      // Disable zoom
      chartRef.current.cursor.behavior = 'none';

      chartRef.current.cursor.events.on('cursorpositionchanged', function(ev) {
        let xAxis = ev.target.chart.xAxes.getIndex(0);
        let yAxis = ev.target.chart.yAxes.getIndex(0);
        setCursor({
          x: xAxis.toAxisPosition(ev.target.xPosition),
          y: yAxis.toAxisPosition(ev.target.yPosition),
        });
      });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
  
  // Load data into chart
  React.useEffect(() => {
    console.log('data ', data)
    if (chartRef.current) {
      chartRef.current.data = data;
      
      Object.keys(data[0]).forEach(key => {
        if(key === 'timestamp') return;
        createSeries(
        'timestamp',
        key,
        key,
        CHART_COLORS[key]
      );
      })
    }
  }, [data]);

  // Handle component unmounting, dispose chart
  React.useEffect(() => {
    return () => {
      chartRef.current && chartRef.current.dispose();
    };
  }, []);
  
  function handleRemoveSeries(){
    setData(data.map(item => ({timestamp: item.timestamp, value1: item.value1, value2: item.value2})))
  }

  return (
    <>
      <button onClick={handleRemoveSeries}>Remove 3rd series</button>
      <div
        id={CHART_CONTAINER}
        style={{
          width: '100%',
          height: '350px',
          marginBottom: '50px',
        }}
      />
    </>
  );
}

ReactDOM.render(<BudgetChart />, document.getElementById('app'));

对于图表顶部附近的所有值,工具提示尝试将自身挤压到图表区域内。根据文档:https://www.amcharts.com/docs/v4/reference/tooltip/, 重要信息:在某些情况下,例如为多个序列堆叠多个工具提示,可能会忽略“ up”和“ down”值以使工具提示重叠算法起作用。

是否可以禁用工具提示重叠算法?

1 个答案:

答案 0 :(得分:0)

4.10.8 版本(在发布初始问题后发布)开始,系列工具提示上有一个属性 ignoreBounds

More on ignoreBounds on amchart docs