們在使用 Canvas 繪制圖形時,可能會想對繪制的圖形進行變換,例如讓圖形旋轉90度,或者讓圖像縮小放大等,這些效果都可以通過 Canvas API 的坐標軸變換處理功能來實現。
如果我們要想將圖形進行旋轉,例如下面這張圖片:
可以通過 rotate() 方法來實現這個效果,rotate() 方法用于旋轉當前的繪圖,帶有一個參數 angle,表示旋轉角度。旋轉的中心點是坐標的原點,是以順時針方向進行旋轉,如果想要以逆時針方向來旋轉,可以將參數設置為負數。
示例:
例如上圖的實現代碼如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5學習(9xkd.com)</title>
</head>
<body>
<canvas id="mycanvas" width="250px" height="150px" style="border: 1px solid #000;"></canvas>
<script>
var can=document.getElementById("mycanvas");
var ctx=can.getContext("2d");
ctx.fillStyle="pink"; // 填充顏色
ctx.rotate(20*Math.PI/180);
ctx.fillRect(50, 30, 100, 50);
</script>
</body>
</html>
圖形縮放可以使用 scale() 方法來實現,可以對圖形進行放大或縮小設置。注意,這個函數有兩個參數,第一個參數為水平方向的縮放倍數,第二個參數為垂直方向的縮放倍數。要將圖形縮小,可以將參數值設置為0到1之間的小數,例如 0.5 表示將圖形縮小一倍。或者也可以將參數值設置為百分數,例如 0.5=50%、1=100%、2=200% 等。
示例:
將圖形放大一倍:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5學習(9xkd.com)</title>
</head>
<body>
<canvas id="mycanvas" width="250px" height="150px" style="border: 1px solid #000;"></canvas>
<script>
var can=document.getElementById("mycanvas");
var ctx=can.getContext("2d");
ctx.fillStyle="pink"; // 填充顏色
ctx.fillRect(50, 30, 100, 50);
ctx.scale(1.5, 1.5);
ctx.fillRect(50, 30, 100, 50);
</script>
</body>
</html>
在瀏覽器中的預覽效果:
移動圖形可以通過 translate() 方法來實現,這個方法中的第一個參數表示將坐標軸向右邊移動若干個單位,第二個參數表示將坐標軸圓點向下移動若干個單位。
示例:
將圖形水平移動50px,向下移動50px:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5學習(9xkd.com)</title>
</head>
<body>
<canvas id="mycanvas" width="250px" height="150px" style="border: 1px solid #000;"></canvas>
<script>
var can=document.getElementById("mycanvas");
var ctx=can.getContext("2d");
ctx.fillStyle="pink"; // 填充顏色
ctx.fillRect(50, 30, 100, 50);
ctx.translate(50, 50);
ctx.fillRect(50, 30, 100, 50);
</script>
</body>
</html>
在瀏覽器中的預覽效果:
我們通過上述學習的三個方法,來實現下圖所示效果:
實現代碼如下所示:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>HTML5學習(9xkd.com)</title>
<script>
window.onload=function() {
var can=document.getElementById("mycanvas");
var ctx=can.getContext("2d");
ctx.translate(200, 10);
ctx.fillStyle="rgba(219,112,147, 0.7)";
for(var i=0; i < 50; i++){
ctx.translate(27, 27);
ctx.scale(0.95, 0.95);
ctx.rotate(Math.PI / 10);
ctx.fillRect(0, 0, 90, 50);
}
}
</script>
</head>
<body>
<canvas id="mycanvas" width="400" height="300" style="border: 1px solid #000;"></canvas>
</body>
</html>
我們在繪制圖形的時候,經常會用到上述幾個方法來進行圖形變化,需要注意的是,這個變化的不是畫布,而是畫布上的畫進行變化。
查看更多可以點擊鏈接:https://www.9xkd.com/
家好,我是前端西瓜哥,今天來和大家說說 canvas 怎么做圖形拾取。
圖形拾取,指的是用戶通過鼠標或手指在圖形界面上能選中圖形的能力。圖形拾取技術是之后的高亮圖形、拖拽圖形、點擊觸發事件的基礎。
canvas 作為一個過于樸實無華的繪制工具,我們想知道如何讓 canvas 能像 HTML 一樣,知道鼠標點中了哪個 “div”。
canvas 只提供 API 在畫布上繪制形狀,并不知道它之前畫過的圖形是什么,不會保存它們的坐標、寬高等信息。
所以如果你想讓 canvas 支持將其中的圖形進行編輯,比如拖拽和放大,那就必須自己去維護一棵節點樹。
類似這樣:
const tree = {
type: 'stage',
children: [
{
type: 'rect',
x: 10, y: 10, w: 100, h: 100,
fill: 'red',
},
{
type: 'circle',
x: 0, y: 0, radius: 80,
stroke: 'yellow',
}
],
};
然后 canvas 基于此去按層級繪制這些圖形。
下面我們看看元素拾取的幾種方案。
isPointInPath 是 canvas 原生提供的一個檢測某個點是否在指定路徑內的方法。
const canvas = document.querySelector("canvas");
const ctx = canvas.getContext("2d");
ctx.beginPath(); // 表示路徑的開始
ctx.rect(30, 30, 100, 50);
ctx.stroke(); // 如果只是計算,可以不繪制出來
ctx.isPointInPath(40, 40); // true,在路徑內
ctx.isPointInPath(10, 10); // false,不在路徑內
線上 demo:
https://codesandbox.io/s/h7pxsm
優點:
缺點:
根據真正的 canvas 元素,額外創建一個大小相同離屏的緩存 canvas 元素。
每次我們在主 canvas 上繪制形狀時,也在緩存 canvas 上繪制同樣形狀的純色塊,并用哈希表記錄顏色和對應的圖形對象,比如紅色表示矩形 A,綠色表示矩形 B。
然后當我們在真實 canvas 上點擊時,我們在 canvas 綁定事件,就可以拿到坐標位置 (x, y),再通過 offScreenCtx.getImageData(x, y, 1, 1) 方法得到緩存 canvas 的對應像素點的顏色值,然后找到它對應的圖形對象,執行其注冊的事件。
Konva 庫使用了該方案。
寫了個簡單的線上 demo,你可以嘗試點擊上面那個 canvas 下的圖形,看看控制臺輸出:
https://codesandbox.io/s/veivt3
優點:
缺點:
可以用計算機圖形學的算法,去判斷一個點是否在某個形狀內。
比如:
(1)點是否在矩形內。
function isPointInRect(point, rect) {
return (
point.x >= rect.x &&
point.y >= rect.y &&
point.x <= rect.x + rect.width &&
point.y <= rect.y + rect.height
);
}
(2)點是否在圓形內。
export function isPointInCircle(point, circle) {
const dx = point.x - circle.x;
const dy = point.y - circle.y;
const dSquare = dx * dx + dy * dy;
return dSquare <= circle.radius * circle.radius;
}
還有其他的:通過 “射線法” 判斷點是否在多邊形等。
優點:
缺點:
總結一下,canvas 的圖形拾取有三種方案:
我是前端西瓜哥,歡迎關注我,學習更多知識。
canvas
*請認真填寫需求信息,我們會在24小時內與您取得聯系。