详解根据 Canvas 手撸1个6边形工作能力图

日期:2021-02-26 类型:科技新闻 

关键词:自助建站,专业建站,建站网站,建站平台,网站在线制作app

1、序言

6边形工作能力图以下,由 6 个 6边形构成,每个端点意味着其在某1层面的工作能力。这篇文章内容大家就看来看怎样根据 canvas 去绘图这么1个6边形工作能力图。自然,你还可以根据别的开源系统的 js 计划方案来完成,如 EChars.js 等。

 

2、6边形绘图基本

6边形工作能力图有 6 个 6边形构成,那大家要是绘图出1个,此外 5 个则先后减小6边形的边长便可。那大家最先来剖析1下,怎样绘图出1个6边形。

如上图,绘图1个6边形有下列几个重要点:

1.紫色矩形框地区大家能够当做是 canvas 的画布。其尺寸能够觉得是 (width,height)。center(centerX,centerY) 是在其中心点,即 (width / 2, height / 2)。

2.绘图6边形的重要是测算出它的 6 个端点的座标。而如上图所示,这里边最重要的又是测算出6边形所属矩形框地区的左上角座标(left,top)。对比上图,(left,top) 的测算公式以下。

要测算出 (left,top) 必须先测算出 x,y 。而 x,y 的值与6边形的边长相关。

3.如上的 x,y 的测算公式为

4.因而,X1(x1,y1),X2(x2,y2),X3(x3,y3),X4(x4,y4),X5(x5,y5),X6(x6,y6) 的座标测算为

因而,获得绘图6边形的编码为:

function computeHexagonPoints(width, height, edge) {
    let centerX = width / 2;
    let centerY = height / 2;
    let x = edge * Math.sqrt(3) / 2;
    let left = centerX - x;
    let x1,x2,x3,x4,x5,x6;
    let y1,y2,y3,y4,y5,y6;
    x5 = x6 = left;
    x2 = x3 = left + x * 2;
    x1 = x4 = left + x;

    let y = edge / 2;
    let top = centerY - 2 * y;
    y1 = top;
    y2 = y6 = top + y;
    y3 = y5 = top + 3 * y;
    y4 = top + 4 * y;

    let points = new Array();
    points[0] = [x1, y1];
    points[1] = [x2, y2];
    points[2] = [x3, y3];
    points[3] = [x4, y4];
    points[4] = [x5, y5];
    points[5] = [x6, y6];
    return points;
  }

3、绘图6维工作能力图

 3.1 绘图 6 个6边形

根据 canvas 绘图,最先便是必须获得 context。

_context = canvas.getContext('2d');

而绘图的话,早已了解 6 个端点了,那只必须将这 6 个点用连线的方法联接起来便可以了。关键用到 moveTo(x,y) 和 lineTo(x,y) 两个方式。这里一共必须绘图 6 个6边形,那要是按等占比减小 edge 的值便可以了。因而绘图6边形工作能力图的关键编码以下。

function drawHexagonInner(edge) {
    _context.strokeStyle = _color;
    for (var i = 0; i < 6; i++) {
      _allPoints[i] = computeHexagonPoints(_width, _height, edge - i * edge / 5);
      _context.beginPath();
      _context.moveTo(_allPoints[i][5][0],_allPoints[i][5][1]);
      for (var j = 0; j < 6; j++) {
        _context.lineTo(_allPoints[i][j][0],_allPoints[i][j][1]);
      }
      _context.closePath();
      _context.stroke();
    }
  }

编码中也有 3 个有关的 API。beginPath() 和 closePath() 关键便是绘图获得1个封闭式的相对路径。stroke() 关键是获得1个镂空的样子。自然,相应的就有 fill() 获得填充的样子。

3.2 绘图 3 条平行线

绘图那 3 条平行线也是较为简易的,要是将 X1和X4 联接,将X2 和 X5 相连,将 X3 和 X6 相连。编码以下:

function drawLines() {
    _context.beginPath();
    _context.strokeStyle = _color;
    for (let i = 0; i < 3; i++) {
      _context.moveTo(_allPoints[0][i][0],_allPoints[0][i][1]); //1⑷
      _context.lineTo(_allPoints[0][i+3][0],_allPoints[0][i+3][1]); //1⑷
      _context.stroke();
    }
    _context.closePath();
  }

3.3 绘图遮盖图

6 个端点意味着了6种工作能力,例如这里的各科考试成绩,把6种工作能力封闭式成1个闭合相对路径并填充则称为遮盖图。要绘图出遮盖图,这里必须测算出6个端点。6 个端点能够根据最外围的6边形的 6 个端点和管理中心点来测算。简易来讲便是根据工作能力得分,在端点到管理中心间距的占有率来测算。测算公式以下。

编码以下

/**
   * 画遮盖物
   */
  function drawCover() {

    let tmpCoverPoints = _allPoints[0];
    _coverPoints = [];
    console.log("coverPoints ",tmpCoverPoints)

    let centerX = _width / 2;
    let centerY = _height / 2;
    for (let i = 0; i < tmpCoverPoints.length; i++) {
      _coverPoints.push([
        centerX + (tmpCoverPoints[i][0] - centerX) * (_data[i].score / 100.0),
        centerX + (tmpCoverPoints[i][1] - centerY) * (_data[i].score / 100.0)
      ]);
    }
    console.log("newCoverPoints ",_coverPoints)
    _context.beginPath();
    _context.fillStyle = 'rgba(90,200,250,0.4)';
    _context.moveTo(_coverPoints[5][0],_coverPoints[5][1]); //5
    for (var j = 0; j < 6; j++) {
      _context.lineTo(_coverPoints[j][0],_coverPoints[j][1]);
    }
    _context.stroke();
    _context.closePath();
    _context.fill();
  }
/**
   * 描点
   * @param pointRadius
   */

  function drawPoints(pointRadius) {
    _context.fillStyle = _color;
    for (let i = 0; i < _coverPoints.length; i++) {
      _context.beginPath();
      _context.arc(_coverPoints[i][0],_coverPoints[i][1],pointRadius,0,Math.PI*2);
      _context.closePath();
      _context.fill();
    }
  }

3.4 最终来绘图文字

绘图文字也是用的最外围的 6 个端点的座标。而用的 API 是 fillText(text,x,y),在其中 x,y 编码文本绘图起始点,但留意,并不是文本所属矩形框框的左上角,应当在左下角的大约部位。精确来讲是文本的基准线部位,这个在别的的GUI系统软件中也是1样,自然这里不追求完美那末细节了,就觉得是左下角部位吧。

因而,针对不一样侧的文本,其起始点座标也是不1样。如左边的文本最少应当是左边的端点 x 减去文本的宽度。再例如,左右两边的文本与端点中相对性垂直居中对齐的,因而测算方式是 x 减去文本宽度的1半。编码的完成分成了左右上下来开展不一样的绘图。

编码以下,看着有点长,但实际上是很简易的。

/**
   * 绘图上侧的文本
   * @param text
   * @param pos
   */
  function drawUpText(item, pos) {
    let nameMeasure = _context.measureText(item.name);
    let scoreMeasure = _context.measureText(item.score);

    _context.fillStyle = '#8E8E8E';
    _context.fillText(item.name, pos[0] - nameMeasure.width / 2,pos[1] - 26);
    _context.fillStyle = '#212121';
    _context.fillText(item.score, pos[0] - scoreMeasure.width / 2,pos[1] - 10);

  }
/**
   * 绘图下侧的文本
   * @param text
   * @param pos
   */
  function drawDownText(item, pos) {

    let nameMeasure = _context.measureText(item.name);
    let scoreMeasure = _context.measureText(item.score);

    _context.fillStyle = '#8E8E8E';
    _context.fillText(item.name, pos[0] - nameMeasure.width / 2,pos[1] + 16);
    _context.fillStyle = '#212121';
    _context.fillText(item.score, pos[0] - scoreMeasure.width / 2,pos[1] + 32);
  }
/**
   * 绘图左边的文本
   * @param text
   * @param pos
   */
  function drawLeftText(item, pos) {

    let nameMeasure = _context.measureText(item.name);
    let scoreMeasure = _context.measureText(item.score);

    _context.fillStyle = '#8E8E8E';
    _context.fillText(item.name, pos[0] - nameMeasure.width - 10,pos[1]);
    _context.fillStyle = '#212121';
    _context.fillText(item.score, pos[0] - 10 - (nameMeasure.width + scoreMeasure.width) / 2,pos[1] + 16);

  }
/**
   * 绘图右边的文本
   * @param text
   * @param pos
   */
  function drawRightText(item, pos) {
    let nameMeasure = _context.measureText(item.name);
    let scoreMeasure = _context.measureText(item.score);

    _context.fillStyle = '#8E8E8E';
    _context.fillText(item.name, pos[0] - nameMeasure.width + 26,pos[1]);
    _context.fillStyle = '#212121';
    _context.fillText(item.score, pos[0] + 26 - (nameMeasure.width + scoreMeasure.width) / 2,pos[1] + 16);
  }
/**
   * 绘图全部文字
   */
  function drawText() {

    _context.fillStyle = '#8E8E8E';
    _context.strokeStyle = _color;

    let textPos = _allPoints[0];

    for (let i = 0; i < textPos.length; i++) {

      let item = _data[i];
      let pos = textPos[i];
      if(i == 0) {
        drawUpText(item, pos);
      } else if(i == 1 || i == 2) {
        drawRightText(item, pos);
      } else if(i == 3) {
        drawDownText(item, pos);
      } else if(i == 4 || i == 5) {
        drawLeftText(item, pos);
      }
    }
  }

4、总结

文章内容关键是根据 canvas 自定1个6边形工作能力图,而这个工作能力的图的重要一部分是针对6边形的绘图,而6边形的绘图又在于测算出 6 个端点。有了 6 个端点,再绘图别的的边,文字,遮盖地区等都根据这个 6 个端点开展相应的绘图便可。

以上便是本文的所有內容,期待对大伙儿的学习培训有一定的协助,也期待大伙儿多多适用脚本制作之家。