我遇到一个问题,即将一个圆圈分成7块。 此刻我有一条线穿过圆圈的中心。 然后旋转并从画布的墙壁反弹。 我似乎无法弄清楚绘制7个相等的段并让它们在圆圈内旋转。 请查看我到目前为止所拥有的代码片段。 任何有关这方面的帮助将不胜感激。
提前谢谢。
<!DOCTYPE html>
<hmtl>
<head>
<meta charset="UTF-8">
<title>Canvas</title>
<!--change cnavas border color to black-->
<style type="text/css">
canvas{
border: 1px solid black;
}
</style>
</head>
<body>
<!-- Canvas one used as container for canvas-->
<canvas id="canvasOne" ></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvasOne");
var me = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
var animation;
var centerX = 125;
var centerY =125;
var radius = 100;
var ballDx = 2;
var ballDy = 2;
var theta = 0;
var thetaInc = 0.01;
function drawBall(){
me.clearRect(0,0,canvas.width,canvas.height);
centerX = centerX + ballDx;
centerY = centerY + ballDy;
me.beginPath();
me.arc(centerX,centerY,radius,0,Math.PI*2,false);
me.stroke();
me.fillStyle = "orange";
me.fill();
theta += thetaInc;
me.moveTo(centerX - radius*Math.cos(theta),centerY - radius*Math.sin(theta));
me.lineTo(centerX + radius*Math.cos(theta),centerY + radius*Math.sin(theta));
me.lineWidth = "2";
me.lineCap = "round";
me.strokeStyle = "black";
me.stroke();
if(centerY > canvas.height - radius || centerY - radius <0){
ballDy = -1*ballDy;
}
if(centerX > canvas.width - radius || centerX - radius < 0){
ballDx = -1*ballDx;
}
}
function animate(){
clearInterval(animation);
setInterval(drawBall,25);
}
animate();
</script>
</body>
</html>
答案 0 :(得分:1)
如果我理解正确,你几乎就在那里,但不是从圆上的一个点到一个完全相反的方向绘制一条线,而是从中心开始并以角度增量从theta
开始绘制七个半径1/7圈。
因为moveTo
在画布上开始一个新的子路径,所以在绘制所有子路径之后只需要描边。作为实现结果的简单修改的一个例子:
<!DOCTYPE html>
<hmtl>
<head>
<meta charset="UTF-8">
<title>Canvas</title>
<!--change cnavas border color to black-->
<style type="text/css">
canvas{
border: 1px solid black;
}
</style>
</head>
<body>
<!-- Canvas one used as container for canvas-->
<canvas id="canvasOne" ></canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvasOne");
var me = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
var animation;
var centerX = 125;
var centerY =125;
var radius = 100;
var ballDx = 2;
var ballDy = 2;
var theta = 0;
var thetaInc = 0.01;
var seventh = (Math.PI*2)/7; // add
var theta2 = 0; // add
function drawBall(){
me.clearRect(0,0,canvas.width,canvas.height);
centerX = centerX + ballDx;
centerY = centerY + ballDy;
me.beginPath();
me.arc(centerX,centerY,radius,0,Math.PI*2,false);
me.stroke();
me.fillStyle = "orange";
me.fill();
theta += thetaInc;
/* removed:
me.moveTo(centerX - radius*Math.cos(theta),centerY - radius*Math.sin(theta));
me.lineTo(centerX + radius*Math.cos(theta),centerY + radius*Math.sin(theta));
*/
for( var n = 0; n < 7; ++n) { // add loop to draw radii
theta2 = theta + n * seventh;
me.moveTo( centerX, centerY);
me.lineTo( centerX + radius*Math.cos(theta2), centerY + radius*Math.sin(theta2));
}
me.lineWidth = "2";
me.lineCap = "round";
me.strokeStyle = "black";
me.stroke();
if(centerY > canvas.height - radius || centerY - radius <0){
ballDy = -1*ballDy;
}
if(centerX > canvas.width - radius || centerX - radius < 0){
ballDx = -1*ballDx;
}
}
function animate(){
clearInterval(animation);
setInterval(drawBall,25);
}
animate();
</script>
</body>
</html>
但是,如果需要单独为这些线段着色,则需要在划动或填充之前将每个线段绘制为两个半径和弧度为2π/ 7弧度的单独路径。
答案 1 :(得分:0)
认为给定的答案有效,这不是解决问题的最佳方法。
如果您想要添加一些旋转的文本,图像或与球相关的任何其他图形内容,该怎么办?如果你想在球撞到墙壁时将球压扁一点,该怎么办?如果您将方向和位置作为渲染代码的一部分,这些都很困难。
您应该将您绘制的每个项目视为一个独立的实体(例如球)并创建一个描述球的对象,包括其行为update
函数,样式和渲染函数draw
该实体有自己的局部坐标系,围绕自己的中心(0,0)绘制。
const ballStyle = {
fillStyle : "orange",
lineWidth : "2",
lineCap : "round",
strokeStyle : "black",
};
const ball = {
x : 125,
y : 125,
radius : 100,
scale : 1,
dx : 2,
dy : 2,
rot : 0,
dRot : 0.1,
segments : 7,
style : ballStyle,
draw : drawBall,
}
function drawBall(){
var i;
const step = Math.PI * 2 / this.segments;
Object.assign(ctx,this.style);
ctx.beginPath();
ctx.arc(0, 0, this.radius, 0, Math.PI * 2);
ctx.fill();
for(i = 0; i < this.segments; i ++){
ctx.moveTo(0,0);
ctx.lineTo(Math.cos(i * step) * this.radius, Math.sin(i * step) * this.radius);
}
ctx.stroke();
}
因此,如果你调用函数ball.draw()
,那么球会在画布的左上角绘制它自己的坐标系。这不是你想要的。
这是您使用画布变换来定位和旋转对象的位置。
因此,创建一个通用函数,用于设置要绘制的对象的位置,比例和旋转。
function drawObject(ball) {
ctx.setTransform(ball.scale, 0, 0, ball.scale, ball.x, ball.y); // set position and scale
ctx.rotate(ball.rotation);
ball.draw();
}
现在您可以在任意位置渲染对象,并且位置,比例和旋转不会影响渲染代码。
该片段执行上述操作。我在球上添加了一个矩形,以说明旋转不需要额外的代码来向对象添加更多细节。还有一个第二个球(从原件复制)来说明一旦你设置了一个对象,制作它的副本很容易。
同样,当您制作动画时,不应使用setInterval
,因为它与显示硬件不同步。使用代码段
requestAnimationFrame
requestAnimationFrame(mainLoop); // start the animation at the next frame
const ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
const ballStyle = {
fillStyle: "orange",
lineWidth: "2",
lineCap: "round",
strokeStyle: "black",
};
const ball = {
x: 125,
y: 155,
radius: 100,
scale: 1,
dx: 2,
dy: 2.5,
rotation: 0,
dRot: 0.02,
segments: 7,
style: ballStyle,
draw: drawBall,
update: updateBall,
}
function updateBall() {
this.x += this.dx;
this.y += this.dy;
this.rotation += this.dRot;
var r = this.radius * this.scale;
if (this.x - r < 0) {
this.dx = Math.abs(this.dx);
this.x = r;
} else if (this.x + r > ctx.canvas.width) {
this.dx = -Math.abs(this.dx);
this.x = ctx.canvas.width - r;
}
if (this.y - r < 0) {
this.dy = Math.abs(this.dy);
this.y = r;
} else if (this.y + r > ctx.canvas.height) {
this.dy = -Math.abs(this.dy);
this.y = ctx.canvas.height - r;
}
}
function drawBall() {
var i;
const step = Math.PI * 2 / this.segments;
Object.assign(ctx, this.style);
ctx.beginPath();
ctx.arc(0, 0, this.radius, 0, Math.PI * 2);
ctx.rect(this.radius - 22, -5, 20, 10);
ctx.fill();
for (i = 0; i < this.segments; i++) {
ctx.moveTo(0, 0);
ctx.lineTo(Math.cos(i * step) * this.radius, Math.sin(i * step) * this.radius);
}
ctx.stroke();
}
// will draw any object that has the properties x,y,scale and rotation and the function draw.
function drawObject(ball) {
ctx.setTransform(ball.scale, 0, 0, ball.scale, ball.x, ball.y); // set position and scale
ctx.rotate(ball.rotation);
ball.draw();
}
// create a copy of the ball.
const ball1 = Object.assign(
{},
ball,
{
scale : 0.5,
segments : 9,
dx : -2,
dRot : - 0.02,
style : Object.assign(
{},
ballStyle,
{
lineWidth : 4,
fillStyle : "yellow"
}
),
}
);
function mainLoop() {
ctx.setTransform(1, 0, 0, 1, 0, 0); // restore default transform
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ball.update();
ball1.update();
drawObject(ball);
drawObject(ball1);
requestAnimationFrame(mainLoop);
}
&#13;
canvas {
border: 1px solid black;
}
&#13;
<canvas id="canvas"></canvas>
&#13;