HTML5 캔버스 (실제 : 파이 차트 2 툴팁 그리기)

에 따라 (전투 : 파이 차트를 그릴) HTML5 캔버스 그 후, 나는 메시지 상자를 추가하는 방법을 연구 나타나는 경우 원형 차트에 마우스를 가리키면.

플롯 개체

이 이동 때 코딩을 시작하기 전에, 내가 가장 쉬운 방법을 생각할 수는 너무 쉽게 표시됩니다 파이에서 mousemove 이벤트, 마우스가 해당 메시지 상자의 각 섹션에 추가됩니다! 이 방울처럼하지만 사실은 ~하지 않다

우리의 육안 뭔가, 캔버스의 조각 같은 외모와 정말는 HTMLElement의 조각에 넣어하지 않았다, 우리는주고 캔버스 이벤트를 바인딩 만 할 수 있습니다. 그렇다면, 당신은 기준 각은 우리가 서로를 저장해야하는 시작 각도와 끝 각도 영역 사이에 연결하는 마우스의 위치와 중심선을 계산할 수있는 마우스가 현재 그 안에 머물고 지역 알 수 있습니까 각 정보 영역.
저장 용이하게하기 위해, 생성자 플롯을 만들 수 있습니다.

function Plot(start, end, color, data) {
  this.start = start;
  this.end = end;
  this.color = color;
  this.data = data;
}

당신은 기사와 파이 차트 범례 영역을 그리기하는 방법에 그릴 수있는 플롯의 프로토 타입 체인을 넣어


Plot.prototype.drawLegend = function() {
  ctx.fillRect(legend_posX, legend_posY, legend_width, legend_height);
  ctx.font = 'bold 12px Arial';
  var percent = this.data.label + ' : ' + (this.data.portion * 100).toFixed(2) + '%';
  ctx.fillText(percent, legend_textX, legend_textY);
}
Plot.prototype.drawPlot = function() {
  ctx.fillStyle = this.color;
  ctx.beginPath();
  ctx.moveTo(center.x, center.y);
  ctx.arc(center.x, center.y, radius, this.start, this.end, false);
  ctx.closePath();
  ctx.fill();
}

사용자 정의 도구 설명

이전 글 : HTML5 캔버스 (실제 파이 차트를 그릴) 은 다음과 같이 우리의 초기 설계에서 볼 수있는, 내용이 툴팁 사용자 정의에 표시 할 수있는 사용자는 템플릿을 설정할 수 있습니다 :

Year: {{year}}, Data: {{data}}

우리의 목표는 위의 템플릿으로 변환 할 수 있습니다 :

Year: 2017, Data: 3000

수신 도구 방법 작성 template문자열을, 그리고 마우스 현재의 주행 plot데이터를 실제 디스플레이는 문자열을 반환합니다 :

function replaceAttr(text, data) {
    while (text.indexOf("{{") != -1) {
      var start = text.indexOf("{{"),
          end = text.indexOf("}}"),
          attr = text.substring(start + 2, end);
      text = text.replace("{{" + attr + "}}", data[attr]);
    }
    return text;
}

당신이 코드에서 볼에 습관적 수 없습니다 {{}}사이에 공백을 추가합니다.

어디 마우스

지역 호버를 결정하기 위해, 우리는 다음과 같은 두 가지 단계를 완료해야합니다 :

  1. 계산 된 중심 위치와 마우스 사이의 라디안angle
  2. 순회가 plots결정하는 angle일에 위치하고 있는지 여부 plot이 발견되면, 사이 , 판사 는 마우스, 만약 그렇다면, 표시하지 않을 경우, 차트를 다시 그리기, 툴팁을 그릴 필요가 없습니다 마지막 영역인지. 해당 영역은 마우스가 캔버스 영역에서 파이 아님을 나타내는 발견되지 않는 경우, 다음은 전역 변수를 지워야합니다, 전설, 제목 또는 빈 영역을 가리 수 천 그림을보십시오.startAngleendAngleplotplotcurrentPlot

마우스의 위치와 중심 사이의 호를 확인하는 방법에서 다음 작은 시리즈는 파이 차트를 그린 만 여기에 도움이 될 수 있습니다 ...

function getAngle(cx, cy, mx, my) {
    var x = Math.abs(cx - mx),
        y = Math.abs(cy - my),
        z = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)),
        cos = y / z,
        radina = Math.acos(cos);

    if (mx > cx && my > cy) {
      return radina;
    } else if (mx < cx && my > cy) {
      return Math.PI / 2 + radina;
    } else if (mx > cx && my < cy) {
      return 3 * Math.PI / 2 - radina
    } else {
      return 3 * Math.PI / 2 + radina
    }
}
function onMouseMove(e) {
    var ex = e.pageX - cv.offsetLeft,
        ey = e.pageY - cv.offsetTop;
    var angle = getAngle(center.x, center.y, ex, ey);
    for (let i = 0; i < plots.length; i++) {
      if (plots[i].start < angle && plots[i].end > angle) {
        if (currentPlot != plots[i]) {
          currentPlot = plots[i];
          draw();
        }
        return;
      }
    }
    currentPlot = null;
    draw();
  }

이제 우리는 마우스 숙박의 현재 위치를 알고, 또한 프롬프트 텍스트로 사용자 정의 할 수 있습니다, 당신은 지금 프롬프트 상자를 그릴 수 있습니다, 다음 코드는 귀찮은 계산 과정도 몇 가지 문제입니다 비트, 나는 다시 계산 다른 날 ~

Plot.prototype.drawTooltip = function() {
    var text = replaceAttr(op.tooltip.template, this.data);
    var width_tooltipText = ctx.measureText(text).width,
        height_tooltipText = parseInt(op.tooltip.font.size, 10),
        angle = (this.start + this.end) / 2 / (2 * Math.PI) *360;
    var tan = Math.tanh(angle),
        x = 0,
        y = 0;

    if (angle < 90)((x = radius / 2 * tan + center.x) || true) && ((y = -radius / 2 + center.y) || true)
    else if (angle > 90 && angle < 180)((x = radius / 2 * tan + center.x) || true) && ((y = radius / 2 + center.y) || true)
    else if (angle > 180 && angle < 270)((x = -radius / 2 * tan + center.x) || true) && ((y = radius / 2 + center.y) || true)
    else if (angle > 270 && angle < 360)((x = -radius / 2 * tan + center.x) || true) && ((y = -radius / 2 + center.y) || true)
    var tooltip_box_x = x - radius / 4,
        tooltip_box_y = y,
        tooltip_box_width = width_tooltipText + 10,
        tooltip_box_height = height_tooltipText + 10,
        tooltip_text_x = x - radius / 4 + 5,
        tooltip_text_y = y + 10 + 2;
    ctx.fillStyle = 'white';
    ctx.fillRect(tooltip_box_x, tooltip_box_y, tooltip_box_width, tooltip_box_height);
    ctx.fillStyle = '#000';
    ctx.fillText(text, tooltip_text_x, tooltip_text_y);
}

툴팁 필요가 당신이 파이를 다시 그리기하지만 때마다 다시 그려야하는 startAngle endAngle그릴 때마다 수정됩니다, 그리기 전에 재설정하는 것이 필요하다.

function clear() {
    ctx.clearRect(0, 0, cv.width, cv.height);
    startAngle = 0;
    endAngle = 0;
    cv.onmousemove = null;
}

우리의 최종 그리기 방법 ~

function draw() {
    clear();
    title_text = op.title.text;
    ctx.font = op.title.font.weight + " " + op.title.font.size + "px " + op.title.font.family;
    title_width = ctx.measureText(title_text).width;
    title_height = op.title.font.size;
    title_position = {
      x: (width, title_width) / 2,
      y: 20 + title_height
    };
    ctx.fillText(title_text, title_position.x, title_position.y);
    radius = (height - title_height - title_position.y - 20) / 2;
    center = {
      x: radius + 20,
      y: radius + 30 + title_position.y
    };
    legend_width = op.legend.font.size * 2.5;
    legend_height = op.legend.font.size * 1.2;
    legend_posX = center.x * 2 + 20;
    legend_posY = 80;
    legend_textX = legend_posX + legend_width + 5;
    legend_textY = legend_posY + op.legend.font.size * 0.9;
    ctx.strokeStyle = 'grey';
    ctx.lineWidth = 3;
    ctx.strokeRect(0, 0, width, height);

    for (var i = 0, len = data_c.length; i < len; i++) {
      endAngle += data_c[i].portion * 2 * Math.PI;
      var plot = new Plot(startAngle, endAngle, data_c[i].color, data_c[i])
      plots.push(plot);
      plot.drawPlot();
      startAngle = endAngle;
      legend_posY += (10 + legend_height);
      legend_textY += (10 + legend_height);
      plot.drawLegend();
    }
    if (currentPlot) {
      currentPlot.drawTooltip();
    }
    cv.onmousemove = onMouseMove;
}

도 완료 :

원본 주소 : HTTPS : //github.com/Sue1024/ca ...

추천

출처www.cnblogs.com/jlfw/p/11919678.html