Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 31.12.2018, 13:56
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 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.
Ответить с цитированием
  #2 (permalink)  
Старый 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>
Ответить с цитированием
  #3 (permalink)  
Старый 31.12.2018, 17:48
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 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.
Ответить с цитированием
  #4 (permalink)  
Старый 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>
Ответить с цитированием
  #5 (permalink)  
Старый 31.12.2018, 20:51
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 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>
Ответить с цитированием
  #6 (permalink)  
Старый 31.12.2018, 21:51
Профессор
Отправить личное сообщение для Nexus Посмотреть профиль Найти все сообщения от Nexus
 
Регистрация: 04.12.2012
Сообщений: 3,734

Rise, у меня проблема с "arcTo" была, а не с "arc".
В итоге все на "arc" и переделал.

рони, еще раз спасибо, но я оставлю свое решение с "arc", "arcTo" слишком геморойный метод.
Ответить с цитированием
  #7 (permalink)  
Старый 31.12.2018, 22:44
Профессор
Отправить личное сообщение для Rise Посмотреть профиль Найти все сообщения от Rise
 
Регистрация: 07.11.2013
Сообщений: 4,662

Nexus, ну у вас и с arc тригонометрия осталась.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск