I'm trying to rotate an image inside a canvas.
Here's my Fiddle: https://jsfiddle.net/kevinludwig11/s6rgpjm9/
I try it with save and restore, but the path is also rotating.
The falcon should fly with his face towards and change the angle in the corners.
Can anybody help me?
Edit: One solution i've found: save the image 360 times with every rotation and load every image in the right position. But i think thats not the smartest solution.
No need to create 360 images to rotate a single image. Also you had a few incorrect ways of doing things.
To do the bird you will need to get the direction it is heading towards so I added a second point on the curves that is ahead of the bird. With these two points (birds pos and lookat pos) I then create a transformation using the lookat direction as the xAxis of the transformation. See function drawImageLookat(image,pos,lookat)
I found that the image is not along the X axis so I rotate the bird 90deg after finding the lookat transformation.
// function assumes front (forward) of image is along the x axis to the right
function drawImageLookat(image, point, lookat ) {
var xAx,xAy; // vector for x Axis of image
var x,y;
x = lookat.x - point.x;
y = lookat.y - point.y;
var dist = Math.max(0.01,Math.sqrt(x * x + y * y)); // Math.max to avoid zero which will create NaN
xAx = x / dist; // get x component of x Axis
xAy = y / dist; // get y component of x Axis
// y axis is at 90 deg so dont need y axis vector
ctx.setTransform( // position the image using transform
xAx, xAy, // set direction of x Axis
-xAy, xAx, // set direction oy y axis
point.x, point.y
);
ctx.drawImage(image, -image.width / 2, -image.height / 2);
}
Your code that I took from the fiddle https://jsfiddle.net/kevinludwig11/s6rgpjm9/ and modified to run as your question implies.
var canvas = document.getElementById("canvas"); var ctx = canvas.getContext("2d"); // only load image once var birdImage = new Image(); birdImage.src = 'http://www.happy-innovation.de/images/Falke_Flug.png'; birdImage.onload = function(){animate()}; // start animation when image has loaded // set starting values var speed = 0.25 var percent = speed; var direction = speed; var length = 300; function animate() { ctx.setTransform(1,0,0,1,0,0); // restore default transform incase its not ctx.clearRect(0, 0, canvas.width, canvas.height); percent += direction; // need to keep the position away from the ends as there is no lookat beyond the path. if(percent >= length - speed){ percent = length- speed; direction = -speed; }else if(percent <= speed){ percent = speed; direction = speed; } draw(percent,direction); requestAnimationFrame(animate); } function P(x,y){return {x,y}}; // quick way to create a point var paths = [ {col : 'red', points : [P(100, 200), P(600, 350), P( 700, 400)]}, {col : "green", points : [P(700, 400), P( 900, 500), P( 200, 600), P( 950, 900)]}, {col : "blue", points : [P(950, 900), P(1200, 950), P( 300, 200), P( 150, 1200)]}, {col : "brown", points : [P(150, 1200),P( 120, 1700),P( 1000, 700),P(850, 1500)]}, {col : "Purple",points : [P(850, 1500),P(800, 1900), P( 200, 900), P( 250, 1800)]}, {col : "yellow", points : [P(250, 1800),P(250, 1950), P( 600, 1500),P(950, 1800)]}, ] // draw the current frame based on sliderValue function draw(sliderValue,direction) { var getPos = false; // true if need pos on current curve var getForwardPos = false; // true if need pos on current curve var percent,percent1; // get the percentage on curves var birdPos; // get bird pos var birdLookAtPos; // get bird look at pos ctx.lineWidth = 5; for(var i = 0; i < paths.length; i ++){ var path = paths[i]; // get a path from array var p = path.points; ctx.strokeStyle = path.col; ctx.beginPath(); ctx.moveTo(p[0].x,p[0].y); if(sliderValue >= i * 50 && sliderValue < (i+1) * 50){ getPos = true; percent = (sliderValue % 50) / 50; } if(sliderValue + direction >= i * 50 && sliderValue + direction < (i+1) * 50){ getForwardPos = true; percent1 = ((sliderValue + direction) % 50) / 50; } if(p.length > 3){ ctx.bezierCurveTo(p[1].x,p[1].y,p[2].x,p[2].y,p[3].x,p[3].y); if(getPos){ birdPos = getCubicBezierXYatPercent(p[0],p[1],p[2],p[3],percent); getPos = false; } if(getForwardPos){ birdLookAtPos = getCubicBezierXYatPercent(p[0],p[1],p[2],p[3],percent1); getForwardPos = false; } }else{ ctx.quadraticCurveTo(p[1].x,p[1].y,p[2].x,p[2].y); if(getPos){ birdPos = getQuadraticBezierXYatPercent(p[0],p[1],p[2],percent); getPos = false; } if(getForwardPos){ birdLookAtPos = getQuadraticBezierXYatPercent(p[0],p[1],p[2],percent1); getForwardPos = false; } } ctx.stroke(); } drawImageLookingAt(birdImage,birdPos,birdLookAtPos); } function drawImageLookingAt(image, point, lookat ) { if(lookat === undefined){ // if no lookat then exit or it will crash. return; } var xAx,xAy; // vector for x Axis of image var x,y; x = lookat.x - point.x; y = lookat.y - point.y; var dist = Math.max(0.01,Math.sqrt(x * x + y * y)); // Math.max to avoid zero which will create NaN xAx = x / dist; // get x component of x Axis xAy = y / dist; // get y component of x Axis // y axis is at 90 deg so dont need y axis vector ctx.setTransform( // position the image using transform xAx, xAy, // set direction of x Axis -xAy, xAx, // set direction oy y axis point.x, point.y ); // bird is pointing in the wrong direction. Not along x axis // so rotate the image 90 deg clockwise ctx.rotate(Math.PI / 2); ctx.drawImage(image, -image.width / 2, -image.height / 2); ctx.setTransform(1,0,0,1,0,0); // Restore default Not really needed if you only use setTransform to do transforms // but in case you use transform, rotate, translate or scale you need to reset the // transform. } // line: percent is 0-1 function getLineXYatPercent(startPt, endPt, percent) { var dx = endPt.x - startPt.x; var dy = endPt.y - startPt.y; var X = startPt.x + dx * percent; var Y = startPt.y + dy * percent; return ({ x: X, y: Y }); } // quadratic bezier: percent is 0-1 function getQuadraticBezierXYatPercent(startPt, controlPt, endPt, percent) { var x = Math.pow(1 - percent, 2) * startPt.x + 2 * (1 - percent) * percent * controlPt.x + Math.pow(percent, 2) * endPt.x; var y = Math.pow(1 - percent, 2) * startPt.y + 2 * (1 - percent) * percent * controlPt.y + Math.pow(percent, 2) * endPt.y; return ({ x: x, y: y }); } // cubic bezier percent is 0-1 function getCubicBezierXYatPercent(startPt, controlPt1, controlPt2, endPt, percent) { var x = CubicN(percent, startPt.x, controlPt1.x, controlPt2.x, endPt.x); var y = CubicN(percent, startPt.y, controlPt1.y, controlPt2.y, endPt.y); return ({ x: x, y: y }); } // cubic helper formula at percent distance function CubicN(pct, a, b, c, d) { var t2 = pct * pct; var t3 = t2 * pct; return a + (-a * 3 + pct * (3 * a - a * pct)) * pct + (3 * b + pct * (-6 * b + b * 3 * pct)) * pct + (c * 3 - c * 3 * pct) * t2 + d * t3; }
<canvas height="1961" width="1000" id="canvas"></canvas>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.