如何使用画布从中心到起始角度减小线条大小?

时间:2018-12-20 13:56:15

标签: html5 canvas html5-canvas

我正在进行R gauge小部件定制。使用画布属性,我必须将Gauge的针号从中心针减小到“开始角度”。

this.drawNeedle = this.DrawNeedle = function (value, color, index) {
var type = prop['chart.needle.type'];
co.lineWidth = 0.5;
co.strokeStyle = 'gray';
co.fillStyle = color;
var angle = (this.endAngle - this.startAngle) * ((value - this.min) / (this.max - this.min));
angle += this.startAngle;
if (typeof (prop['chart.needle.size']) == 'object' && prop['chart.needle.size'] && typeof (prop['chart.needle.size'][index]) == 'number') {
  var size = prop['chart.needle.size'][index];
} else if (typeof (prop['chart.needle.size']) == 'number') {
  var size = prop['chart.needle.size'];
} else {
  var size = this.radius - 25 - prop['chart.border.width'];
}
if (type == 'line') {
  co.beginPath();
  co.lineWidth = prop['chart.needle.width'];
  co.strokeStyle = color;
  co.arc(this.centerx, this.centery, 82, angle, angle + 0.0001, false);
  // co.moveTo(this.centerx-58, this.centery-58);
  // co.lineTo(this.centerx-43, this.centery-43);
  co.lineTo(this.centerx, this.centery);
  if (prop['chart.needle.tail']) {
    co.arc(this.centerx, this.centery, this.radius * 0.2, angle + RG.PI, angle + 0.00001 + RG.PI, false);
  }
  co.lineTo(this.centerx, this.centery);
  co.stroke();
} else {
  co.beginPath();
  co.arc(this.centerx, this.centery, size, angle, angle + 0.00001, false);
  co.arc(this.centerx, this.centery, this.centerpinRadius * 0.5, angle + RG.HALFPI, angle + 0.00001 + RG.HALFPI, false);
  if (prop['chart.needle.tail']) {
    co.arc(this.centerx, this.centery, this.radius * 0.2, angle + RG.PI, angle + 0.00001 + RG.PI, false);
  }
  co.arc(this.centerx, this.centery, this.centerpinRadius * 0.5, angle - RG.HALFPI, angle - 0.00001 - RG.HALFPI, false);
  co.stroke();
  co.fill();
  this.angle = angle;
}

};

enter image description here

代替大针(从中心到起始角度),小针的尺寸应类似于下图。

enter image description here

1 个答案:

答案 0 :(得分:1)

请阅读我在代码中的评论

const canvas = document.getElementById("canvas");
const co = canvas.getContext("2d");
let cw = canvas.width = 200,
  cx = cw / 2;
let ch = canvas.height = 200,
  cy = ch / 2;

//gauge starts at a1
let a1 = 120*Math.PI/180;
//gauge ends at a1
let a2 = 60*Math.PI/180;
// arrow angle
let a = -60*Math.PI/180;
//gauge angle
let R = 82;
// arrow starts at this distance from the center
let r = 70;
// the center
let c = {x:100,y:100}

// coords to draw the arrow
let x1 = c.x+r*Math.cos(a);
let y1 = c.x+r*Math.sin(a);
let x2 = c.x+(R+5)*Math.cos(a);
let y2 = c.x+(R+5)*Math.sin(a);

co.lineWidth = 5;
co.strokeStyle = 'white';
co.lineCap = "round";
//draw the gauge
co.beginPath();
co.arc(c.x, c.y, R, a1, a2);
co.stroke();
//draw the arrow
co.beginPath();
co.moveTo(x1, y1);
co.lineTo(x2, y2);
co.stroke();
body {
  background-color: #222;
}
canvas {
  border:1px solid #999;
}
<canvas id="canvas"></canvas>

更新

OP评论:指针应指向刻度值,该值将动态更新。这就是我动态执行的方式:

我正在添加输入类型范围以动态更改角度的值

const canvas = document.getElementById("canvas");
const co = canvas.getContext("2d");
let cw = (canvas.width = 200),
  cx = cw / 2;
let ch = (canvas.height = 200),
  cy = ch / 2;

// arrow angle
let a = aval.getAttribute("value") * Math.PI / 180;
//gauge starts at a1
let a1 = aval.getAttribute("min") * Math.PI / 180;
//gauge ends at a1
let a2 = aval.getAttribute("max") * Math.PI / 180;

//gauge angle
let R = 82;
// arrow starts at this distance from the center
let r = 70;
// the center
let c = { x: 100, y: 100 };
co.lineWidth = 5;
co.strokeStyle = "white";
co.lineCap = "round";
// a function to draw the gauge
function drawGauge() {
  //draw the gauge
  co.beginPath();
  co.arc(c.x, c.y, R, a1, a2);
  co.stroke();
}
// a function to draw the arrow
function drawArrow(a) {
  // coords to draw the arrow
  let x1 = c.x + r * Math.cos(a);
  let y1 = c.x + r * Math.sin(a);
  let x2 = c.x + (R + 5) * Math.cos(a);
  let y2 = c.x + (R + 5) * Math.sin(a);
  //draw the arrow
  co.beginPath();
  co.moveTo(x1, y1);
  co.lineTo(x2, y2);
  co.stroke();
}

drawGauge();
drawArrow(a);

aval.addEventListener("input", () => {
  // on input the angle of the arrow is changing
  let a = parseInt(aval.value) * Math.PI / 180;
  // clear the canvas
  co.clearRect(0, 0, cw, ch);
  // and redraw everything
  drawGauge();
  drawArrow(a);
});
body {
  background-color: #222;
}
canvas {
  border:1px solid #999;
}
<canvas id="canvas"></canvas>
<input id="aval" type="range" min="-240" max="60" value="-60" />

更新2

OP正在评论:

  

我的最小值是40,最大值是700 .....所以我需要根据这些值范围之间的值来显示针。

为此,我需要将角度映射到这些值,所以我添加了一个映射函数,并更新了代码:

const canvas = document.getElementById("canvas");
const co = canvas.getContext("2d");
let cw = (canvas.width = 200),
  cx = cw / 2;
let ch = (canvas.height = 200),
  cy = ch / 2;


let min = parseInt(aval.getAttribute("min"));// min value
let a_min = -240 * Math.PI / 180;// min angle to draw the gauge
let max = parseInt(aval.getAttribute("max"));// max value
let a_max = 60 * Math.PI / 180;// max angle to draw the gauge
let val = parseInt(aval.getAttribute("value"));
let angle = getAngle(val) * Math.PI / 180;


//gauge angle
let R = 82;
// arrow starts at this distance from the center
let r = 70;
// the center
let c = { x: 100, y: 100 };
co.lineWidth = 5;
co.strokeStyle = "white";
co.lineCap = "round";
// a function to draw the gauge
function drawGauge() {
  //draw the gauge
  co.beginPath();
  co.arc(c.x, c.y, R, a_min, a_max);
  co.stroke();
}
// a function to draw the arrow
function drawArrow(a) {
  // coords to draw the arrow
  let x1 = c.x + r * Math.cos(a);
  let y1 = c.x + r * Math.sin(a);
  let x2 = c.x + (R + 5) * Math.cos(a);
  let y2 = c.x + (R + 5) * Math.sin(a);
  //draw the arrow
  co.beginPath();
  co.moveTo(x1, y1);
  co.lineTo(x2, y2);
  co.stroke();
}

drawGauge();
drawArrow(angle);

aval.addEventListener("input", () => {
  // on input the angle of the arrow is changing
  let val = parseInt(aval.value);
  let angle = getAngle(val);
  // clear the canvas
  co.clearRect(0, 0, cw, ch);
  // and redraw everything
  drawGauge();
  drawArrow(angle);
});

//a p5.js function
function map5(n, a, stop1, start2, stop2, withinBounds) {
  var newval = (n - a) / (stop1 - a) * (stop2 - start2) + start2;
  if (!withinBounds) {
    return newval;
  }
  if (start2 < stop2) {
    return this.constrain(newval, start2, stop2);
  } else {
    return this.constrain(newval, stop2, start2);
  }
};

function constrain(n, low, high) {
  return Math.max(Math.min(n, high), low);
};

function getAngle(val){
  return map5(val, min, max, a_min, a_max)
}
body {
  background-color: #222;
}
canvas {
  border:1px solid #999;
}
<canvas id="canvas"></canvas>
<input id="aval" type="range" min="40" max="700" value="460" />