31.12.2018, 13:56
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,734
|
|
CanvasRenderingContext2D.arcTo
Здравствуйте.
С наступающим новым годом.
Помогите закрасить часть окружности, никак не могу сообразить что я делаю не так.
Метод "drawSection".
Заранее благодарю.
https://jsfiddle.net/m36bkLjh/
<canvas id="canvas" width="400" height="400"></canvas>
<script>
class Circle{
/**
* @param {Canvas} canvas
*/
constructor(canvas){
this.canvas=canvas;
this.radius=canvas.width/2*0.8;
}
/**
* @return {Canvas}
*/
getCanvas(){
return this.canvas;
}
/**
* @param {number} radius
* @return {Circle}
*/
setRadius(radius){
this.radius=radius;
return this;
}
/**
* @return {number}
*/
getRadius(){
return this.radius;
}
/**
* @return {Circle}
*/
draw(){
const cnv=this.getCanvas();
const ctx=cnv.getContext('2d');
const center=[
cnv.width/2,
cnv.height/2
];
ctx.beginPath();
ctx.arc(
center[0],
center[1],
this.getRadius(),
0,
2*Math.PI
);
ctx.stroke();
ctx.fill();
return this;
}
/**
* @param {number} angle
* @return {Circle}
*/
*!*
drawSection(angle){
*/!*
const cnv=this.getCanvas();
const ctx=cnv.getContext('2d');
const center=[
cnv.width/2,
cnv.height/2
];
const radius=this.getRadius();
const x=center[0];
const y=center[1];
angle=180-angle/2;
const points=[
[
radius*Math.sin(-angle*Math.PI/180)+x,
radius*Math.cos(-angle*Math.PI/180)+y,
],
[
radius*Math.sin(angle*Math.PI/180)+x,
radius*Math.cos(angle*Math.PI/180)+y,
]
];
ctx.beginPath();
ctx.moveTo(points[0][0],points[0][1]);
ctx.lineTo(x,y);
ctx.lineTo(points[1][0],points[1][1]);
ctx.stroke();
//Заливка
*!*
ctx.beginPath();
ctx.fillStyle='#F00';
ctx.strokeStyle='#F00';
ctx.moveTo(x,y);
//ctx.lineTo(points[0][0],points[0][1]);
ctx.arcTo(
points[0][0],
points[0][1],
points[1][0],
points[1][1],
radius
);
//ctx.lineTo(x,y);
ctx.stroke();
ctx.fill();
*/!*
return this;
}
}
const circle=new Circle(document.getElementById('canvas'));
circle.getCanvas().getContext('2d').fillStyle='#F5F5F5';
circle.draw().drawSection(45);
</script>
Последний раз редактировалось Nexus, 31.12.2018 в 14:13.
|
|
31.12.2018, 16:16
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,072
|
|
Nexus,
строка 104 и 105 нужна формула, какая именно не знаю.
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
class Circle{
/**
* @param {Canvas} canvas
*/
constructor(canvas){
this.canvas=canvas;
this.radius=canvas.width/2*0.8;
}
/**
* @return {Canvas}
*/
getCanvas(){
return this.canvas;
}
/**
* @param {number} radius
* @return {Circle}
*/
setRadius(radius){
this.radius=radius;
return this;
}
/**
* @return {number}
*/
getRadius(){
return this.radius;
}
/**
* @return {Circle}
*/
draw(){
const cnv=this.getCanvas();
const ctx=cnv.getContext('2d');
const center=[
cnv.width/2,
cnv.height/2
];
ctx.beginPath();
ctx.arc(
center[0],
center[1],
this.getRadius(),
0,
2*Math.PI
);
ctx.stroke();
ctx.fill();
return this;
}
/**
* @param {number} angle
* @return {Circle}
*/
drawSection(angle){
const cnv=this.getCanvas();
const ctx=cnv.getContext('2d');
const center=[
cnv.width/2,
cnv.height/2
];
const radius=this.getRadius();
const x=center[0];
const y=center[1];
angle=180 - angle/2;
const points=[
[
radius*Math.sin(-angle*Math.PI/180)+x,
radius*Math.cos(-angle*Math.PI/180)+y,
],
[
radius*Math.sin(angle*Math.PI/180)+x,
radius*Math.cos(angle*Math.PI/180)+y,
]
];
ctx.beginPath();
ctx.moveTo(points[0][0],points[0][1]);
ctx.lineTo(x,y);
ctx.lineTo(points[1][0],points[1][1]);
ctx.stroke();
//Заливка
ctx.beginPath();
ctx.fillStyle='#F00';
ctx.strokeStyle='#F00';
ctx.moveTo(x,y);
ctx.lineTo(points[0][0],points[0][1]);
ctx.arcTo(212, 32, points[1][0],points[1][1], radius);
ctx.lineTo(x,y);
ctx.stroke();
ctx.fill();
return this;
}
}
const circle=new Circle(document.getElementById('canvas'));
circle.getCanvas().getContext('2d').fillStyle='#F5F5F5';
circle.draw().drawSection(45);
</script>
</body>
</html>
|
|
31.12.2018, 17:48
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,734
|
|
рони, спасибо, я используя метод arc сделал, с помощью окружности.
https://jsfiddle.net/m36bkLjh/1/
https://jsfiddle.net/m36bkLjh/2/
<canvas id="canvas" width="400" height="400"></canvas>
<script>
class Circle{
/**
* @param {Canvas} canvas
*/
constructor(canvas){
this.canvas=canvas;
this.radius=canvas.width/2*0.8;
}
/**
* @return {Canvas}
*/
getCanvas(){
return this.canvas;
}
/**
* @param {number} radius
* @return {Circle}
*/
setRadius(radius){
this.radius=radius;
return this;
}
/**
* @return {number}
*/
getRadius(){
return this.radius;
}
/**
* @return {Circle}
*/
draw(){
const cnv=this.getCanvas();
const ctx=cnv.getContext('2d');
const center=[
cnv.width/2,
cnv.height/2
];
ctx.beginPath();
ctx.arc(
center[0],
center[1],
this.getRadius(),
0,
2*Math.PI
);
ctx.stroke();
ctx.fill();
return this;
}
/**
* @param {number} angle
* @return {Circle}
*/
drawSection(angle){
const cnv=this.getCanvas();
const ctx=cnv.getContext('2d');
const center=[
cnv.width/2,
cnv.height/2
];
const radius=this.getRadius();
const x=center[0];
const y=center[1];
angle=(angle%360)/2;
const radian=(180-angle)*Math.PI/180;
const points=[
[
radius*Math.sin(-radian)+x,
radius*Math.cos(-radian)+y,
],
[
radius*Math.sin(radian)+x,
radius*Math.cos(radian)+y,
]
];
ctx.beginPath();
ctx.moveTo(points[0][0],points[0][1]);
ctx.lineTo(x,y);
ctx.lineTo(points[1][0],points[1][1]);
ctx.stroke();
//Заливка
ctx.beginPath();
ctx.fillStyle='#F00';
ctx.strokeStyle='#F00';
ctx.moveTo(x,y);
ctx.lineTo(points[0][0],points[0][1]);
ctx.arc(
x,
y,
radius,
(270-angle)*Math.PI/180,
(angle-90)*Math.PI/180
);
ctx.lineTo(x,y);
ctx.stroke();
ctx.fill();
return this;
}
}
const circle=new Circle(document.getElementById('canvas'));
circle.getCanvas().getContext('2d').fillStyle='#F5F5F5';
circle.draw().drawSection(45);
</script>
Последний раз редактировалось Nexus, 31.12.2018 в 17:59.
|
|
31.12.2018, 19:42
|
|
Профессор
|
|
Регистрация: 27.05.2010
Сообщений: 33,072
|
|
Nexus,
... надо условие добавить какое для yy
<!DOCTYPE html>
<html>
<head>
<title>Untitled</title>
<meta charset="utf-8">
</head>
<body>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
class Circle{
/**
* @param {Canvas} canvas
*/
constructor(canvas){
this.canvas=canvas;
this.radius=canvas.width/2*0.8;
}
/**
* @return {Canvas}
*/
getCanvas(){
return this.canvas;
}
/**
* @param {number} radius
* @return {Circle}
*/
setRadius(radius){
this.radius=radius;
return this;
}
/**
* @return {number}
*/
getRadius(){
return this.radius;
}
/**
* @return {Circle}
*/
draw(){
const cnv=this.getCanvas();
const ctx=cnv.getContext('2d');
const center=[
cnv.width/2,
cnv.height/2
];
ctx.beginPath();
ctx.arc(
center[0],
center[1],
this.getRadius(),
0,
2*Math.PI
);
ctx.stroke();
ctx.fill();
return this;
}
/**
* @param {number} angle
* @return {Circle}
*/
drawSection(angle){
const cnv=this.getCanvas();
const ctx=cnv.getContext('2d');
const center=[
cnv.width/2,
cnv.height/2
];
const radius=this.getRadius();
const x=center[0];
const y=center[1];
angle=180 - angle/2;
const points=[
[
radius*Math.sin(-angle*Math.PI/180)+x,
radius*Math.cos(-angle*Math.PI/180)+y,
],
[
radius*Math.sin(angle*Math.PI/180)+x,
radius*Math.cos(angle*Math.PI/180)+y,
]
];
ctx.beginPath();
ctx.moveTo(points[0][0],points[0][1]);
ctx.lineTo(x,y);
ctx.lineTo(points[1][0],points[1][1]);
ctx.stroke();
//Заливка
ctx.beginPath();
ctx.fillStyle='#F00';
ctx.strokeStyle='#F00';
ctx.moveTo(x,y);
ctx.lineTo(points[0][0],points[0][1]);
let yy = y + (radius / Math.cos(angle*Math.PI/180));
ctx.arcTo(x, yy, points[1][0],points[1][1], radius);
ctx.lineTo(x,y);
ctx.stroke();
ctx.fill();
return this;
}
}
const circle=new Circle(document.getElementById('canvas'));
const ctx=circle.getCanvas().getContext('2d');
let angle=0;
const framesPerSecond=60;
const step=30/framesPerSecond;
setTimeout(function run(){
ctx.clearRect(0,0,canvas.width,canvas.height);
ctx.fillStyle='#F5F5F5';
circle.draw().drawSection(angle=(angle+step)%360);
setTimeout(run,1000/framesPerSecond);
},1000/framesPerSecond);
</script>
</body>
</html>
|
|
31.12.2018, 20:51
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
Там всё дело в moveTo, нужно начинать путь с центра круга, по-умолчанию путь arc идет не с центра, а с начала дуги.
<canvas id="canvas" width="400" height="250" style="background:beige"></canvas>
<script>
const ctx = document.getElementById('canvas').getContext('2d');
class Circle {
constructor(x, y, radius) {
this.x = x;
this.y = y;
this.radius = radius;
this.degree = Math.PI / 180;
}
draw(ctx, fillStyle, strokeStyle, startAngle, endAngle, lineWidth) {
ctx.beginPath();
if ((endAngle - startAngle) % 360) ctx.moveTo(this.x, this.y);
ctx.arc(this.x, this.y, this.radius, startAngle * this.degree, endAngle * this.degree);
ctx.closePath();
ctx.fillStyle = fillStyle;
ctx.fill();
ctx.lineWidth = lineWidth;
ctx.strokeStyle = strokeStyle;
ctx.stroke();
return this;
}
}
new Circle(ctx.canvas.width * 0.5, ctx.canvas.height * 0.5, ctx.canvas.height * 0.4)
.draw(ctx, 'aqua', 'blue', 0, 360, 8)
.draw(ctx, 'lime', 'green', 0, 90, 6)
.draw(ctx, 'pink', 'red', -120, -60, 4)
.draw(ctx, 'transparent', 'yellow', 260, 45, 2);
</script>
|
|
31.12.2018, 21:51
|
Профессор
|
|
Регистрация: 04.12.2012
Сообщений: 3,734
|
|
Rise, у меня проблема с "arcTo" была, а не с "arc".
В итоге все на "arc" и переделал.
рони, еще раз спасибо, но я оставлю свое решение с "arc", "arcTo" слишком геморойный метод.
|
|
31.12.2018, 22:44
|
Профессор
|
|
Регистрация: 07.11.2013
Сообщений: 4,662
|
|
Nexus, ну у вас и с arc тригонометрия осталась.
|
|
|
|