如何在画布上创建Duval五角大楼

时间:2016-04-10 14:54:21

标签: javascript css canvas html5-canvas

嘿,我根据在画布上创建duval三角形的帖子创建了一个Duval五角大楼:how to create Duval Triangle in canvas。 我的最终结果应该是: enter image description here

我目前的情况是,我可以创建五角大楼内的所有部分,但我没有找到在我的duval五角大楼的每个角落(点)周围放置气体标签的方法,任何建议或帮助是欢迎。

创建duval五边形流程是这样的:

1.创造外五角大楼。

2.创建循环中的所有细分。

3.创建五角大楼的传奇。

更新 我已经尝试根据@markE引导线再次构建分子标签。到目前为止没有那么好尝试过,我肯定做错了什么。 :(

2.3

function moleculeLabel(V,P,text){
    var dx=V.x-P.x;
    var dy=V.y-P.y;
    var rAngle=Math.atan2(dy,dx);
    var padding=15; // == how far outside the pentagon you want to go
    var outsideX=P.x+(P.radius+padding)*Math.cos(rAngle);
    var outsideY=P.y+(P.radius+padding)*Math.sin(rAngle);
    ctx.textAlign='center';
    ctx.textBaseline='middle';
    ctx.fillStyle='black';
    ctx.fillText(text,outsideX,outsideY);
}`
$(function() {

  //offset :  
  var canvas = document.getElementById("canvas");
  var ctx = canvas.getContext("2d");

  var points = [{
    x: 397,
    y: 149
  }, {
    x: 318,
    y: 346
  }, {
    x: 112,
    y: 347
  }, {
    x: 44,
    y: 147
  }, {
    x: 221,
    y: 27
  }, {
    x: 397,
    y: 149
  }];
  var cx = 0;
  var cy = 0;

  for (var i = 0; i < points.lenght; i++) {
    cx = cx + points[i].x;
    cy = cy + points[i].y;
  }
  cx = cx / points.lenght;
  cy = cy / points.lenght;
  var centerPoint = {
    x: cy,
    y: cy
  };
  // Define all your segments here
  var segments = [{
    points: [{
      x: 61,
      y: 191
    }, {
      x: 112,
      y: 347
    }, {
      x: 190,
      y: 223
    }, {
      x: 214,
      y: 211
    }, {
      x: 217,
      y: 198
    }, {
      x: 61,
      y: 192
    }],
    fill: 'rgb(172,236,222)',
    label: {
      text: 'T1',
      cx: 130,
      cy: 250,
      withLine: false,
      endX: null,
      endY: null
    },
  }, {
    points: [{
      x: 61,
      y: 191
    }, {
      x: 217,
      y: 198
    }, {
      x: 220,
      y: 26
    }, {
      x: 44,
      y: 149
    }],
    fill: 'deepskyblue',
    label: {
      text: 'S',
      cx: 140,
      cy: 150,
      withLine: false,
      endX: null,
      endY: null
    },
  }, {
    points: [{
      x: 220,
      y: 26
    }, {
      x: 217,
      y: 198
    }, {
      x: 239,
      y: 135
    }, {
      x: 365,
      y: 230
    }, {
      x: 397,
      y: 149
    }, {
      x: 221,
      y: 27
    }],
    fill: 'lightCyan',
    label: {
      text: 'D1',
      cx: 270,
      cy: 110,
      withLine: false,
      endX: null,
      endY: null
    },
  }, {
    points: [{
      x: 214,
      y: 211
    }, {
      x: 239,
      y: 135
    }, {
      x: 365,
      y: 231
    }, {
      x: 320,
      y: 336
    }, ],
    fill: 'navajoWhite',
    label: {
      text: 'D2',
      cx: 270,
      cy: 210,
      withLine: false,
      endX: null,
      endY: null
    },
  }, {
    points: [{
      x: 190,
      y: 223
    }, {
      x: 214,
      y: 211
    }, {
      x: 320,
      y: 336
    }, {
      x: 318,
      y: 346
    }, {
      x: 223,
      y: 346
    }],
    fill: 'tan',
    label: {
      text: 'T3',
      cx: 250,
      cy: 310,
      withLine: false,
      endX: null,
      endY: null
    },
  }, {
    points: [{
      x: 112,
      y: 347
    }, {
      x: 190,
      y: 223
    }, {
      x: 223,
      y: 346
    }],
    fill: 'peru',
    label: {
      text: 'T2',
      cx: 175,
      cy: 300,
      withLine: false,
      endX: null,
      endY: null
    },
  }, {
    points: [{
      x: 210,
      y: 105
    }, {
      x: 219,
      y: 105
    }, {
      x: 219,
      y: 68
    }, {
      x: 210,
      y: 67
    }],
    fill: 'red',
    label: {
      text: 'PD',
      cx: 170,
      cy: 87,
      withLine: true,
      endX: 215,
      endY: 88
    },
  }];

  // label styles
  var labelfontsize = 12;
  var labelfontface = 'verdana';
  var labelpadding = 3;

  var legendTexts = ['PD = Partial Discharge', 'T1 = Thermal fault < 300 celcius', '...'];


  // start drawing
  /////////////////////


  // draw pentagon
  drawPentagon(points);

  // draw colored segments inside pentagon
  for (var i = 0; i < segments.length; i++) {
    drawSegment(segments[i]);
  }
  moleculeLabel(points[0], centerPoint, 'CH4');
  moleculeLabel(points[1], centerPoint, 'CH2');
  moleculeLabel(points[2], centerPoint, 'H2');
  // draw legend
  drawLegend(legendTexts, 10, 10, 12.86);

  // end drawing
  /////////////////////

  function drawSegment(s) {
    // draw and fill the segment path
    ctx.beginPath();
    ctx.moveTo(s.points[0].x, s.points[0].y);
    for (var i = 1; i < s.points.length; i++) {
      ctx.lineTo(s.points[i].x, s.points[i].y);
    }
    ctx.closePath();
    ctx.fillStyle = s.fill;
    ctx.fill();
    ctx.lineWidth = 2;
    ctx.strokeStyle = 'black';
    ctx.stroke();
    // draw segment's box label
    if (s.label.withLine) {
      lineBoxedLabel(s, labelfontsize, labelfontface, labelpadding);
    } else {
      boxedLabel(s, labelfontsize, labelfontface, labelpadding);
    }
  }

  function boxedLabel(s, fontsize, fontface, padding) {
    var centerX = s.label.cx;
    var centerY = s.label.cy;
    var text = s.label.text;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle'
    ctx.font = fontsize + 'px ' + fontface
    var textwidth = ctx.measureText(text).width;
    var textheight = fontsize * 1.286;
    var leftX = centerX - textwidth / 2 - padding;
    var topY = centerY - textheight / 2 - padding;
    ctx.fillStyle = 'white';
    ctx.fillRect(leftX, topY, textwidth + padding * 2, textheight + padding * 2);
    ctx.lineWidth = 1;
    ctx.strokeRect(leftX, topY, textwidth + padding * 2, textheight + padding * 2);
    ctx.fillStyle = 'black';
    ctx.fillText(text, centerX, centerY);
  }


  function lineBoxedLabel(s, fontsize, fontface, padding) {
    var centerX = s.label.cx;
    var centerY = s.label.cy;
    var text = s.label.text;
    var lineToX = s.label.endX;
    var lineToY = s.label.endY;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle'
    ctx.font = fontsize + 'px ' + fontface
    var textwidth = ctx.measureText(text).width;
    var textheight = fontsize * 1.286;
    var leftX = centerX - textwidth / 2 - padding;
    var topY = centerY - textheight / 2 - padding;
    // the line
    ctx.beginPath();
    ctx.moveTo(leftX, topY + textheight / 2);
    ctx.lineTo(lineToX, topY + textheight / 2);
    ctx.strokeStyle = 'black';
    ctx.lineWidth = 1;
    ctx.stroke();
    // the boxed text
    ctx.fillStyle = 'white';
    ctx.fillRect(leftX, topY, textwidth + padding * 2, textheight + padding * 2);
    ctx.strokeRect(leftX, topY, textwidth + padding * 2, textheight + padding * 2);
    ctx.fillStyle = 'black';
    ctx.fillText(text, centerX, centerY);
  }

  function moleculeLabel(V, P, text) {
    var dx = V.x - P.x;
    var dy = V.y - P.y;
    var rAngle = Math.atan2(dy, dx);
    var padding = 15; // == how far outside the pentagon you want to go
    var outsideX = P.x + (P.radius + padding) * Math.cos(rAngle);
    var outsideY = P.y + (P.radius + padding) * Math.sin(rAngle);
    ctx.textAlign = 'center';
    ctx.textBaseline = 'middle';
    ctx.fillStyle = 'black';
    ctx.fillText(text, outsideX, outsideY);
  }


  /**
   * draw basic pentagon.
   **/
  function drawPentagon(points) {
    ctx.beginPath();
    for (var i = 0; i < points.length; i++) {
      ctx.lineTo(points[i].x, points[i].y);
    }

    ctx.strokeStyle = 'black';
    ctx.lineWidth = 1;
    ctx.stroke();
    ctx.closePath();

  }

  function drawLegend(texts, x, y, lineheight) {
    ctx.textAlign = 'left';
    ctx.textBaseline = 'top';
    ctx.fillStyle = 'black';
    ctx.font = '12px arial';
    for (var i = 0; i < texts.length; i++) {
      ctx.fillText(texts[i], x, y + i * lineheight);
    }
  }
})
body {
  background-color: ivory;
  padding: 10px;
}
#canvas {
  border: 1px solid red;
  margin: 0 auto;
}

1 个答案:

答案 0 :(得分:0)

最后的答案,非常感谢@markE。

var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
        
var points = [{x:397,y:149},{x:318,y:346},{x:112,y:347},{x:44,y:147},{x: 221,y:27},{x:397,y:149}];

// calc the polygon center mass
var cx,cy;
var totx=0;
var toty=0;
for(var i=0;i<points.length-1;i++){ // don't include the "closing" point in points[]
    totx+=points[i].x;
    toty+=points[i].y;
}
cx=totx/(points.length-1);
cy=toty/(points.length-1);

draw();

function draw(){
    // draw the polygon
    ctx.beginPath();
    ctx.moveTo(points[0].x,points[0].y);
    for(var i=1;i<points.length;i++){
        ctx.lineTo(points[i].x,points[i].y);
    }
    ctx.stroke();
    
    // draw the labels at their radial extension points
    ctx.textAlign='center';
    ctx.textBaseline='middle';
    var padding=20;
    for(var i=0;i<points.length-1;i++){
        var p=points[i];
        var dx=p.x-cx;
        var dy=p.y-cy;
        var dist=Math.sqrt(dx*dx+dy*dy);
        var rAngle=Math.atan2(dy,dx);
        var labelX=cx+(dist+padding)*Math.cos(rAngle);
        var labelY=cy+(dist+padding)*Math.sin(rAngle);
        ctx.fillText('label#'+i,labelX,labelY)
        
        // demo only, for points[0] draw the 
        //centerpoint and the radial extension point
        if(i==0){
            ctx.beginPath();
            ctx.moveTo(cx,cy);
            ctx.lineTo(labelX,labelY);
            ctx.moveTo(cx,cy);
            ctx.arc(cx,cy,5,0,Math.PI*2);
            ctx.moveTo(labelX,labelY);
            ctx.arc(labelX,labelY,3,0,Math.PI*2);
            ctx.strokeStyle='red';
            ctx.stroke();
            ctx.fillStyle='red';
            ctx.fill();
            ctx.strokeStyle='black';
            ctx.fillStyle='black';
        }
    }   
}
body{ background-color: ivory; }
#canvas{border:1px solid red; margin:0 auto; }
<canvas id="canvas" width=500 height=500></canvas>