我正在尝试在画布内旋转图像。
Here's my Fiddle: https://jsfiddle.net/kevinludwig11/s6rgpjm9/
我尝试使用保存和恢复,但路径也在旋转。
猎鹰应该朝着他的脸飞去并改变角落里的角度。
有人能帮助我吗?
编辑:我找到的一个解决方案:每次旋转将图像保存360次,并将每张图像加载到正确的位置。但我认为这不是最聪明的解决方案。
答案 0 :(得分:0)
无需创建360度图像即可旋转单个图像。你也有一些不正确的做法。
要做鸟,你需要得到它朝向的方向,所以我在鸟的前面的曲线上添加了第二个点。有了这两点(鸟pos和lookat pos),我就使用lookat方向创建一个变换作为变换的xAxis。参见函数drawImageLookat(image,pos,lookat)
我发现图像不是沿X轴,所以在找到外观变换后我将鸟旋转90度。
// 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);
}
我从小提琴https://jsfiddle.net/kevinludwig11/s6rgpjm9/中获取的代码,并根据您的问题进行了修改。
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>