html画布检查对象是不是成角度

Posted

技术标签:

【中文标题】html画布检查对象是不是成角度【英文标题】:html canvas check that object is in anglehtml画布检查对象是否成角度 【发布时间】:2018-06-21 05:59:15 【问题描述】:

我有一个圆圈和一个对象。 我想画一个具有指定散布的圆段,然后检查对象是否处于定义的角度,如果是,角度颜色将为红色,否则为绿色。但是我的代码在某些情况下不起作用...

在这种情况下它可以工作:

这也是:

但这里不是:

我知道我的角度检测代码部分并不完美,但我不知道我能做什么。

这是我的代码:

html:

<html>
    <head></head>
    <body>
        <canvas id="c"   style="background-color: #DDD"></canvas>
        <script src="script.js"></script>
    </body>
</html>

js:

window.addEventListener('mousemove', updateMousePos, false);
var canvas = document.getElementById("c");
var context = canvas.getContext("2d");

//mouse coordinates
var mx = 0, my = 0;

draw();

function draw()

    context.clearRect(0, 0, canvas.width, canvas.height);

    //object coordinates
    var ox = 350, oy = 260;

    context.beginPath();
    context.arc(ox,oy,5,0,2*Math.PI);
    context.fill();

    //circle
    var cx = 400, cy = 280;
    var r = 100;
    var segmentPoints = 20;
    var circlePoints = 40;
    var spread = Math.PI / 2;
    var mouseAngle = Math.atan2(my - cy, mx - cx); //get angle between circle center and mouse position

    context.beginPath();
    context.strokeStyle = "blue";
    context.moveTo(cx + r, cy);

    for(var i=0; i<circlePoints; i++)
    
        var a = 2 * Math.PI / (circlePoints - 1) * i;
        var x = cx + Math.cos(a) * r;
        var y = cy + Math.sin(a) * r;

        context.lineTo(x, y);
    

    context.lineTo(cx + r, cy);
    context.stroke();

    var objAngle = Math.atan2(oy - cy, ox - cx);

    var lowerBorder = mouseAngle - spread / 2;
    var biggerBorder = mouseAngle + spread / 2;

    /////////////////////////////////////////////ANGLES DETECTION PART
    if(objAngle >= lowerBorder && objAngle <= biggerBorder ||
       objAngle <= biggerBorder && objAngle >= lowerBorder)
    
        context.strokeStyle = "red";
    
    else
        context.strokeStyle = "green";

    context.lineWidth = 3;

    //angle center line
    context.beginPath();
    context.moveTo(cx, cy);
    context.lineTo(cx + Math.cos(mouseAngle) * r * 2, cy + Math.sin(mouseAngle) * r * 2);
    context.stroke();

    //draw spread arc
    context.beginPath();
    context.moveTo(cx, cy);

    for(var i=0; i<segmentPoints; i++)
    
        var a = mouseAngle - spread / 2 + spread / (segmentPoints - 1) * i; 
        var x = cx + Math.cos(a) * r;
        var y = cy + Math.sin(a) * r;

        context.lineTo(x, y);
    
    context.lineTo(cx, cy);
    context.stroke();

    //show degrees
    context.font = "20px Arial";
    context.fillText((lowerBorder * 180 / Math.PI).toFixed(2), Math.cos(lowerBorder) * r + cx, Math.sin(lowerBorder) * r + cy);
    context.fillText((biggerBorder * 180 / Math.PI).toFixed(2), Math.cos(biggerBorder) * r + cx, Math.sin(biggerBorder) * r + cy);
    context.fillText((mouseAngle * 180 / Math.PI).toFixed(2), Math.cos(mouseAngle) * r + cx, Math.sin(mouseAngle) * r + cy);

    //update
    setTimeout(function()  draw(); , 10);


//getting mouse coordinates
function updateMousePos(evt) 

    var rect = document.getElementById("c").getBoundingClientRect();
    mx = evt.clientX - rect.left;
    my = evt.clientY - rect.top;

【问题讨论】:

你在 strokeStype = "green"; 之后少了一个 ; 对于它的价值,对应于角度的数字似乎很奇怪。传统上,3 点钟是零度,随着角度的增加,您逆时针扫过。因此,前 2 个图表看起来没问题,尽管在每个图表之前都有一个错误的 - 【参考方案1】:

<!doctype html>
<html>
	<head>
		<meta charset="utf-8">
		<style>
			body 
				background-color: black;
			
			
			canvas 
				position: absolute;
				margin: auto;
				left: 0;
				right: 0;
				border: solid 1px white;
				border-radius: 10px;
			
		</style>
	</head>
	
	<body>
		<canvas id="canvas"></canvas>
		<script type="application/javascript">
			
			// Rotation here is being measured in Radians
			// Given two 2D vectors A & B, the angle between them can be drawn from this formula
			// A dot B = length(a) * length(b) * cos(angle)
			// if the vectors are normalized (the length is 1) the formula becomes
			// A dot B = cos(angle)
			// angle = acos(a.x * b.x + a.y * b.y)
			// So here you are concerned with the direction of the two vectors
			// One will be the vector facing outward from the middle of your arc segment
			// The other will be a directional vector from the point you want to do collision with to the center
			// of the circle
			
			var canvasWidth = 180;
			var canvasHeight = 160;
			var canvas = null;
			var ctx = null;
			var bounds = top: 0.0, left: 0.0;
			
			var circle = 
				x: (canvasWidth * 0.5)|0,
				y: (canvasHeight * 0.5)|0,
				radius: 50.0,
				rotation: 0.0, // In Radians
				arcSize: 1.0
			;
			
			var point = 
				x: 0.0,
				y: 0.0
			;
			
			window.onmousemove = function(e) 
				point.x = e.clientX - bounds.left;
				point.y = e.clientY - bounds.top;
			
			
			// runs after the page has loaded
			window.onload = function() 
				canvas = document.getElementById("canvas");
				canvas.width = canvasWidth;
				canvas.height = canvasHeight;
				bounds = canvas.getBoundingClientRect();
				ctx = canvas.getContext("2d");
				loop();
			
			
			function loop() 
				// Update Circle Rotation
				circle.rotation = circle.rotation + 0.025;
				if (circle.rotation > 2*Math.PI)  
					circle.rotation = 0.0;
				
				
				// Vector A (Point Pos -> Circle Pos)
				var aX = circle.x - point.x;
				var aY = circle.y - point.y;
				var aLength = Math.sqrt(aX * aX + aY * aY);
				
				// Vector B (The direction the middle of the arc is facing away from the circle)
				var bX = Math.sin(circle.rotation);
				var bY =-Math.cos(circle.rotation); // -1 is facing upward, not +1
				var bLength = 1.0;
				
				// Normalize vector A
				aX = aX / aLength;
				aY = aY / aLength;
				
				// Are we inside the arc segment?
				var isInsideRadius = aLength < circle.radius;
				var isInsideAngle = Math.abs(Math.acos(aX * bX + aY * bY)) < circle.arcSize * 0.5;
				var isInsideArc = isInsideRadius && isInsideAngle;
				
				// Clear the screen
				ctx.fillStyle = "gray";
				ctx.fillRect(0,0,canvasWidth,canvasHeight);
				
				// Draw the arc
				ctx.strokeStyle = isInsideArc ? "green" : "black";
				ctx.beginPath();
				ctx.moveTo(circle.x,circle.y);
				ctx.arc(
					circle.x,
					circle.y,
					circle.radius,
					circle.rotation - circle.arcSize * 0.5 + Math.PI * 0.5,
					circle.rotation + circle.arcSize * 0.5 + Math.PI * 0.5,
					false
				);
				ctx.lineTo(circle.x,circle.y);
				ctx.stroke();
				
				// Draw the point
				ctx.strokeStyle = "black";
				ctx.fillStyle = "darkred";
				ctx.beginPath();
				ctx.arc(
					point.x,
					point.y,
					5.0,
					0.0,
					2*Math.PI,
					false
				);
				ctx.fill();
				ctx.stroke();
				
				// This is better to use then setTimeout()
				// It automatically syncs the loop to 60 fps for you
				requestAnimationFrame(loop);
			
		
		</script>
	</body>
</html>

【讨论】:

以上是关于html画布检查对象是不是成角度的主要内容,如果未能解决你的问题,请参考以下文章

html 角度检查对象为空以显示/隐藏元素

使用html5画布在一个圆圈中以不同角度显示不同的值

画布从底部中心图像角度旋转?

如何在角度 chart.js 中更改画布高度和宽度

如何在角度中使用织物js将两个画布(外部和内部)保存为png

如何在 html 5 画布上旋转单个对象?