我正在建立一个动态雷达图,我审查了代码,并遵循了SO成员的建议。

这是我走的路,但似乎遇到了障碍:



var canv = document.getElementById('canvas');
var canv1 = document.getElementById('canvas1');
var point_xy = document.getElementById('point_xy');
var tipCanvas = document.getElementById("tip");
var tipCtx = tipCanvas.getContext("2d");
var point_xy_cords = [
  []
];
var pentagon_one = 24;
var pentagon_two = 18;
var pentagon_three = 12;
var pentagon_four = 6;
var pentagon_five = 0;
var circles = [];
var contx = canv.getContext('2d');
var contx1 = canv1.getContext('2d');
var offsetX = canv1.offsetLeft;
var offsetY = canv1.offsetTop;
contx.clearRect(0, 0, canv.width, canv.height);

function drawShape(ctx, x, y, points, radius1, radius2, alpha0) {
  //points: number of points (or number of sides for polygons)
  //radius1: "outer" radius of the star
  //radius2: "inner" radius of the star (if equal to radius1, a polygon is drawn)
  //angle0: initial angle (clockwise), by default, stars and polygons are 'pointing' up
  var radius_size = radius1;
  var i, angle, radius;
  if (radius2 !== radius1) {
    points = 2 * points;
  }
  for (var i = 0; i <= 5; i++) {
    var temp = [];
    contx1.beginPath();
    for (var j = 0; j <= 4; j++) {
      angle = j * 2 * Math.PI / points - Math.PI / 2 + alpha0;
      radius = j % 2 === 0 ? radius_size : radius_size;
      temp[j] = [(x + radius_size * Math.cos(angle)), (y + radius_size * Math.sin(angle))];
      ctx.lineTo(temp[j][0], temp[j][1]);
    }
    ctx.closePath();
    style(ctx);
    radius_size = radius_size - 20;
    point_xy_cords.push(temp);
  }
  point_xy.textContent = "[1] = " + point_xy_cords[1] + " y = " + point_xy_cords[1][1];
}

function style(ctx, fill) {
  ctx.strokeStyle = "rgba(0, 109, 0, 1)";
  ctx.lineWidth = 2;
  if (fill) {
    ctx.fillStyle = "rgba(74, 157, 33, 0.6)";
    ctx.fill();
  } else {
    ctx.stroke()
  }

  //contx.fill();
}

var radius = 2;

var Circle = function(x, y, radius) {
  this.left = x - radius;
  this.top = y - radius;
  this.right = x + radius;
  this.bottom = y + radius;
  this.point_clicked = [];

  this.clicked = function(){
    points[1][0] = x; //hardcoded part
    points[1][1] = y; //hardcoded part
    contx1.clearRect(0, 0, canv.width, canv.height);
    drawBackgroundPentagons(contx1);
    drawMainPentagon(contx1, points);
    drawPoints();
  }

  this.draw = function(ctx) {
    //Draw all points

    ctx.beginPath();
    ctx.arc(x, y, 2, 0, 2 * Math.PI, false);
    ctx.lineWidth = 1;
    ctx.strokeStyle = "rgba(74, 157, 33, 1)";
    ctx.fill();
    ctx.stroke();
  }

  this.containsPoint = function(x,y){
  	return (x < this.right && x > this.left && y > this.top && y < this.bottom);
  }
};

//Draw background
function drawBackgroundPentagons(ctx) {
  drawShape(ctx, 120, 120, 5, 100, 100, 0);
}
drawBackgroundPentagons(contx1);

//Draw all the points
function drawPoints(){
  for (var x = 1; x <= 5; x++){
    for (var y = 0; y <= 4; y++){
      var circle = new Circle(point_xy_cords[x][y][0], point_xy_cords[x][y][1], 8);
      circle.draw(contx1);
      circles.push(circle);
    }
  }
}
drawPoints();
function drawMainPentagon(ctx, points) {
  ctx.beginPath();
  ctx.moveTo(points[0][0], points[0][1]);
  for (var x = 1; x <= 4; x++) {
    ctx.lineTo(points[x][0], points[x][1]);
  }
    style(ctx, "fill");
  	ctx.closePath();
}

points = point_xy_cords[1];
drawMainPentagon(contx1, points);

function handleMouseDown(e, message) {

  point_xy.textContent = (message);
}

function getMousePos(canvas, evt) {
  var rect = canvas.getBoundingClientRect();
  return {
    x: evt.clientX - rect.left,
    y: evt.clientY - rect.top
  };
}

canv1.onmousedown = function(e) {
  var pos = getMousePos(canv1, e);
  var clickedX = pos.x;
  var clickedY = pos.y;


  var tooltipText = "nothing";

  for (var i = 0; i < circles.length; i++) {
    var circle = circles[i];
    if (circle.containsPoint(clickedX, clickedY)) {
      circle.clicked();
      return;
    }
	}
  tooltip("points[0]", clickedX, clickedY);
};

function tooltip(text, clickedX, clickedY) {
  tipCtx.fillStyle = "black";
  tipCtx.fillRect(0, 0, canvas.width, canvas.height);
  tipCtx.fillStyle = "white";
  tipCtx.fillText(text, 5, 10);
  tipCanvas.style.left = (clickedX + 15) + "px";
  tipCanvas.style.top = (clickedY - 26) + "px";
}

canv1.onmouseover = function(e) {
  return null;

}
canv1.onmouseout = function(e) {
  return null;
}
canv1.onmousemove = function(e) {
  return null;
}

#tip {
  left: -200px;
  top: 100px;
  position: absolute;
  float: left;
  maxWidth: 200px;
  backgroundColor: rgba(0, 0, 0, 0.8);
  border: rgba(45, 65, 45, 1);
  borderRadius: 5px;
  color: #f9f9f9;
  fontSize: 14px;
  padding: 5px;
  textAlign: left;
}

<div id="canvasesdiv" style="position:relative; width:400px; height:300px">
  <canvas id="tip" width=100 height=100 style="z-index: 3;"></canvas>
  <canvas id="canvas" style="z-index: 1;
position:absolute;
left:10px;
top:10px;
" height="300px" width="400">
    This text is displayed if your browser does not support HTML5 Canvas.
  </canvas>
  <canvas id="canvas1" style="z-index: 2;
position:absolute;
left:10px;
top:10px;
" height="300px" width="400">
    This text is displayed if your browser does not support HTML5 Canvas.
  </canvas>

</div>
<div id='point_xy'></div>





如果单击一个点,则假定将突出显示的五边形的点移到该单击的点。它可以工作,除了我不知道要添加什么条件才能移动突出显示的五边形的正确角。在上面的代码中,我已经对其进行了硬编码,因此无论您单击哪一点,它都会将指针移动到索引0处。

任何方向将不胜感激。

最佳答案

因此,您要让每个圈子知道它属于哪个spokeradii。像这样:

var Circle = function(x, y, radius, spoke, value) {
  this.x = x;
  this.y = y;
  this.radius = radius;
  this.spoke = spoke;
  this.value = value;


现在创建它们,如下所示:

function drawPoints() {
  for (var value = 1; value <= 5; value++){
    for (var spoke = 0; spoke <= 4; spoke++){
      var circle = new Circle(point_xy_cords[value][spoke][0], point_xy_cords[value][spoke][1], 8, spoke, value);
      circle.draw(contx1);
      circles.push(circle);
    }
  }
}


我将变量名称更改为有意义的名称。这里要注意的是,您混合使用代码来创建圆并使用代码来绘制圆。您不想这样做。在初始化时创建一次,并在进行更改(单击)时重新绘制它们。您不想每次重绘时都重新创建圆。

最后更改此:

// Circle
this.clicked = function(){
    points[this.spoke][0] = this.x;
    points[this.spoke][1] = this.y;
    updateCanvas();
}


在其他地方:

function updateCanvas() {
  contx1.clearRect(0, 0, canv.width, canv.height);
  drawBackgroundPentagons(contx1);
  drawMainPentagon(contx1, points);
  drawPoints();
}


如果我可以提出建议,请从最简单的代码开始。从显示圆和五边形开始,使它干净地工作并在其上构建。尝试使代码中的逻辑分开。在绘制时,可以在多个位置创建对象和初始化数组(例如coords),这既不必要,又意味着您可以一遍又一遍地进行操作,而不仅仅是一次。这里还有很多不必要的代码。

关于javascript - 动态雷达图跟踪点,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42965497/

10-12 13:35