2017-06-29 86 views
1

我有這個簡單的canvas網頁,它允許用戶通過使用HTML input type file從相機上傳照片。這個想法是讓用戶在他們的圖像上自由繪畫。但是,我有一個問題。HTML Canvas在變換和旋轉後重置繪圖點

在某些設備上,來自相機的圖像以錯誤的方向繪製到畫布上,所以我必須爲用戶提供一個按鈕來旋轉其圖像以獲取正確方向的圖形。

問題是,在畫布已被轉換並旋轉以獲得正確的方向之後,繪圖座標看起來有些偏離。例如,如果我繪製直線水平線,則在圖像旋轉一次後,我會得到垂直線。我認爲問題在於畫布方向改變的事實。

那麼如何在圖像被轉換和旋轉後如何校正繪圖座標?我的代碼如下..

window.onload = init; 
 
var canvas, ctx, file, fileURL; 
 
var mousePressed = false; 
 
var lastX, lastY; 
 

 
function init(){ 
 
\t canvas = document.getElementById('myCanvas') 
 
\t ctx = canvas.getContext('2d') 
 
\t canvas.addEventListener('mousedown', touchstartHandler, false) 
 
\t canvas.addEventListener('mousemove', touchmoveHandler, false) 
 
\t canvas.addEventListener('mouseup', touchendHandler, false) 
 
\t canvas.addEventListener('mouseleave', touchcancelHandler, false) 
 
} 
 

 
function touchstartHandler(e){ 
 
\t e.preventDefault() 
 
\t mousePressed = true; 
 
\t Draw(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, false); 
 
} 
 
function touchmoveHandler(e){ 
 
\t e.preventDefault() 
 
\t if (mousePressed) { 
 
\t  Draw(e.pageX - this.offsetLeft, e.pageY - this.offsetTop, true); 
 
\t } 
 
} 
 

 
function touchendHandler(e){ 
 
\t e.preventDefault() 
 
\t if (mousePressed) { 
 
\t  mousePressed = false; 
 
\t } 
 
} 
 

 
function touchcancelHandler(e){ 
 
\t e.preventDefault() 
 
\t if (mousePressed) { 
 
\t  mousePressed = false; 
 
\t } 
 
} 
 

 
function Draw(x, y, isDown) { 
 
    if (isDown) { 
 
     ctx.beginPath(); 
 
     ctx.strokeStyle = "blue"; 
 
     ctx.lineWidth = 12; 
 
     ctx.lineJoin = "round"; 
 
     ctx.moveTo(lastX, lastY); 
 
     ctx.lineTo(x, y); 
 
     ctx.closePath(); 
 
     ctx.stroke(); 
 
    } 
 
    lastX = x; 
 
    lastY = y; 
 
}
<!DOCTYPE html> 
 
<html> 
 
<head> 
 
\t <title>Portrait</title> 
 
</head> 
 
<body> 
 
\t <canvas id="myCanvas"></canvas><br/> 
 
\t <input type="file" onchange="fileUpload(this.files)" id="file-input" capture="camera"><br/><br/> 
 
\t <button onclick="rotate()">Rotate</button> 
 

 
\t <script> 
 
\t \t var file, canvas, ctx, image, fileURL; 
 
\t \t function fileUpload(files){ 
 
\t \t \t file = files[0] 
 
\t \t \t fileURL = URL.createObjectURL(file) 
 
\t \t \t canvas = document.getElementById('myCanvas') 
 
\t \t \t canvas.style.backgroundColor = "blue" 
 
\t \t \t ctx = canvas.getContext('2d') 
 
\t \t \t image = new Image() 
 
\t \t \t 
 
     image.onload = function() { 
 
      canvas.width = 500 
 
      canvas.height = (500*this.height)/this.width 
 
      ctx.drawImage(image,0,0,canvas.width,canvas.height) 
 
      ctx.save(); 
 
     } 
 
\t \t \t image.src = fileURL 
 
\t \t \t } 
 

 
\t \t \t function rotate(){ 
 
\t \t \t \t ctx.clearRect(0,0,canvas.width,canvas.height) 
 
\t \t \t \t ctx.translate(canvas.width/2, canvas.height/2) 
 
\t \t \t \t ctx.rotate(90*Math.PI/180) 
 
\t \t \t \t ctx.translate(-canvas.width/2, -canvas.height/2) 
 
\t \t \t \t ctx.drawImage(image,0,0,canvas.width,canvas.height) 
 
\t \t \t } 
 
\t </script> 
 
</body> 
 
</html>

回答

1

您需要的時候改造完成旋轉和平移,然後restore狀態之前save畫布狀態。

var file, canvas, ctx, image, fileURL, rotation = 90; 
 

 
function fileUpload(files) { 
 
    file = files[0] 
 
    fileURL = URL.createObjectURL(file) 
 
    canvas = document.getElementById('myCanvas') 
 
    canvas.style.backgroundColor = "blue" 
 
    ctx = canvas.getContext('2d') 
 
    image = new Image() 
 

 
    image.onload = function() { 
 
     canvas.width = 500 
 
     canvas.height = (500 * this.height)/this.width 
 
     ctx.drawImage(image, 0, 0, canvas.width, canvas.height) 
 
    } 
 
    image.src = fileURL 
 
} 
 

 
function rotate() { 
 
    ctx.clearRect(0, 0, canvas.width, canvas.height); 
 
    ctx.save(); //save canvas state 
 
    ctx.translate(canvas.width/2, canvas.height/2); 
 
    ctx.rotate(rotation * Math.PI/180); 
 
    ctx.translate(-canvas.width/2, -canvas.height/2); 
 
    ctx.drawImage(image, 0, 0, canvas.width, canvas.height); 
 
    rotation += 90; 
 
    ctx.restore(); //restore canvas state 
 
}
canvas {border: 1px solid red}
<canvas id="myCanvas"></canvas> 
 
<br/> 
 
<input type="file" onchange="fileUpload(this.files)" id="file-input" capture="camera"> 
 
<br/> 
 
<br/> 
 
<button onclick="rotate()">Rotate</button>

+0

我以前試過這個選項,它工作,但問題是,我只能旋轉一次,旋轉似乎停止工作一次後。你爲什麼一次停止旋轉? – notQ

+0

我還有一個問題。例如,圖像旋轉一次後,畫布左右兩側會有一些沒有圖像繪製的空白區域。現在我想調整畫布大小,使畫布大小與圖像相同,但我不知道如何在圖像旋轉和轉換後獲取圖像的寬度和高度。看起來圖像的寬度和高度都發生了變化。 – notQ

+0

檢查編輯的答案,我沒有看到任何空白。 *(這是一個差異。問題btw,這裏不能回答)* –

0

簡單旋轉而旋轉通過90度的步驟的圖像

最快方式

ctx.setTransform(
     0,1, // direction of x axis 
     -1,0 // direction of y axis 
     canvas.width,0 // location in pixels of the origin (0,0) 
); 

然後繪製圖像

ctx.drawImage(image,0,0); 

而不是使用ctx.restore(),在許多情況下可能會很慢,您只能將變換僅設置爲默認值。

ctx.setTransform(1,0,0,1,0,0); 

旋轉90度,180,-90deg

因此旋轉90度

ctx.setTransform(0,1,-1,0,canvas.width,0); 
ctx.drawImage(image,0,0); 
ctx.setTransform(1,0,0,1,0,0); 

因此能夠旋轉180度

ctx.setTransform(-1,0,0,-1,canvas.width,canvas.height); 
ctx.drawImage(image,0,0); 
ctx.setTransform(1,0,0,1,0,0); 

因此旋轉-90度

ctx.setTransform(0,-1,1,0,0,canvas.height); 
ctx.drawImage(image,0,0); 
ctx.setTransform(1,0,0,1,0,0); 
+0

嗨,你能回答這個嗎? [鏈接](https://stackoverflow.com/questions/44825002/rezize-html-canvas-size-after-transformed-operation) 我已經得到了這個問題。 – notQ