I have an ASP.NET application that allows users to click or tap on a Canvas to indicate pain locations on a body image. A body image is displayed on the Canvas and is the same size as the Canvas.
function drawBodyMap() {
var c = document.getElementById('myCanvas');
var ctx = c.getContext('2d');
var imageObj = new Image();
imageObj.src = 'https://.../body.jpg';
imageObj.onload = function () {
ctx.drawImage(imageObj, 0, 0, 600, 367);
};
}
<canvas id="myCanvas" width="600" height="367"></canvas>
<script>
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
var canvas = document.getElementById('myCanvas');
var ctx = canvas.getContext('2d');
canvas.addEventListener('mouseup', function (evt) {
if (ixPos > 9)
return;
var mousePos = getMousePos(canvas, evt);
bodyX[ixPos] = mousePos.x;
bodyY[ixPos] = mousePos.y;
painType[ixPos] = pain_type;
ixPos++;
ctx.beginPath();
ctx.arc(mousePos.x, mousePos.y, 8, 0, 2 * Math.PI);
if (pain_type == 1)
ctx.fillStyle = "#DC143C";
else if (pain_type == 2)
ctx.fillStyle = "#EA728A";
else if (pain_type == 3)
ctx.fillStyle = "#DAA520";
else if (pain_type == 4)
ctx.fillStyle = "#008000";
else if (pain_type == 5)
ctx.fillStyle = "#4169E1";
ctx.fill();
}, false);
</script>
The X,Y points added to the Canvas on the body image are saved to a database. These points are then loaded into a WPF application that displays the same body image on an XAML Canvas. C# code then adds the points over the image.
WPF CODE:
private void DisplayBodyPain()
{
List<BodyPain> pain = gFunc.sws.GetBodyPain(MemberID);
foreach (BodyPain bp in pain)
{
Border b = new Border();
b.Tag = bp.PainType.ToString();
b.Cursor = Cursors.Hand;
b.Width = 16;
b.Height = 16;
b.CornerRadius = new CornerRadius(8);
b.Background = GetPainBrush((byte)bp.PainType);
cvsBody.Children.Add(b);
Canvas.SetTop(b, bp.YPos);
Canvas.SetLeft(b, bp.XPos);
}
}
The problem I have is that the points drawn on the XAML Canvas are all slightly different from the points that were drawn on the HTML Canvas. Each point is not in exactly the same location.
Is there a way I can fix this? Should I be doing it differently?
HTML Canvas
WPF Canvas
I think you need to subtract the size of the marker from the coordinate where you want to place it. For the last two lines, try this instead:
Canvas.SetTop(b, bp.YPos - (b.Height / 2));
Canvas.SetLeft(b, bp.XPos - (b.Width / 2));
By subtracting half the marker's height and width, the center of the marker is placed on the desired coordinates.
I have created a horizontal line in HTML5 Canvas. I want to animate the line to move infinity up and down. Is it possible?
function horizontal_line() {
context.beginPath();
context.moveTo(100, 100);
context.lineTo(5000, 100);
context.strokeStyle = "Green";
context.stroke();
}
For an animation you will need to have a way to draw different frames, and in each frame you have to delete the previous one, calculate the new position of the line, and then draw the line again:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
ctx.strokeStyle = "Green";
var posY = 0;
var lineLength = 10;
var speed = 2;
function drawLine() {
ctx.beginPath();
ctx.moveTo(10, posY);
ctx.lineTo(10, posY+lineLength);
ctx.stroke();
}
function moveLine () {
posY += speed;
if (posY < 0 || posY > canvas.height) {
speed = speed * -1;
}
}
function loop() {
// clear old frame;
ctx.clearRect(0,0,canvas.width, canvas.height);
moveLine();
drawLine();
requestAnimationFrame(loop);
}
requestAnimationFrame(loop);
<canvas id="canvas"></canvas>
In this example requestAnimationFrame is what provides you the frames you need, so the function loop() gets called over and over again. In there we clear the old frame with clearRect(), calculate the new position, and then we draw the new Line with drawLine().
EDIT::
I have converted the various points to (x,y) just as I wanted. I changed the name from bolt to drop because I already have an established shape named drop. However, it will not draw on the canvas. I replaced the coordinates with a leaf shape I also drew and converted to (x,y) and it worked fine. I can't figure out what's so different about my bolt shape.
context.beginPath();
context.moveTo(drop.x,drop.y);
context.moveTo(drop.x+140,drop.y+28);
context.lineTo(drop.x+24,drop.y+28);
context.moveTo(drop.x+24,drop.y+28);
context.lineTo(drop.x-2,drop.y+25);
context.moveTo(drop.x-2,drop.y+25);
context.lineTo(drop.x+17,drop.y+25);
context.moveTo(drop.x+17,drop.y+25);
context.lineTo(drop.x-18,drop.y+53);
context.moveTo(drop.x-18,drop.y+53);
context.lineTo(drop.x-3,drop.y+54);
context.moveTo(drop.x-3,drop.y+54);
context.lineTo(drop.x-47,drop.y+77);
context.moveTo(drop.x-47,drop.y+77);
context.lineTo(drop.x-31,drop.y+59);
context.moveTo(drop.x-31,drop.y+59);
context.lineTo(drop.x-40,drop.y+59);
context.moveTo(drop.x-40,drop.y+59);
context.lineTo(drop.x-14,drop.y+33);
context.moveTo(drop.x-14,drop.y+33);
context.lineTo(drop.x-30,drop.y+32);
context.moveTo(drop.x-30,drop.y+32);
context.lineTo(drop.x+140,drop.y+28);
context.closePath();
context.fillStyle = 'yellow';
context.fill();
I'm not sure what I want to do is called. This is the code my professor provided for a cloud.
function drawCloud(cloud) {
context.beginPath();
context.moveTo(cloud.x, cloud.y);
context.bezierCurveTo(cloud.x-40, cloud.y+20, cloud.x-40, cloud.y+70, cloud.x+60, cloud.y+70);
context.bezierCurveTo(cloud.x+80, cloud.y+100, cloud.x+170, cloud.y+100, cloud.x+170, cloud.y+70);
context.bezierCurveTo(cloud.x+250, cloud.y+70, cloud.x+250, cloud.y+40, cloud.x+210, cloud.y+20);
context.bezierCurveTo(cloud.x+260, cloud.y-40, cloud.x+200, cloud.y+50, cloud.x+170, cloud.y-30);
context.bezierCurveTo(cloud.x+150, cloud.y-75, cloud.x+80, cloud.y-60, cloud.x+80, cloud.y-30);
context.bezierCurveTo(cloud.x+30, cloud.y-75, cloud.x-20, cloud.y-60, cloud.x, cloud.y);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.strokeStyle = cloud.color;
context.stroke();
}
I found the shape generator and made this shape
function drawBolt(bolt){
context.beginPath()
context.moveTo(140,28);
context.lineTo(164,28);
context.moveTo(164,28);
context.lineTo(138,53);
context.moveTo(138,53);
context.lineTo(157,53);
context.moveTo(157,53);
context.lineTo(122,81);
context.moveTo(122,81);
context.lineTo(137,82);
context.moveTo(137,82);
context.lineTo(93,105);
context.moveTo(93,105);
context.lineTo(109,87);
context.moveTo(109,87);
context.lineTo(100,87);
context.moveTo(100,87);
context.moveTo(126,61);
context.lineTo(110,60);
context.moveTo(110,60);
context.lineTo(140,28);
context.closePath();
context.fill();
};
She told me that I had to change those points to x,y and I imagine there is math involved? Is there an easy way of doing that?
So how she has (cloud.x-40) I suppose I need bolt.x(?)
Where is a good starting point?
var canvas;
var context;
var shapes = []
var timer;
var timerTwo;
var possibleShapes = ['drop','triangle','square','circle','cloud'];
function Shape(x, y, color) {
this.x = x;
this.y = y;
this.size = Math.random()*20+5;
this.dx = Math.random()*4-2;
this.dy = Math.random()*4-2;
this.color = color;
this.shape = possibleShapes[Math.floor(Math.random()*possibleShapes.length)];
}
function init() {
canvas = document.getElementById('canvas');
context = canvas.getContext("2d");
window.addEventListener('resize', resizeCanvas, false);
window.addEventListener('orientationchange', resizeCanvas, false);
resizeCanvas();
canvas.onclick = function(event) {
handleClick(event.clientX, event.clientY);
};
timer = setInterval(resizeCanvas, 20);
timerTwo = setInterval(newShape, 200);
}
function newShape() {
var x = Math.random() * canvas.width;
var y = Math.random() * canvas.height;
var colors = ["red", "green", "blue", "orange", "purple", "yellow"];
var color = colors[Math.floor(Math.random()*colors.length)];
shapes.push(new Shape(x, y, color));
}
function drawCircle(circle) {
context.beginPath();
context.arc(circle.x, circle.y, circle.size, 0, degreesToRadians(360), true);
context.fillStyle = circle.color;
context.fill();
}
function drawSquare(square) {
context.beginPath();
context.fillStyle = square.color;
context.fillRect(square.x, square.y, square.size, square.size);
}
function drawTriangle(triangle) {
context.beginPath();
context.fillStyle = triangle.color;
context.moveTo(triangle.x+triangle.size,triangle.y);
context.lineTo(triangle.x,triangle.y);
context.lineTo(triangle.x,triangle.y+triangle.size);
context.closePath();
context.fill();
}
function drawCloud(cloud) {
context.beginPath();
context.moveTo(cloud.x, cloud.y);
context.bezierCurveTo(cloud.x-40, cloud.y+20, cloud.x-40, cloud.y+70, cloud.x+60, cloud.y+70);
context.bezierCurveTo(cloud.x+80, cloud.y+100, cloud.x+170, cloud.y+100, cloud.x+170, cloud.y+70);
context.bezierCurveTo(cloud.x+250, cloud.y+70, cloud.x+250, cloud.y+40, cloud.x+210, cloud.y+20);
context.bezierCurveTo(cloud.x+260, cloud.y-40, cloud.x+200, cloud.y+50, cloud.x+170, cloud.y-30);
context.bezierCurveTo(cloud.x+150, cloud.y-75, cloud.x+80, cloud.y-60, cloud.x+80, cloud.y-30);
context.bezierCurveTo(cloud.x+30, cloud.y-75, cloud.x-20, cloud.y-60, cloud.x, cloud.y);
// complete custom shape
context.closePath();
context.lineWidth = 5;
context.strokeStyle = cloud.color;
context.stroke();
}
function drawDrop(drop) {
context.beginPath();
context.lineJoin = 'miter';
context.moveTo(drop.x, drop.y);
context.arc(drop.x, drop.y+68, 34.5, 5.75, 3.66, false);
context.quadraticCurveTo(drop.x-3.5, drop.y+15, drop.x, drop.y);
context.closePath();
context.lineWidth = 2;
context.fillStyle = drop.color;
context.fill();
}
function drawText() {
context.fillStyle = 'white';
context.font = 'bold 2em sans-serif';
context.textAlign = 'right';
context.fillText('Art?', canvas.width-40, canvas.height-40);
}
function resizeCanvas() {
canvas.width = window.innerWidth-20;
canvas.height = window.innerHeight-20;
fillBackgroundColor();
for (var i=0; i<shapes.length; i++) {
if (shapes[i].shape == 'square') {
drawSquare(shapes[i]);
} else if (shapes[i].shape == 'circle') {
drawCircle(shapes[i]);
} else if (shapes[i].shape == 'triangle') {
drawTriangle(shapes[i]);
} else if (shapes[i].shape == 'drop') {
drawDrop(shapes[i]);
} else if (shapes[i].shape == 'cloud') {
drawCloud(shapes[i]);
}
if (shapes[i].x + shapes[i].dx > canvas.width || shapes[i].x + shapes[i].dx < 0)
shapes[i].dx = -shapes[i].dx;
if (shapes[i].y + shapes[i].dy > canvas.height || shapes[i].y + shapes[i].dy < 0)
shapes[i].dy = -shapes[i].dy;
shapes[i].x += shapes[i].dx;
shapes[i].y += shapes[i].dy;
}
drawText();
}
function fillBackgroundColor() {
//var colors = ["white", "yellow", "blue", "red"];
//var bgColor = colors[Math.floor(Math.random() * colors.length)];
context.fillStyle = 'black';
context.fillRect(0, 0, canvas.width, canvas.height);
}
function degreesToRadians(degrees) {
//converts from degrees to radians and returns
return (degrees * Math.PI)/180;
}
window.onload = init;
You can translate entire canvas instead of modifying your code.
let's suppose that bolt is an object with x and y as properties.
function drawBolt(bolt){
context.save();
context.translate(bolt.x, bolt.y);
context.beginPath()
context.moveTo(140,28);
context.lineTo(164,28);
context.moveTo(164,28);
context.lineTo(138,53);
context.moveTo(138,53);
context.lineTo(157,53);
context.moveTo(157,53);
context.lineTo(122,81);
context.moveTo(122,81);
context.lineTo(137,82);
context.moveTo(137,82);
context.lineTo(93,105);
context.moveTo(93,105);
context.lineTo(109,87);
context.moveTo(109,87);
context.lineTo(100,87);
context.moveTo(100,87);
context.moveTo(126,61);
context.lineTo(110,60);
context.moveTo(110,60);
context.lineTo(140,28);
context.closePath();
context.fill();
context.restore();
};
This is equivalent to drawing the bolt modifying all the points adding x and y to each of them.
I have to create a rotation wheel with 12 fields like in the image below link :http://www.resilienciacomunitaria.org/
How i create through which approach?
I used canvas for this but not successful i used d3.js svg but not successful .
<!DOCTYPE html>
<html>
<body>
<canvas id="canvas" width="600" height="600"
style="background-color:#ffff">
</canvas>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var radius = canvas.height /2; //400
//alert(radius);
//draw a circle again and agian
ctx.translate(radius, radius);
radius =radius*0.85;
setInterval(drawCircle, 50);
function drawCircle() {
var pos = .01;
var length = 100;
var width = 40;
drawFace(ctx, radius);
drawHand(ctx, pos, length, width);
}
function drawFace(ctx,radius){
ctx.beginPath();
ctx.arc(0, 0, 50, 0, 2 * Math.PI, false);
ctx.fillStyle = '#ffff';
ctx.strokeStyle = 'blue';
ctx.fill();
ctx.stroke();
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI, false);
ctx.strokeStyle = 'yellow';
ctx.fillStyle = 'blue';
ctx.lineWidth = 50;
ctx.fill();
ctx.stroke();
}
function drawHand(ctx, pos, length, width) {
ctx.beginPath();
ctx.lineWidth = 30;
ctx.moveTo(-radius,0);
ctx.lineTo(radius, 0);
ctx.moveTo(-radius,150);
ctx.lineTo(radius, -150);
ctx.moveTo(-radius,-150);
ctx.lineTo(radius, 150);
ctx.moveTo(-radius,380);
ctx.lineTo(radius, -380);
ctx.moveTo(-radius,-380);
ctx.lineTo(radius, 380);
ctx.moveTo(0, -radius);
ctx.lineTo(0, radius);
ctx.stroke();
/*
ctx.globalCompositeOperation='destination-over';
ctx.font="20px Verdana";
ctx.fillStyle = 'white';
ctx.fillText("Explore Zero",180,180);
ctx.stroke();
ctx.globalCompositeOperation='source-over';*/
ctx.rotate(-pos);
}
</script>
</body>
</html>
Thanks in advance
Here's code to get you started:
You can style it to your specific needs
Create an in-memory canvas containing your wheel.
Create an in-memory canvas containing your spike-indicator.
Rotate the canvas and draw the wheel on the main canvas.
Draw the indicator on the main canvas.
Change the rotation angle for the next loop.
Repeat, repeat, repeat using requestAnimationFrame.
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='24px verdana';
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='18px verdana';
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));
}
body{ background-color: ivory; padding:10px; }
canvas{border:1px solid red;}
<canvas id="canvas" width=400 height=300></canvas>
You can just put the "wheel" image on the website and just rotate it.
document.getElementById("TheImage").style.transform = "rotate("+YourAngle+"deg)";
Also you will need to put the "pointer" image on top of "wheel" image. (you will not rotate this one)
This is a fiddle written in 20 minutes, hope it helps.
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
canvas.width = 500;
canvas.height = 500;
var lines = new Array();
lines[0] = new Array();
lines[0] = ["Prize 1","#000000"];
lines[1] = new Array();
lines[1] = ["Prize 2","#ffff00"];
lines[2] = new Array();
lines[2] = ["Prize 3","#ff00ff"];
lines[3] = new Array();
lines[3] = ["Prize 4","#00ffff"];
lines[4] = new Array();
lines[4] = ["Prize 5","#00ff00"];
var TO_RADIANS = Math.PI / 180;
var angle = 360 / lines.length; //to see how far apart the lines need to be
var angle_offset = 0; //this will determine the spinning
var angle_speed = 1; //degrees per cycle
var center_offset = 20; //the radius of your spinner in the middle
function animate() {
ctx.clearRect(0,0,canvas.width,canvas.height);
angle_offset+=angle_speed;
ctx.font="20px Verdana";
ctx.fillStyle="#000000";
for (i=0; i<lines.length; i++) {
ctx.fillStyle=lines[i][1];
ctx.save();
ctx.translate(canvas.width/2, canvas.height/2);
ctx.rotate((angle * i + angle_offset) * TO_RADIANS);
//Here you can also decorate with boxes and stuff
ctx.fillText(lines[i][0],center_offset,0);
ctx.restore();
}
requestAnimationFrame(animate);
}
animate();
<canvas id="canvas"></canvas>