我正在创建像半圆一样的速度计,我已经成功创造了所有颜色的半圆。请参阅以下设计:
我面临的问题是创建将充当指针的三角形。它会在300到850之间移动。在这个范围内,这个值将达到什么值。
<canvas id="myCanvas" height="350" width="666">
</canvas>
JS:
window.onload = function(){
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
context.font = "14px Trebuchet MS";
context.fillStyle = "#aaaaaa";
context.fillText("300", 60, 218);
context.font = "14px Trebuchet MS";
context.fillStyle = "#aaaaaa";
context.fillText("850", 280, 218);
// drawArcShadow x y rad sAng eAng clockwise line fill
drawArcShadow(180, 200, 100, 0, 180, true, "#eeeeee","white");
function drawArcShadow(xPos, yPos, radius, startAngle, endAngle, clockwise, lineColor, fillColor) {
var startAngle = startAngle * (Math.PI/180);
var endAngle = endAngle * (Math.PI/180);
var radius = radius;
context.strokeStyle = lineColor;
context.fillStyle = fillColor;
context.lineWidth = 20;
context.beginPath();
context.arc(xPos, yPos, radius, startAngle, endAngle, clockwise);
context.fill();
context.stroke();
}
// drawArc x y rad sAng eAng clockwise line fill
drawArc(180, 200, 110, 0, 180, true, "#c1634a","rgba(255, 255, 255, 0)");
drawArc(180, 200, 110, 0, 263, true, "#ab5741","rgba(255, 255, 255, 0)");
drawArc(180, 200, 110, 0, 264, true, "#e59636","rgba(255, 255, 255, 0)");
drawArc(180, 200, 110, 0, 288, true, "#ce8631","rgba(255, 255, 255, 0)");
drawArc(180, 200, 110, 0, 289, true, "#e8d932","rgba(255, 255, 255, 0)");
drawArc(180, 200, 110, 0, 302, true, "#d0c52d","rgba(255, 255, 255, 0)");
drawArc(180, 200, 110, 0, 303, true, "#aecd9c","rgba(255, 255, 255, 0)");
drawArc(180, 200, 110, 0, 320, true, "#8db872","rgba(255, 255, 255, 0)");
function drawArc(xPos, yPos, radius, startAngle, endAngle, clockwise, lineColor, fillColor) {
var startAngle = startAngle * (Math.PI/180);
var endAngle = endAngle * (Math.PI/180);
var radius = radius;
context.strokeStyle = lineColor;
context.fillStyle = fillColor;
context.lineWidth = 20;
context.beginPath();
context.arc(xPos, yPos, radius, startAngle, endAngle, clockwise);
context.fill();
context.stroke();
}
};
答案 0 :(得分:2)
这个问题已经多次得到解答,但我觉得你需要在你的代码逻辑中做一些更正。
要围绕画布中的某个点旋转形状,请使用translate(x,y)
和rotate(radian)
方法。
首先,将上下文移动到旋转锚点,然后相应地旋转,最后再次平移以提供所需的偏移
将您的背景视为可以移动和旋转的纸张。
在你的代码片段中,你有很大的抗锯齿效果。这是因为您使所有弧从角度0开始。绘制弧时,浏览器将创建半透明像素,以使线条看起来平滑。但是如果你在相同的位置绘制多个弧,这些像素越来越不透明,导致这些可见的伪像。
这是你的代码,有点重构:
var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
function drawTriangle() {
var ratio = Math.PI / (slider.max - slider.min);
var angle = ((slider.value - slider.min) * ratio) + Math.PI;
var radius = 110;
// first move our cursor to the center of our arcs
context.translate(180, 200);
// then rotate the whole context
context.rotate(angle);
// move our cursor to our arc's radius
context.translate(radius, 0);
// draw the triangle
context.fillStyle = 'black';
context.beginPath();
// this draws the triangle around its center point
context.lineTo(10, -5);
context.lineTo(10, 5)
context.lineTo(-10, 0)
context.closePath();
context.fill();
// place back our context's transfrom to its default
context.setTransform(1, 0, 0, 1, 0, 0);
}
function drawArcShadow(xPos, yPos, radius, startAngle, endAngle, clockwise, lineColor, fillColor) {
var startAngle = startAngle * (Math.PI / 180);
var endAngle = endAngle * (Math.PI / 180);
var radius = radius;
context.strokeStyle = lineColor;
context.fillStyle = fillColor;
context.lineWidth = 20;
context.beginPath();
context.arc(xPos, yPos, radius, startAngle, endAngle, clockwise);
context.fill();
context.stroke();
}
function draw() {
// clear the canvas
context.clearRect(0, 0, canvas.width, canvas.height);
// text
context.font = "14px Trebuchet MS";
context.fillStyle = "#aaaaaa";
// since we don't change the properties, no need to tell the browser to do so
context.fillText("300", 60, 218);
context.fillText("850", 280, 218);
// drawArcShadow x y rad sAng eAng clockwise line fill
drawArcShadow(180, 200, 100, 0, 180, true, "#eeeeee", "white");
// drawArc x y rad sAng eAng ANTIclockwise line fill
// be careful, 6th argument of arc() is ANTI-clockwise boolean
// here I changed all start angle to avoid anti-aliasing artifacts + I removed the transparent fill parameter
drawArc(180, 200, 110, 263, 180, true, "#c1634a", null);
drawArc(180, 200, 110, 264, 263, true, "#ab5741", null);
drawArc(180, 200, 110, 288, 264, true, "#e59636", null);
drawArc(180, 200, 110, 289, 288, true, "#ce8631", null);
drawArc(180, 200, 110, 302, 289, true, "#e8d932", null);
drawArc(180, 200, 110, 303, 302, true, "#d0c52d", null);
drawArc(180, 200, 110, 320, 303, true, "#aecd9c", null);
drawArc(180, 200, 110, 0, 320, true, "#8db872", null);
drawTriangle();
}
function drawArc(xPos, yPos, radius, startAngle, endAngle, clockwise, lineColor, fillColor) {
var startAngle = startAngle * (Math.PI / 180);
var endAngle = endAngle * (Math.PI / 180);
context.strokeStyle = lineColor;
context.fillStyle = fillColor;
context.lineWidth = 20;
context.beginPath();
context.arc(xPos, yPos, radius, startAngle, endAngle, clockwise);
// instead of filling transparent, which produces nothing, just don't pass the fillColor parameter and don't call fill().
fillColor && context.fill();
context.stroke();
}
slider.oninput = draw;
draw();
<input type="range" id="slider" min="300" max="850">
<canvas id="myCanvas" height="350" width="666"></canvas>