If you're seeing this message, it means we're having trouble loading external resources on our website.

Jeżeli jesteś za filtrem sieci web, prosimy, upewnij się, że domeny *.kastatic.org i *.kasandbox.org są odblokowane.

Główna zawartość

Funkcja przycisku

Jeśli przeszedłeś przez wstęp do kursu JS, wykonałeś już kilka prostych przycisków w łamigłówkach Twój Pierwszy Przycisk oraz Sprytniejszy Przycisk. Jeśli zapomniałeś jak je robić, przećwiczymy to jeszcze raz.
Po pierwsze, jakie są minimalne wymaganie, które musi spełniać przycisk?
  1. Ma jakiś kształt (zazwyczaj prostokąt)
  2. Zawiera podpis lub ikonę opisujące jego funkcję
  3. Reaguje, gdy użytkownik kliknie w niego
Punkty 1 i 2 możemy osiągnąć bardzo łatwo:
fill(0, 234, 255);
rect(100, 100, 150, 50, 5);
fill(0, 0, 0);
textSize(19);
text("Bezużyteczny przycisk", 110, 133);
Osiągnięcie ostatniego wymaga zdefiniowania funkcji mouseClicked, która będzie wywołana, gdy użytkownik kliknie. Wewnątrz niej musimy sprawdzać, czy mouseX oraz mouseY mieszczą się w granicach przycisku. Jak zilustrowano poniżej, wcześniej zdefiniowany przycisk rozciąga się od x=100 do x=250 oraz od y=100 do y=150.
Możemy sprawdzić te współrzędne &&kodując poniższe 4 warunki:
mouseClicked = function() {
  if (mouseX >= 100 && mouseX <= 250 &&
      mouseY >= 100 && mouseY <= 150) {
        println("Wciąż bezużyteczny");
      }
};
Spróbuj kliknąć na nim oraz poniżej niego, aby sprawdzić, czy to działa:
To na pewno działa, ale mimo to jestem tym zaniepokojony. Obawiam się, że nie jest to kod, który będę mógł ponownie wykorzystać. Jak dużo będzie trzeba zrobić, jeśli zapragnę zmienić pozycję przycisku? (Spróbuj wyżej!) Widzę w kodzie wiele wpisanych na "sztywno" liczb -- np. współrzędne w funkcji mouseClicked i od razu zaczynam się zastanawiać, czy nie ma lepszego sposobu na zrobienie tego.
Na początku stwórzmy zmienne przechowujące pozycję i rozmiar. Dzięki temu będziemy mogli zmienić położenie przycisku tylko w jednym miejscu, a kliknięcia nadal będą działać. Do poniższego kodu dodałem btnX, btnY, btnWidth i btnHeight. Spróbuj zmienić ich wartości i kliknij na przycisk:
Jest lepiej, jednak jak dużo pracy będę musiał włożyć w dodanie nowego przycisku? Czy będę musiał skopiować cały kod i poprawić, tak aby zawierał btn2X oraz btn2Y? Ach, to nie brzmi dobrze. To brzmi jak dobra motywacja, do napisania funkcji, która zajmie się wszystkim co jest wspólne dla przycisków i wykorzysta parametry do rozróżnienia tego co je różni. Możemy napisać ją tak, zamieniając zmienne w parametry:
var drawButton = function(btnX, btnY, btnWidth, btnHeight) {
    fill(0, 234, 255);
    rect(btnX, btnY, btnWidth, btnHeight, 5);
    fill(0, 0, 0);
    textSize(19);
    textAlign(LEFT, TOP);
    text("Bezużyteczny przycisk", btnX+10, btnY+btnHeight/4);
};
Teraz będziemy mogli tworzyć przyciski wywołując funkcję jak poniżej:
drawButton(100, 100, 150, 50);
Ale co z kodem funkcji mouseClicked? Czy widzisz co jest w nim problematyczne?
mouseClicked = function() {
  if (mouseX >= btnX && mouseX <= (btnX+btnWidth) &&
      mouseY >= btnY && mouseY <= (btnY+btnHeight)) {
        println("Wciąż bezużyteczny"); 
      }
};
Złączenie tego kodu razem powoduje wystąpienie błędu "btnX jest niezdefiniowany" - i tak być powinno! Przekształciliśmy btnX w parametr funkcji, co oznacza, że nie jest on już zmienną globalną. Jest to świetne jeśli chodzi o ponowne wykorzystanie funkcji drawButton, ale teraz funkcja mouseClicked nie może wiedzieć jakie współrzędne ma sprawdzić.
Dlatego musimy znaleźć dobry sposób na przekazanie informacji drawButton i uczynienie ich dostępnych dla mouseClicked. Można to zrobić na kilka sposobów:
  1. Ponownie wprowadzić zmienne globalne dla pozycji i rozmiaru (btnX, btnY, btnWidth, btnHeight)
  2. Wprowadzić tablicę globalną, która będzie przechowywać wszystkie parametry (var btn1 = [...];)
  3. Wprowadzić a obiekt globalny przechowujący atrybuty (var btn1 = {..})
  4. Użyć zasad programowania zorientowanego obiektowo, aby zdefiniować przycisk przechowujący właściwości (var btn1 = new Button(...))
Który wybrać? Więc, nie podoba mi się opcja pierwsza, ponieważ musielibyśmy dodać bardzo wiele zmiennych globalnych, a ja mam alergię na zmienne globalne. Nie lubię drugiej techniki, gdyż ciężko jest czytać kod, który przyjmuje dane opierające się o pola tablic. Podoba mi się trzecia trzecia technika, ponieważ wprowadza tylko jedną zmienną globalną i tworzy czytelniejszy kod. Podobnie jest z ostatnią techniką - wykorzystaniem zasad programowania zorientowanego obiektowo do stworzenia standardowego typu obiektowego Button, jednak zostawmy to na później.
Nasz globalny obiekt btn1 może wyglądać tak:
var btn1 = {
    x: 100,
    y: 100,
    width: 150,
    height: 50  
};
Następnie zmień funkcję drawButton tak, aby akceptowała jeden obiekt i później pobierała atrybuty z niego:
var drawButton = function(btn) {
    fill(0, 234, 255);
    rect(btn.x, btn.y, btn.width, btn.height, 5);
    fill(0, 0, 0);
    textSize(19);
    textAlign(LEFT, TOP);
    text("Bezużyteczny przycisk", btn.x+10, btn.y+btn.height/4);
};
Funkcja mouseClicked będzie sprawdzać atrybuty globalnej zmiennej:
mouseClicked = function() {
    if (mouseX >= btn1.x && mouseX <= (btn1.x+btn1.width) &&
        mouseY >= btn1.y && mouseY <= (btn1.y+btn1.height))     {
        println("Nadal bezużyteczny");
}
};
Wypróbuj je poniżej! Tak jak przedtem, spróbuj zmieniać parametry przycisku i zobacz jak całość zacznie wtedy działać:
Celem tego ćwiczenia było umożliwienie łatwego dodawania większej liczby przycisków. Jeśli się to powiedzie, znaczy to, że przejdzie to ostateczny test możliwości ponownego wykorzystania. Czy uda się to nam? Ba Bum BUM.
Zaczniemy od nowej globalnej zmiennej btn2, przesunietej w pozycji y od pierwszego przycisku:
var btn2 = {
  x: 100,
  y: 200,
  width: 150,
  height: 50
};
Teraz narysujmy ten przycisk:
drawButton(btn2);
Dzięki temu uda się narysować dwa przyciski na płótnie, ale tylko pierwszy będzie reagował na kliknięcia. Możemy sprawić, aby drugi powielał mechanikę poprzez skopiowanie kodu dla btn2 z btn1 w następujący sposób:
mouseClicked = function() {
    if (mouseX >= btn1.x && mouseX <= (btn1.x+btn1.width) &&
        mouseY >= btn1.y && mouseY <= (btn1.y+btn1.height))     {
        println("Dosyć bezużyteczny");    
    }

    if (mouseX >= btn2.x && mouseX <= (btn2.x+btn2.width) &&
        mouseY >= btn2.y && mouseY <= (btn2.y+btn2.height))     {
        println("Drugi również raczej bezużyteczny!");    
    }
};
Ale czy ten powtórzony kod nie sprawia, że chce wam się krzyczeć? Stwórzmy funkcję isMouseInside, która będzie w stanie sprawdzić wszystkie obiekty przycisków i zwrócić wartość true jeśli myszka będzie na którymś z nich:
var isMouseInside = function(btn) {
  return (mouseX >= btn.x &&
    mouseX <= (btn.x+btn.width) &&
    mouseY >= btn.y &&
    mouseY <= (btn.y+btn.height));
};
Dzięki temu mozemy napisać część kodu wewnątrz mouseClicked która znacznie zredukuje powtarzalność kodu:
mouseClicked = function() {
  if (isMouseInside(btn1))     {
    println("Wciąż raczej bezużyteczny");
  } else if (isMouseInside(btn2))     {
    println("Drugi też raczej bezużyteczny!");
  }
};
A oto wynik! Użyliśmy funkcji do narysowania wielu przycisków i sprawiliśmy, że w miarę łatwo jest dodawać kolejne. Wypróbuj te możliwości poniżej:
Moglibyśmy kontynuować - tworzyć tablice przycisków w programie, umożliwić modyfikację napisu na przycisku lub jego koloru - ale miejmy nadzieję, że dalo Ci to w miarę przyzwoite podstawy do tworzenia prostych przycisków za pomocą funkcji. Pora przejść do omówienia metod tworzenia przycisków za pomocą zasad programowania obiektowego.

Chcesz dołączyć do dyskusji?

Na razie brak głosów w dyskusji
Rozumiesz angielski? Kliknij tutaj, aby zobaczyć więcej dyskusji na angielskiej wersji strony Khan Academy.