How To Get The Value Of A Canvas . I have wheel which is rotating on mouse over the wheel stops now i want to echo out the value on which it was stopped. It is printing the whole array . Not the one on which the wheel stop.
$("#canvas").mouseover(function(){
backup= ctx;
alert(myData);
ctx = null;
});
this is the fiddle: https://jsfiddle.net/z61n9ccx/3/
Here is the full code:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var PI2 = Math.PI * 2;
var myData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var cx = 150;
var cy = 150;
var radius = 150;
var wheel = document.createElement('canvas');
var wheelCtx = wheel.getContext('2d');
var indicator = document.createElement('canvas');
var indicatorCtx = indicator.getContext('2d');
var angle = PI2 - PI2 / 4;
var myColor = [];
for (var i = 0; i < myData.length; i++) {
myColor.push(randomColor());
}
makeWheel();
makeIndicator();
requestAnimationFrame(animate);
function makeWheel() {
wheel.width = wheel.height = radius * 2 + 2;
wheelCtx.lineWidth = 1;
wheelCtx.font = '40px Pacifico, cursive';
wheelCtx.textAlign = 'center';
wheelCtx.textBaseline = 'middle';
var cx = wheel.width / 2;
var cy = wheel.height / 2;
var sweepAngle = PI2 / myData.length;
var startAngle = 0;
for (var i = 0; i < myData.length; i++) {
// calc ending angle based on starting angle
var endAngle = startAngle + sweepAngle;
// draw the wedge
wheelCtx.beginPath();
wheelCtx.moveTo(cx, cy);
wheelCtx.arc(cx, cy, radius, startAngle, endAngle, false);
wheelCtx.closePath();
wheelCtx.fillStyle = myColor[i];
wheelCtx.strokeStyle = 'black';
wheelCtx.fill();
wheelCtx.stroke();
// draw the label
var midAngle = startAngle + (endAngle - startAngle) / 2;
var labelRadius = radius * .85;
var x = cx + (labelRadius) * Math.cos(midAngle);
var y = cy + (labelRadius) * Math.sin(midAngle);
wheelCtx.fillStyle = 'gold';
wheelCtx.fillText(myData[i], x, y);
wheelCtx.strokeText(myData[i], x, y);
// increment angle
startAngle += sweepAngle;
}
}
function makeIndicator() {
indicator.width = indicator.height = radius + radius / 10;
indicatorCtx.font = '40px Georgia';
indicatorCtx.textAlign = 'center';
indicatorCtx.textBaseline = 'middle';
indicatorCtx.fillStyle = 'skyblue';
indicatorCtx.strokeStyle = 'blue';
indicatorCtx.lineWidth = 1;
var cx = indicator.width / 2;
var cy = indicator.height / 2;
indicatorCtx.beginPath();
indicatorCtx.moveTo(cx - radius / 8, cy);
indicatorCtx.lineTo(cx, cy - indicator.height / 2);
indicatorCtx.lineTo(cx + radius / 8, cy);
indicatorCtx.closePath();
indicatorCtx.fillStyle = 'skyblue'
indicatorCtx.fill();
indicatorCtx.stroke();
indicatorCtx.beginPath();
indicatorCtx.arc(cx, cy, radius / 3, 0, PI2);
indicatorCtx.closePath();
indicatorCtx.fill();
indicatorCtx.stroke();
indicatorCtx.fillStyle = 'blue';
indicatorCtx.fillText('Prizes', cx, cy);
}
function animate(time) {
ctx.clearRect(0, 0, cw, ch);
ctx.translate(cw / 2, ch / 2);
ctx.rotate(angle);
ctx.drawImage(wheel, -wheel.width / 2, -wheel.height / 2);
ctx.rotate(-angle);
ctx.translate(-cw / 2, -ch / 2);
ctx.drawImage(indicator, cw / 2 - indicator.width / 2, ch / 2 - indicator.height / 2)
angle += PI2 / 360;
requestAnimationFrame(animate);
}
function randomColor() {
return ('#' + Math.floor(Math.random() * 16777215).toString(16));
}
var backup = null;
$("#canvas").mouseover(function() {
backup = ctx;
alert(myData);
ctx = null;
});
$("#canvas").mouseout(function() {
// backup= ctx;
ctx = backup;
animate();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<canvas id="canvas" width="600" height="600" style="background-color:#ffff">
</canvas>
I added a counter, and then use that as a index: https://jsfiddle.net/Twisty/L6nws9yz/2/
HTML
<canvas id="canvas" width="310" height="310" style="background-color:#ffff">
</canvas>
<div id="counterBox">
<label>Counter:</label>
<span></span>
</div>
<div id="countBox">
<label>Index:</label>
<span></span>
</div>
JS
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var PI2 = Math.PI * 2;
var myData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var cx = 150;
var cy = 150;
var radius = 150;
var wheel = document.createElement('canvas');
var wheelCtx = wheel.getContext('2d');
var indicator = document.createElement('canvas');
var indicatorCtx = indicator.getContext('2d');
var currentSelection = 12;
var counter = 360;
var angle = PI2 - PI2 / 4;
var myColor = [];
for (var i = 0; i < myData.length; i++) {
myColor.push(randomColor());
}
makeWheel();
makeIndicator();
requestAnimationFrame(animate);
function makeWheel() {
wheel.width = wheel.height = radius * 2 + 2;
wheelCtx.lineWidth = 1;
wheelCtx.font = '40px Pacifico, cursive';
wheelCtx.textAlign = 'center';
wheelCtx.textBaseline = 'middle';
var cx = wheel.width / 2;
var cy = wheel.height / 2;
var sweepAngle = PI2 / myData.length;
var startAngle = 0;
for (var i = 0; i < myData.length; i++) {
// calc ending angle based on starting angle
var endAngle = startAngle + sweepAngle;
// draw the wedge
wheelCtx.beginPath();
wheelCtx.moveTo(cx, cy);
wheelCtx.arc(cx, cy, radius, startAngle, endAngle, false);
wheelCtx.closePath();
wheelCtx.fillStyle = myColor[i];
wheelCtx.strokeStyle = 'black';
wheelCtx.fill();
wheelCtx.stroke();
// draw the label
var midAngle = startAngle + (endAngle - startAngle) / 2;
var labelRadius = radius * .85;
var x = cx + (labelRadius) * Math.cos(midAngle);
var y = cy + (labelRadius) * Math.sin(midAngle);
wheelCtx.fillStyle = 'gold';
wheelCtx.fillText(myData[i], x, y);
wheelCtx.strokeText(myData[i], x, y);
// increment angle
startAngle += sweepAngle;
}
}
function makeIndicator() {
indicator.width = indicator.height = radius + radius / 10;
indicatorCtx.font = '40px Georgia';
indicatorCtx.textAlign = 'center';
indicatorCtx.textBaseline = 'middle';
indicatorCtx.fillStyle = 'skyblue';
indicatorCtx.strokeStyle = 'blue';
indicatorCtx.lineWidth = 1;
var cx = indicator.width / 2;
var cy = indicator.height / 2;
indicatorCtx.beginPath();
indicatorCtx.moveTo(cx - radius / 8, cy);
indicatorCtx.lineTo(cx, cy - indicator.height / 2);
indicatorCtx.lineTo(cx + radius / 8, cy);
indicatorCtx.closePath();
indicatorCtx.fillStyle = 'skyblue'
indicatorCtx.fill();
indicatorCtx.stroke();
indicatorCtx.beginPath();
indicatorCtx.arc(cx, cy, radius / 3, 0, PI2);
indicatorCtx.closePath();
indicatorCtx.fill();
indicatorCtx.stroke();
indicatorCtx.fillStyle = 'blue';
indicatorCtx.fillText('Prizes', cx, cy);
}
var lastloop = new Date;
var thisloop = new Date;
var fps = 0;
function animate(time) {
ctx.clearRect(0, 0, cw, ch);
ctx.translate(cw / 2, ch / 2);
ctx.rotate(angle);
ctx.drawImage(wheel, -wheel.width / 2, -wheel.height / 2);
ctx.rotate(-angle);
ctx.translate(-cw / 2, -ch / 2);
ctx.drawImage(indicator, cw / 2 - indicator.width / 2, ch / 2 - indicator.height / 2)
angle += PI2 / 360;
thisloop = new Date;
fps = 1000 / (thisloop - lastloop);
lastloop = thisloop;
counter--;
if (counter < 1) {
counter = 360;
}
$("#counterBox span").html(counter);
var index = counter / 30;
$("#countBox span").html(Math.round(index));
//$("#fpsBox span").html(fps);
requestAnimationFrame(animate);
}
function randomColor() {
return ('#' + Math.floor(Math.random() * 16777215).toString(16));
}
var backup = null;
$("#canvas").mouseover(function() {
backup = ctx;
alert(myData[Math.round(counter / 30)-1]);
ctx = null;
});
$("#canvas").mouseout(function() {
// backup= ctx;
ctx = backup;
animate();
});
Counter is set to 360 and then each frame decreases it. Take that and divide by 30 (360 / 12), and you can count each wedge. I round up and now I have 0 - 11 count.
Update
I moved the Index into a global space. To make it more precise, I used the % operator like so:
counter--;
if (counter == 0) {
counter = 360;
}
$("#counterBox span").html(counter);
if (counter % 30 === 0) {
index--;
}
$("#countBox span").html(Math.round(index));
if (index === 0) {
index = 12;
}
When you mouse over, you get the selection:
$("#canvas").mouseover(function() {
backup = ctx;
alert(index);
ctx = null;
});
I wrapped everything in an IIFE so that there aren't any global variables.
Updated Example
It's important to note that the angle calculation is:
angle = degree * Math.PI / 180;
With that being said, you can calculate the current degree and normalize it using:
(angle * (180 / Math.PI)) % 360
I added a function called getValue which takes an angle parameter:
function getValue(angle) {
var degree = (angle * (180 / Math.PI)) % 360,
offsetIndex = (Math.floor(degree / sweepDegree) + offset) % myData.length,
normalizedIndex = Math.abs(offsetIndex - (myData.length - 1));
return myData[normalizedIndex];
}
It essentially calculates the current degree, normalizes it taking into account what the initial degree was when the animation was initialized (which is the offset). Then it divides the degree by the sweep degree, which is 30 in this case since there are 12 items (i.e., 360/12 === 30) and rounds down.
var sweepDegree = 360 / myData.length;
var offset = (360 - (angle * (180 / Math.PI)) % 360) / sweepDegree;
This should work for a varying number of array items. In other words, nothing is hardcoded for a set length of 12 items (like in your case), so it should work for any given number of items.
Then you can simply use the getValue function in the mouseover event listener:
Updated Example
$("#canvas").mouseover(function() {
// ...
alert(getValue(angle));
});
(function() {
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var cw = canvas.width;
var ch = canvas.height;
var PI2 = Math.PI * 2;
var myData = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var cx = 150;
var cy = 150;
var radius = 150;
var wheel = document.createElement('canvas');
var wheelCtx = wheel.getContext('2d');
var indicator = document.createElement('canvas');
var indicatorCtx = indicator.getContext('2d');
var angle = PI2 - PI2 / 4;
var sweepDegree = 360 / myData.length;
var offset = (360 - (angle * (180 / Math.PI)) % 360) / sweepDegree;
var myColor = [];
for (var i = 0; i < myData.length; i++) {
myColor.push(randomColor());
}
makeWheel();
makeIndicator();
requestAnimationFrame(animate);
function makeWheel() {
wheel.width = wheel.height = radius * 2 + 2;
wheelCtx.lineWidth = 1;
wheelCtx.font = '40px Pacifico, cursive';
wheelCtx.textAlign = 'center';
wheelCtx.textBaseline = 'middle';
var cx = wheel.width / 2;
var cy = wheel.height / 2;
var sweepAngle = PI2 / myData.length;
var startAngle = 0;
for (var i = 0; i < myData.length; i++) {
// calc ending angle based on starting angle
var endAngle = startAngle + sweepAngle;
// draw the wedge
wheelCtx.beginPath();
wheelCtx.moveTo(cx, cy);
wheelCtx.arc(cx, cy, radius, startAngle, endAngle, false);
wheelCtx.closePath();
wheelCtx.fillStyle = myColor[i];
wheelCtx.strokeStyle = 'black';
wheelCtx.fill();
wheelCtx.stroke();
// draw the label
var midAngle = startAngle + (endAngle - startAngle) / 2;
var labelRadius = radius * .85;
var x = cx + (labelRadius) * Math.cos(midAngle);
var y = cy + (labelRadius) * Math.sin(midAngle);
wheelCtx.fillStyle = 'gold';
wheelCtx.fillText(myData[i], x, y);
wheelCtx.strokeText(myData[i], x, y);
// increment angle
startAngle += sweepAngle;
}
}
function makeIndicator() {
indicator.width = indicator.height = radius + radius / 10;
indicatorCtx.font = '40px Georgia';
indicatorCtx.textAlign = 'center';
indicatorCtx.textBaseline = 'middle';
indicatorCtx.fillStyle = 'skyblue';
indicatorCtx.strokeStyle = 'blue';
indicatorCtx.lineWidth = 1;
var cx = indicator.width / 2;
var cy = indicator.height / 2;
indicatorCtx.beginPath();
indicatorCtx.moveTo(cx - radius / 8, cy);
indicatorCtx.lineTo(cx, cy - indicator.height / 2);
indicatorCtx.lineTo(cx + radius / 8, cy);
indicatorCtx.closePath();
indicatorCtx.fillStyle = 'skyblue'
indicatorCtx.fill();
indicatorCtx.stroke();
indicatorCtx.beginPath();
indicatorCtx.arc(cx, cy, radius / 3, 0, PI2);
indicatorCtx.closePath();
indicatorCtx.fill();
indicatorCtx.stroke();
indicatorCtx.fillStyle = 'blue';
indicatorCtx.fillText('Prizes', cx, cy);
}
function animate(time) {
if (ctx === null) {
return
}
ctx.clearRect(0, 0, cw, ch);
ctx.translate(cw / 2, ch / 2);
ctx.rotate(angle);
ctx.drawImage(wheel, -wheel.width / 2, -wheel.height / 2);
ctx.rotate(-angle);
ctx.translate(-cw / 2, -ch / 2);
ctx.drawImage(indicator, cw / 2 - indicator.width / 2, ch / 2 - indicator.height / 2)
angle += PI2 / 360;
requestAnimationFrame(animate);
}
function randomColor() {
return ('#' + Math.floor(Math.random() * 16777215).toString(16));
}
var backup = null;
$("#canvas").mouseover(function() {
backup = ctx;
ctx = null;
alert(getValue(angle));
});
$("#canvas").mouseout(function() {
ctx = backup;
animate();
});
function getValue(angle) {
var degree = (angle * (180 / Math.PI)) % 360,
offsetIndex = (Math.floor(degree / sweepDegree) + offset) % myData.length,
normalizedIndex = Math.abs(offsetIndex - (myData.length - 1));
return myData[normalizedIndex];
}
})();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<canvas id="canvas" width="600" height="600" style="background-color:#ffff">
</canvas>
Related
I've been working on a JavaScript raycasting project, I use DDA to cast the rays. I want to add textures, but I'm not exactly sure how to do that (maybe exporting images in the .ppm file format, but I wouldn't know how to actually cast the textures on each wall).
Here's my code (two canvases, #canvas is for the 2D world, #canvas2 is for the projection):
const canvas = document.querySelector("#canvas");
const ctx = canvas.getContext("2d");
const canvas2 = document.querySelector("#canvas2");
const ctx2 = canvas2.getContext("2d");
let width = 513;
let height = 513;
let width2 = 1024;
let height2 = 512;
const columns = 2000;
let columnWidth = width2 / columns;
canvas.width = width;
canvas.height = height;
canvas2.width = width2;
canvas2.height = height2;
let deltaTime = 0;
let lastFrame = Date.now();
const moveSpeed = 3.5;
const rotationSpeed = 175;
const FOV = 80;
let map = [
"##########",
"#...#....#",
"#...#....#",
"### #....#",
"#...#....#",
"# ###....#",
"#...#### #",
"#........#",
"#........#",
"##########"
];
let tileHeight = 512 / map.length;
let tileWidth = 512 / map[0].length;
const player = {
x: 2.5,
y: 8.5,
heading: 270
}
const keyMap = {};
const deg2rad = deg => deg * Math.PI / 180;
const willCollide = ({ xC, yC }, { x, y, w, h }) => {
boundingBox = {
left: x - w / 2,
right: x + w / 2,
top: y - h / 2,
bottom: y + h / 2
}
return xC > boundingBox.left && xC < boundingBox.right && yC > boundingBox.top && yC < boundingBox.bottom;
}
const handlePlayerMovement = () => {
if (keyMap.w) {
let dx = Math.cos(player.heading * Math.PI / 180);
let dy = Math.sin(player.heading * Math.PI / 180);
const xCheck = player.x + dx * 5 * deltaTime;
const yCheck = player.y + dy * 5 * deltaTime;
let canMoveX = true;
let canMoveY = true;
if (map[Math.floor(yCheck)][Math.floor(player.x)] == "#") canMoveY = false;
if (map[Math.floor(player.y)][Math.floor(xCheck)] == "#") canMoveX = false;
if (canMoveX) player.x += dx * moveSpeed * deltaTime;
if (canMoveY) player.y += dy * moveSpeed * deltaTime;
}
if (keyMap.s) {
let dx = Math.cos((player.heading * Math.PI / 180) + Math.PI);
let dy = Math.sin((player.heading * Math.PI / 180) + Math.PI);
const xCheck = player.x + dx * 5 * deltaTime;
const yCheck = player.y + dy * 5 * deltaTime;
let canMoveX = true;
let canMoveY = true;
if (map[Math.floor(yCheck)][Math.floor(player.x)] == "#") canMoveY = false;
if (map[Math.floor(player.y)][Math.floor(xCheck)] == "#") canMoveX = false;
if (canMoveX) player.x += dx * moveSpeed * deltaTime;
if (canMoveY) player.y += dy * moveSpeed * deltaTime;
}
if (keyMap.a) player.heading -= rotationSpeed * deltaTime;
if (keyMap.d) player.heading += rotationSpeed * deltaTime;
}
const generateColumns = () => {
for (let i = 0; i < columns; i++) {
let collided = false;
let angle = (player.heading - FOV / 2) + (i / columns) * FOV;
let dx = Math.cos(angle * Math.PI / 180);
let dy = Math.sin(angle * Math.PI / 180);
let stepX = Math.sign(dx);
let stepY = Math.sign(dy);
let dispX = dx == 0 ? 0 : Math.abs(1 / dx);
let dispY = dy == 0 ? 0 : Math.abs(1 / dy);
let distX = (dx > 0 ? Math.ceil(player.x) - player.x : player.x - Math.floor(player.x)) * dispX;
let distY = (dy > 0 ? Math.ceil(player.y) - player.y : player.y - Math.floor(player.y)) * dispY;
let gridX = Math.floor(player.x);
let gridY = Math.floor(player.y);
let dist = 0;
let side = 0;
while (!collided) {
if (distX < distY) {
gridX += stepX;
dist = distX;
distX += dispX;
side = 1;
} else {
gridY += stepY;
dist = distY;
distY += dispY;
side = 0;
}
// ctx.beginPath();
// ctx.arc((player.x + dist * dx) * tileWidth, (player.y + dist * dy) * tileHeight, 3, 0, Math.PI * 2);
// ctx.fill();
if (map[gridY][gridX] == "#") {
collided = true;
let fix_dist = dist * Math.cos((player.heading - angle) * Math.PI / 180); // fisheye fix
let h = 550 / fix_dist;
let fill = `rgb(0, ${side ? 220 : 255}, 0`;
ctx2.fillStyle = fill;
ctx2.fillRect(Math.round(columnWidth * i), height2 / 2 - h / 2, columnWidth + 1, h);
}
}
ctx.strokeStyle = "#fff";
ctx.beginPath();
ctx.moveTo(player.x * tileWidth, player.y * tileHeight);
ctx.lineTo((player.x + dist * dx) * tileWidth, (player.y + dist * dy) * tileHeight);
ctx.stroke();
}
}
const update = () => {
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, width, height);
ctx2.fillStyle = "#000";
ctx2.fillRect(0, 0, width2, height2 / 2);
ctx2.fillStyle = "#fff";
ctx2.fillRect(0, height2 - height2 / 2, width2, height2 / 2);
if (player.heading < 0) player.heading += 360;
if (player.heading > 360) player.heading -= 360;
handlePlayerMovement();
for (let y = 0; y < map.length; y++) {
for (let x = 0; x < map[y].length; x++) {
ctx.fillStyle = "#fff";
if (map[y][x] == "#") ctx.fillRect(x * tileWidth, y * tileHeight, tileWidth, tileHeight);
ctx.fillStyle = "#666";
ctx.fillRect(0, y * tileHeight, 512, 1);
ctx.fillRect(x * tileWidth, 0, 1, 512);
}
}
generateColumns();
deltaTime = (Date.now() / 1000 - lastFrame / 1000);
lastFrame = Date.now();
requestAnimationFrame(update);
}
update();
window.onkeydown = (e) => {
keyMap[e.key.toLowerCase()] = true;
}
window.onkeyup = (e) => {
keyMap[e.key.toLowerCase()] = false;
}
I have a circle, and a object.
I want to draw a circle segment with specified spread, and next check that the object is in defined angle, if it is, angle color will be red, otherwise green. But my code does not work in some cases...
in this case it work:
in this too:
but here it isn't:
I know that my angle detection code part is not perfect, but I have no idea what I can do.
This is my code:
html:
<html>
<head></head>
<body>
<canvas id="c" width="800" height="480" 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;
}
<!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>
I'm trying to create a Structure as shown in the Screenshot below. Is there a way to build an Algorithm for this in JavaScript to get the X and Y Coordinates of each red Point in chronological order to generate an infinite Spiral depending on a specific amount?
Screenshot of how it should look and work
This Code generates me a regular Hexagon:
function hexagon(centerX, centerY) {
var ctx = canvas.getContext('2d');
var x = centerX + Math.cos(Math.PI * 2 / 6) * 50;
var y = centerY + Math.sin(Math.PI * 2 / 6) * 50;
ctx.beginPath();
ctx.moveTo(x, y);
for (var i = 1; i < 7; i++) {
x = centerX + Math.cos(Math.PI * 2 / 6 * i) * 50;
y = centerY + Math.sin(Math.PI * 2 / 6 * i) * 50;
ctx.lineTo(x, y);
}
ctx.closePath();
ctx.stroke();
}
And this is the Cluster-function so far:
function cluster(centerX, centerY, count) {
var ctx = canvas.getContext('2d');
for (var i = 0; i < count; i++) {
if (i == 0) {
var x = centerX;
var y = centerY;
} else {
var x = centerX + Math.cos(-Math.PI / 2) * (100 * (Math.sqrt(3) / 2));
var y = centerY + Math.sin(-Math.PI / 2) * (100 * (Math.sqrt(3) / 2));
}
hexagon(x, y);
}
}
Thank you!
Your cluster function could be like this:
function cluster(centerX, centerY, count) {
var x = centerX,
y = centerY,
angle = Math.PI / 3,
dist = Math.sin(angle) * 100,
i = 1,
side = 0;
hexagon(x, y);
count--;
while (count > 0) {
for (var t = 0; t < Math.floor((side+4)/6)+(side%6==0) && count; t++) {
y = y - dist * Math.cos(side * angle);
x = x - dist * Math.sin(side * angle);
hexagon(x, y);
count--;
}
side++;
}
}
function hexagon(centerX, centerY) {
var ctx = canvas.getContext('2d');
var x = centerX + Math.cos(Math.PI * 2 / 6) * 50;
var y = centerY + Math.sin(Math.PI * 2 / 6) * 50;
ctx.beginPath();
ctx.moveTo(x, y);
for (var i = 1; i < 7; i++) {
x = centerX + Math.cos(Math.PI * 2 / 6 * i) * 50;
y = centerY + Math.sin(Math.PI * 2 / 6 * i) * 50;
ctx.lineTo(x, y);
}
ctx.closePath();
ctx.stroke();
}
function cluster(centerX, centerY, count) {
var x = centerX,
y = centerY,
angle = Math.PI / 3,
dist = Math.sin(angle) * 100,
i = 1,
side = 0;
hexagon(x, y);
count--;
while (count > 0) {
for (var t = 0; t < Math.floor((side+4)/6)+(side%6==0) && count; t++) {
y = y - dist * Math.cos(side * angle);
x = x - dist * Math.sin(side * angle);
hexagon(x, y);
count--;
}
side++;
}
}
cluster(200,230,9);
<canvas id="canvas" width="400" height="400"></canvas>
hello all i used canvas to create pie chart by surfing through stackoverflow and i found the below code but i need only for 2 values instead of 5 because my pie chart doesnt appear fully .below chv2 and chs2 are js values
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var lastend = 0;
var data = [chv2, chs2]; // If you add more data values make sure you add more colors
var myTotal = 0; // Automatically calculated so don't touch
var myColor = ['red', 'green']; // Colors of each slice
for (var e = 0; e < data.length; e++) {
myTotal += data[e];
}
alert(myTotal);
for (var i = 0; i < data.length; i++) {
ctx.fillStyle = myColor[i];
ctx.beginPath();
ctx.moveTo(canvas.width / 2, canvas.height / 2);
// Arc Parameters: x, y, radius, startingAngle (radians), endingAngle (radians), antiClockwise (boolean)
ctx.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 * (data[i] / myTotal)), false);
ctx.lineTo(canvas.width / 2, canvas.height / 2);
ctx.fill();
lastend += Math.PI * 2 * (data[i] / myTotal);
}
<canvas id="canvas" width="400" height="300">
This text is displayed if your browser does not support HTML5 Canvas.
</canvas>
I think you missed the chv2 and chs2 varible declaration.
Please check this code
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var lastend = 0;
var chv2= 20;
var chs2= 40;
var data = [chv2,chs2]; // If you add more data values make sure you add more colors
var myTotal = 0; // Automatically calculated so don't touch
var myColor = ['red','green']; // Colors of each slice
for (var e = 0; e < data.length; e++) {
myTotal += data[e];
}
alert(myTotal);
for (var i = 0; i < data.length; i++) {
ctx.fillStyle = myColor[i];
ctx.beginPath();
ctx.moveTo(canvas.width / 2, canvas.height / 2);
// Arc Parameters: x, y, radius, startingAngle (radians), endingAngle (radians), antiClockwise (boolean)
ctx.arc(canvas.width / 2, canvas.height / 2, canvas.height / 2, lastend, lastend + (Math.PI * 2 * (data[i] / myTotal)), false);
ctx.lineTo(canvas.width / 2, canvas.height / 2);
ctx.fill();
lastend += Math.PI * 2 * (data[i] / myTotal);
}
Fiddle
Hope this will help you.
I have some html5 and javascript code to create a spinning roulette wheel. It is split up into 14 outcomes. My question is, how can I get some unique HTML code to display per each outcome of the wheel. For example, if the wheel lands on Business, some text will appear below the wheel that has information on Business.
Here is my HTML code and below it is a link to a working example:
<!--[if IE]><script type="text/javascript" src="/sites/default/files/1010/source/excanvas.js"></script><![endif]-->
<input type="button" value="spin" onclick="spin();" style="float: left;" />
<canvas id="wheelcanvas" width="800" height="750"></canvas>
<script type="application/javascript">
var colors = ["#B8D430", "#3AB745", "#029990", "#3501CB",
"#2E2C75", "#673A7E", "#CC0071", "#F80120",
"#F35B20", "#FB9A00", "#FFCC00", "#FEF200", "#B2DF00", "#5C8300"];
var classes = ["Business", "Office Education", "Continuing Care Assistant", "Practical Nursing",
"Primary Care Paramedic", "Early Childhood Education", "Cooking", "Electrician",
"Heavy Equipment Operator", "Industrial Mechanic - Millwright", "Plumbing & Pipefitting", "Truck Driver Training", "Welding", "Power Engineering"];
var startAngle = 0;
var arc = Math.PI / 7;
var spinTimeout = null;
var spinArcStart = 10;
var spinTime = 0;
var spinTimeTotal = 0;
var ctx;
function draw() {
drawRouletteWheel();
}
function drawRouletteWheel() {
var canvas = document.getElementById("wheelcanvas");
if (canvas.getContext) {
var outsideRadius = 300;
var textRadius = 260;
var insideRadius = 100;
ctx = canvas.getContext("2d");
ctx.clearRect(5,0,1000,1000);
ctx.strokeStyle = "black";
ctx.lineWidth = 2;
ctx.font = 'bold 10px sans-serif';
for(var i = 0; i < 14; i++) {
var angle = startAngle + i * arc;
ctx.fillStyle = colors[i];
ctx.beginPath();
ctx.arc(400, 400, outsideRadius, angle, angle + arc, false);
ctx.arc(400, 400, insideRadius, angle + arc, angle, true);
ctx.stroke();
ctx.fill();
ctx.save();
ctx.shadowOffsetX = -1;
ctx.shadowOffsetY = -1;
ctx.shadowBlur = 0;
ctx.shadowColor = "rgb(220,220,220)";
ctx.fillStyle = "black";
ctx.translate(400 + Math.cos(angle + arc / 2) * textRadius, 400 + Math.sin(angle + arc / 2) * textRadius);
ctx.rotate(angle + arc / 2 + Math.PI / 2);
var text = classes[i];
ctx.fillText(text, -ctx.measureText(text).width / 2, 0);
ctx.restore();
}
//Arrow
ctx.fillStyle = "black";
ctx.beginPath();
ctx.moveTo(400 - 4, 400 - (outsideRadius + 5));
ctx.lineTo(400 + 4, 400 - (outsideRadius + 5));
ctx.lineTo(400 + 4, 400 - (outsideRadius - 5));
ctx.lineTo(400 + 9, 400 - (outsideRadius - 5));
ctx.lineTo(400 + 0, 400 - (outsideRadius - 13));
ctx.lineTo(400 - 9, 400 - (outsideRadius - 5));
ctx.lineTo(400 - 4, 400 - (outsideRadius - 5));
ctx.lineTo(400 - 4, 400 - (outsideRadius + 5));
ctx.fill();
}
}
function spin() {
spinAngleStart = Math.random() * 10 + 10;
spinTime = 0;
spinTimeTotal = Math.random() * 3 + 4 * 1000;
rotateWheel();
}
function rotateWheel() {
spinTime += 30;
if(spinTime >= spinTimeTotal) {
stopRotateWheel();
return;
}
var spinAngle = spinAngleStart - easeOut(spinTime, 0, spinAngleStart, spinTimeTotal);
startAngle += (spinAngle * Math.PI / 180);
drawRouletteWheel();
spinTimeout = setTimeout('rotateWheel()', 30);
}
function stopRotateWheel() {
clearTimeout(spinTimeout);
var degrees = startAngle * 180 / Math.PI + 90;
var arcd = arc * 180 / Math.PI;
var index = Math.floor((360 - degrees % 360) / arcd);
ctx.save();
ctx.font = 'bold 30px sans-serif';
var text = classes[index]
ctx.fillText(text, 400 - ctx.measureText(text).width / 2, 400 + 10);
ctx.restore();
document.getElementById('wheelResult').innerHTML = 'Test' + text;
}
function easeOut(t, b, c, d) {
var ts = (t/=d)*t;
var tc = ts*t;
return b+c*(tc + -3*ts + 3*t);
}
draw();
</script>
<p id="wheelResult"></p>
http://www.ctrc.sk.ca/wheel.html
There are a couple of ways to do it but this is the way I would do it.
You could create a div tag with the css style of display:none and then set it with the info desired and hide and show it as needed.
Example:
<script>
var htmlData = ['<h1>Business</h1><br><span>What is Business?</span><br>...', ...];
....
function spin()
{
//Hide description box.
document.getElementById('idDescriptionBox').style.display = 'none';
spinAngleStart = Math.random() * 10 + 10;
....
}
....
function stopRotateWheel()
{
....
//Set description and display it.
var descriptionBox = document.getElementById('idDescriptionBox');
descriptionBox.innerHTML = htmlData[index];
descriptionBox.style.display = 'block';
}
....
</script>
<div id="idDescriptionBox" style="display:none;">
<!--Description info in here-->
....
</div>