Szukaj…


Tworzenie responsywnego obszaru roboczego całej strony

Kod startowy do tworzenia i usuwania obszaru roboczego całej strony, który reaguje na zdarzenia zmiany rozmiaru za pomocą javascript.

var canvas;    // Global canvas reference
var ctx;       // Global 2D context reference
// Creates a canvas
function createCanvas () {                
    const canvas = document.createElement("canvas"); 
    canvas.style.position = "absolute"; // Set the style 
    canvas.style.left     = "0px";      // Position in top left
    canvas.style.top      = "0px";
    canvas.style.zIndex   = 1;        
    document.body.appendChild(canvas);  // Add to document
    return canvas;
}
// Resizes canvas. Will create a canvas if it does not exist
function sizeCanvas () {                
    if (canvas === undefined) {         // Check for global canvas reference
        canvas = createCanvas();        // Create a new canvas element
        ctx = canvas.getContext("2d");  // Get the 2D context
    }
    canvas.width  = innerWidth;         // Set the canvas resolution to fill the page
    canvas.height = innerHeight;        
}
// Removes the canvas
function removeCanvas () {
    if (canvas !== undefined) {              // Make sure there is something to remove
        removeEventListener("resize", sizeCanvas); // Remove resize event
        document.body.removeChild(canvas);   // Remove the canvas from the DOM
        ctx = undefined;                     // Dereference the context
        canvas = undefined;                  // Dereference the canvas
     }
}

// Add the resize listener
addEventListener("resize", sizeCanvas); 
// Call sizeCanvas to create and set the canvas resolution
sizeCanvas();
// ctx and canvas are now available for use.

Jeśli nie potrzebujesz już płótna, możesz go usunąć, wywołując removeCanvas()

Demo tego przykładu w jsfiddle

Współrzędne myszy po zmianie rozmiaru (lub przewinięciu)

Aplikacje Canvas często polegają w dużej mierze na interakcji użytkownika z myszą, ale przy zmianie rozmiaru okna współrzędne zdarzenia myszy, na których opiera się canvas, prawdopodobnie ulegają zmianie, ponieważ zmiana rozmiaru powoduje przesunięcie płótna w innej pozycji względem okna. Zatem responsywne projektowanie wymaga ponownego obliczenia położenia przesunięcia obszaru roboczego przy zmianie rozmiaru okna - a także ponownego obliczenia po przewinięciu okna.

Ten kod nasłuchuje zdarzeń zmieniających rozmiar okna i ponownie oblicza przesunięcia używane w programach obsługi zdarzeń myszy:

// variables holding the current canvas offset position
//    relative to the window
var offsetX,offsetY;

// a function to recalculate the canvas offsets
function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}

// listen for window resizing (and scrolling) events
//     and then recalculate the canvas offsets
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }

// example usage of the offsets in a mouse handler
function handleMouseUp(e){
    // use offsetX & offsetY to get the correct mouse position
    mouseX=parseInt(e.clientX-offsetX);
    mouseY=parseInt(e.clientY-offsetY);
    // ...
}

Elastyczne animacje na płótnie bez zdarzeń zmiany rozmiaru.

Zdarzenia zmiany rozmiaru okna mogą być uruchamiane w odpowiedzi na ruch urządzenia wejściowego użytkownika. Po zmianie rozmiaru płótna jest on automatycznie usuwany i użytkownik jest zmuszony do ponownego renderowania treści. W przypadku animacji robisz to co klatkę za pomocą funkcji głównej pętli wywoływanej przez requestAnimationFrame która stara się zachować synchronizację renderowania ze sprzętem wyświetlającym.

Problem ze zdarzeniem zmiany rozmiaru polega na tym, że gdy mysz zmienia rozmiar okna, zdarzenia mogą być wyzwalane wiele razy szybciej niż standardowa szybkość 60 klatek na sekundę w przeglądarce. Po wyjściu ze zdarzenia zmiany rozmiaru bufor tylnego obszaru roboczego jest prezentowany DOM bez synchronizacji z urządzeniem wyświetlającym, co może powodować ścinanie i inne negatywne skutki. Istnieje również wiele niepotrzebnych przydziałów pamięci i zwolnień, które mogą mieć wpływ na animację, gdy GC oczyści trochę później.


Ogłoszono zdarzenie zmiany rozmiaru

Częstym sposobem radzenia sobie z wysokimi częstotliwościami wystrzeliwania zdarzenia zmiany rozmiaru jest ogłoszenie zdarzenia zmiany rozmiaru.

 // Assume canvas is in scope
 addEventListener.("resize", debouncedResize );

 // debounce timeout handle
 var debounceTimeoutHandle;

 // The debounce time in ms (1/1000th second)
 const DEBOUNCE_TIME = 100; 

 // Resize function 
 function debouncedResize () { 
     clearTimeout(debounceTimeoutHandle);  // Clears any pending debounce events

     // Schedule a canvas resize 
     debounceTimeoutHandle = setTimeout(resizeCanvas, DEBOUNCE_TIME);
 }

 // canvas resize function
 function resizeCanvas () { ... resize and redraw ... }

Powyższy przykład opóźnia zmianę rozmiaru obszaru roboczego do 100 ms po zdarzeniu zmiany rozmiaru. Jeśli w tym czasie zostaną uruchomione kolejne zdarzenia zmiany rozmiaru, istniejący limit czasu zostanie anulowany i zaplanowane zostanie nowe. To skutecznie zużywa większość zdarzeń zmiany rozmiaru.

Nadal występują pewne problemy, najbardziej zauważalne jest opóźnienie między zmianą rozmiaru a wyświetleniem obrazu o zmienionym rozmiarze. Skrócenie czasu odbicia poprawia to, ale zmiana rozmiaru nadal nie jest zsynchronizowana z urządzeniem wyświetlającym. Nadal masz również renderowanie głównej pętli animacji na źle dopasowanym płótnie.

Więcej kodów może zmniejszyć problemy! Więcej kodu stwarza również nowe problemy.


Prosty i najlepszy rozmiar

Po wypróbowaniu wielu różnych sposobów na wygładzenie rozmiaru płótna, od absurdalnie skomplikowanego, po ignorowanie problemu (kogo to obchodzi?) Wróciłem do zaufanego przyjaciela.

KISS jest czymś większość programistów powinien być świadomy ((K EEP I t S wyko S tupid) Głupi odnosi się do mnie nie myślał o nim rok temu.) I okazuje się, że najlepszym rozwiązaniem jest najprostszym ze wszystkich.

Po prostu zmień rozmiar płótna w głównej pętli animacji. Pozostaje zsynchronizowany z urządzeniem wyświetlającym, nie ma niepotrzebnego renderowania, a zarządzanie zasobami jest na minimalnym możliwym poziomie przy zachowaniu pełnej częstotliwości klatek. Nie trzeba też dodawać zdarzenia zmiany rozmiaru do okna ani żadnych dodatkowych funkcji zmiany rozmiaru.

Dodajesz zmianę rozmiaru w miejscu, w którym normalnie wyczyścisz płótno, sprawdzając, czy rozmiar płótna odpowiada rozmiarowi okna. Jeśli nie, zmień jego rozmiar.

// Assumes canvas element is in scope as canvas

// Standard main loop function callback from requestAnimationFrame
function mainLoop(time) {

    // Check if the canvas size matches the window size
    if (canvas.width !== innerWidth || canvas.height !== innerHeight) {
        canvas.width = innerWidth;    // resize canvas
        canvas.height = innerHeight;  // also clears the canvas
    } else {
        ctx.clearRect(0, 0, canvas.width, canvas.height); // clear if not resized
    }

    // Animation code as normal.



    requestAnimationFrame(mainLoop);
}


Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow