Canvas 2D Web 應用/靜態按鈕
本章討論了使用 cui2d 實現按鈕的最基本方法。這當然不是實現按鈕的唯一方法,但它非常靈活,定義按鈕外觀和功能的程式碼只是一個簡單的 if 語句,它檢查使用者事件是否發生在按鈕區域,並指定如何對這些事件做出反應。在本章中,按鈕的外觀是靜態的;根據使用者事件(例如,滑鼠懸停)改變其外觀的按鈕將在關於 響應式按鈕 的章節中討論。
本章的示例顯示了三個分別標記為“紅色”、“綠色”和“藍色”的按鈕,以及一個顏色補丁,其顏色根據點選的按鈕而變化。按鈕使用點陣圖影像渲染,允許任意按鈕設計。該示例可 線上 獲得,並且還可 線上 獲得可在移動裝置上下載的版本。如果你想在本地計算機上試用該示例,你還需要將檔案 cui2d.js 和影像 selected.png 下載到與 HTML 檔案相同的目錄中。
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta name="viewport"
content="width=device-width, initial-scale=1.0, user-scalable=no">
<script>
function init() {
// get image
imageFocusedButton.src = "selected.png";
imageFocusedButton.onload = cuiRepaint;
// deactivate single-finger dragging for myPage
myPage.interactionBits = cuiConstants.isTransformableWithTwoFingers;
// set defaults for all pages
cuiBackgroundFillStyle = "#000000";
cuiDefaultFont = "bold 20px Helvetica, sans-serif";
cuiDefaultFillStyle = "#FFFFFF";
// initialize cui2d and start with myPage
cuiInit(myPage);
}
// create an image for the button
var imageFocusedButton = new Image();
// create a color
var myColor = "#000000";
// create a new page of size 400x300 and attach myPageProcess
var myPage = new cuiPage(400, 300, myPageProcess);
// a function to repaint the canvas and return false (if null == event)
// or to process user events (if null != event) and return true
// if the event has been processed
function myPageProcess(event) {
// draw and react to buttons
if (cuiIsInsideRectangle(event, 50, 50, 80, 50, "red", imageFocusedButton)) {
if ("mouseup" == event.type || "touchend" == event.type) {
myColor = "#FF0000";
cuiRepaint();
return true;
}
}
if (cuiIsInsideRectangle(event, 150, 50, 80, 50, "green", imageFocusedButton)) {
if ("mouseup" == event.type || "touchend" == event.type) {
myColor = "#00FF00";
cuiRepaint();
return true;
}
}
if (cuiIsInsideRectangle(event, 250, 50, 80, 50, "blue", imageFocusedButton)) {
if ("mouseup" == event.type || "touchend" == event.type) {
myColor = "#0000FF";
cuiRepaint();
return true;
}
}
// click on background?
if (null != event) {
if ("mouseup" == event.type || "touchend" == event.type) {
myColor = "#000000";
cuiRepaint();
return true;
}
}
// repaint this page?
if (null == event) {
// draw color box
cuiContext.fillStyle = myColor;
cuiContext.fillRect(150, 150, 80, 80);
// background
cuiContext.fillStyle = "#404040";
cuiContext.fillRect(0, 0, this.width, this.height);
}
return false; // event has not been processed
}
</script>
</head>
<body bgcolor="#000000" onload="init()"
style="-webkit-user-drag:none; -webkit-user-select:none; ">
<span style="color:white;">A canvas element cannot be displayed.</span>
</body>
</html>
本討論假設您熟悉第 框架入門 章中討論的程式碼示例。
該示例使用點陣圖影像繪製按鈕。該影像分配給全域性變數 imageFocusedButton
// create an image for the button
var imageFocusedButton = new Image();
然後在 init() 函式中指定影像檔案
// get image
imageFocusedButton.src = "selected.png";
imageFocusedButton.onload = cuiRepaint;
透過將 onload 設定為 cuiRepaint,我們可以確保在影像完全載入之前,如果畫布已被渲染,則重新繪製畫布。
該示例定義了一個全域性變數 myColor 來儲存使用者選擇的顏色
// create a color
var myColor = "#000000";
由於該示例使用背景上的點選將 myColor 設定為黑色,因此這些“單指”事件不應由頁面處理。因此,該示例透過僅允許此頁面的雙指手勢來停用單指拖動
// deactivate single-finger dragging for myPage
myPage.interactionBits = cuiConstants.isTransformableWithTwoFingers;
為了重新繪製按鈕並處理按鈕上的點選,該示例使用了三次對 cuiIsInsideRectangle() 的呼叫
// draw and react to buttons
if (cuiIsInsideRectangle(event, 50, 50, 80, 50, "red", imageFocusedButton)) {
if ("mouseup" == event.type || "touchend" == event.type) {
myColor = "#FF0000";
cuiRepaint();
return true;
}
}
if (cuiIsInsideRectangle(event, 150, 50, 80, 50, "green", imageFocusedButton)) {
if ("mouseup" == event.type || "touchend" == event.type) {
myColor = "#00FF00";
cuiRepaint();
return true;
}
}
if (cuiIsInsideRectangle(event, 250, 50, 80, 50, "blue", imageFocusedButton)) {
if ("mouseup" == event.type || "touchend" == event.type) {
myColor = "#0000FF";
cuiRepaint();
return true;
}
}
cuiIsInsideRectangle() 的定義將在下面討論。這裡,重要的是它與處理函式的工作方式類似
- 如果
event為null,cuiIsInsideRectangle()會在指定的矩形中寫入一個字串("red"、"green"或"blue"),然後在其下方繪製imageFocusedButton。 - 如果
event不為null,則它會檢查此使用者事件是否在指定的矩形內,如果在矩形內,則返回true。在這種情況下,將檢查事件的型別,在mouseup和touchend事件的情況下,myColor將更改為某種顏色(取決於按鈕),並使用cuiRepaint()請求重新繪製以確保新顏色用於繪製。此外,該函式將返回true以指示事件已處理。
以下程式碼檢查其他地方是否發生了 mouseup 或 touchend,在這種情況下,它將 myColor 設定為黑色
// click on background?
if (null != event) {
if ("mouseup" == event.type || "touchend" == event.type) {
myColor = "#000000";
cuiRepaint();
return true;
}
}
最後,該函式檢查 event 是否為 null,如果是,則它使用顏色 myColor 和灰色背景重新繪製一個正方形矩形
// repaint this page?
if (null == event) {
// draw color box
cuiContext.fillStyle = myColor;
cuiContext.fillRect(150, 150, 80, 80);
// background
cuiContext.fillStyle = "#404040";
cuiContext.fillRect(0, 0, this.width, this.height);
}
然後,該函式返回 false 以指示事件未處理。
當你嘗試這個示例時,你可能會意識到它感覺非常靜態,即使你可以透過點選按鈕和背景來改變顏色。第 響應式按鈕 章中的示例感覺更加動態,因為按鈕的外觀會對使用者事件做出反應。
函式 cuiIsInsideRectangle() 在 cui2d.js 中定義
/**
* Either determine whether the event's position is inside a rectangle (if event != null)
* or draw an image in the rectangle with a text string on top of it (if event == null).
*/
function cuiIsInsideRectangle(event, x, y, width, height, text, image) {
if (null == event) { // draw button
if (null != text) {
cuiContext.fillText(text, x + width / 2, y + height / 2);
}
if (null != image) {
cuiContext.drawImage(image, x, y, width, height);
}
return false;
}
else { // if (null != event)
if (event.eventX >= x && event.eventX < x + width &&
event.eventY >= y && event.eventY < y + height) {
return true;
}
return false;
}
}
實現非常簡單:如果 event 為 null,則除非 text 為 null,否則 text 將寫入矩形的中心。同樣,除非 image 為 null,否則 image 將繪製到矩形中。另一方面(如果 event 不為 null),該函式會檢查事件中的座標 eventX 和 eventY 是否在矩形內,並返回結果。
請注意,eventX 和 eventY 是 cui2d 特有的:這些座標位於頁面的座標系中,這與 HTML 使用的任何座標系都不同,並且如果使用者使用雙指手勢變換頁面,它也會發生變化。