2017-01-11 14 views
9

Potrzebuję wykonać animację na div dla właściwości scaleZ() i translateZ() przy użyciu animacji CSS.Animacja CSS dla transformacji nie działa poprawnie podczas korzystania z początkowej klatki kluczowej z wartością macierzy3d

następujący kod działa poprawnie, gdy początkowe i ostatnie klatki kluczowe wartości w animacji dla transform nieruchomości są w podobnym "format":

  • 0% jest transform: rotateY(-179deg) scaleZ(2) translateZ(200px);
  • 100% to transform: rotateY(179deg) scaleZ(2) translateZ(200px);

 console.clear(); 
 
     document.addEventListener('DOMContentLoaded',() => { 
 
      let content1 = document.querySelector('#content1'); 
 
      var computedTransform = window.getComputedStyle(content1).transform; 
 
      console.log(computedTransform); 
 

 
     });
 @-webkit-keyframes animation { 
 
      0% { 
 
       /*works*/ 
 
       -webkit-transform: rotateY(-179deg) scaleZ(2) translateZ(200px); 
 
         transform: rotateY(-179deg) scaleZ(2) translateZ(200px); 
 
       /*issue*/ 
 
       /*transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1);*/ 
 
      } 
 

 

 
      100% { 
 
       -webkit-transform: rotateY(179deg) scaleZ(2) translateZ(200px); 
 
         transform: rotateY(179deg) scaleZ(2) translateZ(200px); 
 
      } 
 
     } 
 

 
     @keyframes animation { 
 
      0% { 
 
       /*works*/ 
 
       -webkit-transform: rotateY(-179deg) scaleZ(2) translateZ(200px); 
 
         transform: rotateY(-179deg) scaleZ(2) translateZ(200px); 
 
       /*issue*/ 
 
       /*transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1);*/ 
 
      } 
 

 

 
      100% { 
 
       -webkit-transform: rotateY(179deg) scaleZ(2) translateZ(200px); 
 
         transform: rotateY(179deg) scaleZ(2) translateZ(200px); 
 
      } 
 
     } 
 

 
     #content1 { 
 
      -webkit-animation: animation 2s; 
 
        animation: animation 2s; 
 
      -webkit-animation-fill-mode: forwards; 
 
        animation-fill-mode: forwards; 
 
      /*works*/ 
 
      -webkit-transform: rotateY(-179deg) scaleZ(2) translateZ(200px); 
 
        transform: rotateY(-179deg) scaleZ(2) translateZ(200px); 
 
      /*issue*/ 
 
      /*transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1);*/ 
 
     }
<div id="wrapper1" style="position:fixed; top: 100px; left:300px; perspective: 1000px; width: 250px; height:250px; border: dotted 1px blue"> 
 
     <div id="content1" style="width: 250px; height:250px; background-color:lightsalmon; opacity:0.2;"> 
 
     </div> 
 
    </div>


Ta sama animacja z transform dla kluczowej ramki 0% napisany jako matrix3D wrócił z Window.getComputedStyle() nie czyni pracę animacji prawidłowo:

  • 0% jest transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1);
  • 100% to transform: rotateY(179deg) scaleZ(2) translateZ(200px);

 console.clear(); 
 
     document.addEventListener('DOMContentLoaded',() => { 
 
      let content1 = document.querySelector('#content1'); 
 
      var computedTransform = window.getComputedStyle(content1).transform; 
 
      console.log(computedTransform); 
 

 
     });
@-webkit-keyframes animation { 
 
      0% { 
 
       /*works*/ 
 
       /*transform: rotateY(-179deg) scaleZ(2) translateZ(200px);*/ 
 
       /*issue*/ 
 
       -webkit-transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
         transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
      } 
 

 

 
      100% { 
 
       -webkit-transform: rotateY(179deg) scaleZ(2) translateZ(200px); 
 
         transform: rotateY(179deg) scaleZ(2) translateZ(200px); 
 
      } 
 
     } 
 

 
     @keyframes animation { 
 
      0% { 
 
       /*works*/ 
 
       /*transform: rotateY(-179deg) scaleZ(2) translateZ(200px);*/ 
 
       /*issue*/ 
 
       -webkit-transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
         transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
      } 
 

 

 
      100% { 
 
       -webkit-transform: rotateY(179deg) scaleZ(2) translateZ(200px); 
 
         transform: rotateY(179deg) scaleZ(2) translateZ(200px); 
 
      } 
 
     } 
 

 
     #content1 { 
 
      -webkit-animation: animation 2s; 
 
        animation: animation 2s; 
 
      -webkit-animation-fill-mode: forwards; 
 
        animation-fill-mode: forwards; 
 
      /*works*/ 
 
      /*transform: rotateY(-179deg) scaleZ(2) translateZ(200px);*/ 
 
      /*issue*/ 
 
      -webkit-transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
        transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
     }
<div id="wrapper1" style="position:fixed; top: 100px; left:300px; perspective: 1000px; width: 250px; height:250px; border: dotted 1px blue"> 
 
     <div id="content1" style="width: 250px; height:250px; background-color:lightsalmon; opacity:0.2;"> 
 
     </div> 
 
    </div>

Z przyczyn technicznych muszę użyć jako klucza ramie 0% wartość dla transformation właściwie wrócił ze stylu komputerowej w DOM przy użyciu Window.getComputedStyle() lub inną funkcję, jeśli jest dostępna.

Moje pytania:

  1. Czy mój kod na drugim przykładzie buggy?
  2. Czy możesz zaproponować alternatywny sposób uzyskania obliczonej wartości z DOM?
  3. Czy znasz jakieś błędy związane z wartością zwróconą z Window.getComputedStyle()?
  4. Czy znasz jakieś błędy z animacjami CSS i inną "notacją" dla transform?

Uwagi: Widzę ten problem w najnowszym Chrome (55.0.2883.87 m) i FireFox (50.1.0).

Wszelkie rozwiązania lub pomysły są mile widziane.


EDIT:

Stworzyłem kilka nowych przykładów (dla Chrome) do dalszego badania.

Zasadniczo dwa przykładem obracać

from rotateY(20deg) to rotateY(90deg)

Korzystanie przekształcać z jednego rodzaju „zapis”, działa zgodnie z oczekiwaniami

pożądany efekt https://jsbin.com/bodaxefake/edit?html,output

Gdy wartości są zamiast podjąć obliczony styl CSS i ponownie zastosowany do animacji za pomocą matrix3d, animacja ma niewielkie zniekształcenie.

Zamiast tego spodziewam się odtworzyć animację, która ma dokładnie taki sam wynik, ponieważ dla mojego zrozumienia, matrix3d ​​z Window.getComputedStyle() powinien zwrócić tę samą wartość.

Nieprawidłowe działanie https://jsbin.com/luhikahexi/edit?html,output

Odpowiedz

5

Twój problem jest punkt numer 4. Ale tak naprawdę nie jest to błąd, to jest złożony algorytm próbuje dowiedzieć się, co prawda chcesz zrobić.

Kiedy robisz animację z obrotu (0deg) do obracania (360deg), czy zastanawiałeś się kiedyś, że 2 macierze są takie same? Jeśli określono tylko początkowe stany końcowe, animacja nie istnieje.

Po ustawieniu animacji w taki sam sposób, algorytm nie ma pojęcia o tym, co należy zrobić, więc zachowanie nie jest zgodne z oczekiwaniami. Ale nie powiedziałbym, że to błąd.

Ustawiłem animację, która robi to, co chcesz. Sztuczka polega na pozostawieniu stałej macierzy, dodaniu początkowego obrotu, czyli tego, co zmienimy, i dodaniu kolejnego obrotu przeciwnego do tego, aby zachować pierwotny stan.

Ponieważ ten fragment jest trochę rozbudowany, usunąłem prefiksy webkita. (Z drugiej strony, ani naprawdę potrzebne w dzisiejszych czasach)

console.clear(); 
 
document.addEventListener('DOMContentLoaded',() => { 
 
    let content1 = document.querySelector('#content1'); 
 
    var computedTransform = window.getComputedStyle(content1).transform; 
 
    console.log(computedTransform); 
 

 
});
@keyframes animation { 
 
    0% { 
 
    transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
    } 
 
    0.1% { 
 
    transform: rotateY(-179deg) rotateY(179deg) matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
    } 
 
    100% { 
 
    transform: rotateY(179deg) rotateY(179deg) matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
    } 
 
} 
 
#content1 { 
 
    animation: animation 2s; 
 
    animation-fill-mode: forwards; 
 
    transform: matrix3d(-0.999848, 0, 0.0174524, 0, 0, 1, 0, 0, -0.0349048, 0, -1.9997, 0, -6.98096, 0, -399.939, 1); 
 
}
<div id="wrapper1" style="position:fixed; top: 100px; left:300px; perspective: 1000px; width: 250px; height:250px; border: dotted 1px blue"> 
 
    <div id="content1" style="width: 250px; height:250px; background-color:lightsalmon; opacity:0.2;"> 
 
    </div> 
 
</div>

Prawdziwym problemem jest to, że nie ma wystarczająco dużo informacji na początku i na końcu punktu animacji, aby go odtworzyć. W macierzach transformacji nie ma informacji, którą podajesz w serii indywidualnych transformacji. Zobacz fragment kodu (w 2D): stan początkowy i końcowy są takie same, animacja nie jest. 3D, jest jeszcze bardziej możliwości wykorzystania

.test { 
 
    width: 50px; 
 
    height: 50px; 
 
    position: absolute; 
 
    top: 400px; 
 
    left: 100px; 
 
} 
 
#one { 
 
    background-color: lightgreen; 
 
    transform: translateX(200px); 
 
    animation: tr1 6s infinite; 
 
} 
 
@keyframes tr1 { 
 
    0% { 
 
    transform: rotate(0deg) translateX(200px) 
 
    } 
 
    33%, 
 
    100% { 
 
    transform: rotate(-90deg) translateX(200px) 
 
    } 
 
} 
 
#two { 
 
    background-color: lightblue; 
 
    transform: translate(200px, 0px); 
 
    animation: tr2 6s infinite; 
 
} 
 
@keyframes tr2 { 
 
    0%, 33% { 
 
    transform: translate(200px, 0px) rotate(0deg) 
 
    } 
 
    66%, 
 
    100% { 
 
    transform: translate(0px, -200px) rotate(-90deg) 
 
    } 
 
} 
 
#three { 
 
    background-color: tomato; 
 
    transform: translate(200px, -200px) rotate(0deg) translateY(200px); 
 
    animation: tr3 6s infinite; 
 
} 
 
@keyframes tr3 { 
 
    0%, 66% { 
 
    transform: translate(200px, -200px) rotate(0deg) translateY(200px) rotate(0deg); 
 
    } 
 
    100% { 
 
    transform: translate(200px, -200px) rotate(-270deg) translateY(200px) rotate(180deg); 
 
    } 
 
}
<div class="test" id="one">1</div> 
 
<div class="test" id="two">2</div> 
 
<div class="test" id="three">3</div>

+0

Odnośnie pkt 3. muszę rozwiązanie, w którym w klatce kluczowej 0% jest zwracana tylko za pomocą komputerowej stylu dom, myślisz, że jest to możliwe do osiągnięcia tego celu? Dziękuję za poświęcony czas. – GibboK

+1

Różnice, które widzisz dla 360deg, są nieistotne (e-16). Jest to po prostu zaokrąglenie błędu podczas konwersji z deg na rad, jak sądzę. Jeśli chodzi o inny problem, spróbuję, ale zauważ, że nadal możesz uzyskać wartość z DOM i właśnie dodałeś dwie rotacje. – vals

+0

Ustawiłem małą sztuczkę, aby uzyskać 0% do obliczonej wartości, nie jestem pewien, czy jest w porządku dla ciebie – vals

0

zgodnie ze specyfikacjami https://www.w3.org/TR/css-transforms-1/

jako początkowe i końcowe keyframes nie są opisane zarówno jako przekształcenie funkcji numeryczne interpolacja pomiędzy przekształcenie funkcji nie jest możliwe i przeglądarka potrzebuje zamiast tego korzystać z interpolacji macierzowej (zgodnie z ostatnią regułą interpolacji transformacji https://www.w3.org/TR/css-transforms-1/#interpolation-of-transforms).

Podczas interpolacji macierzy niektóre informacje o liczbie zwojów są tracone, a animacja może mieć inne zachowanie niż oczekiwano.

Demonstracja przy użyciu API animacji internetowych (najnowszy Chrome): - Na klatkę kluczową startową ustaw rotateZ 0. - Na Keyframe start ustawiony rotateZ do 360 lub 350. - Kliknij przycisk animowany.

Animacja traci informacje o zakrętach.

Warto zauważyć, że to zachowanie występuje również wtedy, gdy klatki kluczowe początku i końca są opisane zarówno jako funkcje transformacji, ale ich kolejność lub liczba argumentów jest inna.

(function() { 
 
      let data = { 
 
       translateX: { 
 
        type: 'range', 
 
        unit: 'px', 
 
        min: -200, 
 
        max: 200, 
 
        steps: 400, 
 
        value: { 
 
         start: 0, 
 
         end: 0 
 
        } 
 
       }, 
 
       translateY: { 
 
        type: 'range', 
 
        unit: 'px', 
 
        min: -200, 
 
        max: 200, 
 
        steps: 400, 
 
        value: { 
 
         start: 0, 
 
         end: 0 
 
        } 
 
       }, 
 
       translateZ: { 
 
        type: 'range', 
 
        unit: 'px', 
 
        min: -200, 
 
        max: 200, 
 
        steps: 400, 
 
        value: { 
 
         start: 0, 
 
         end: 0 
 
        } 
 
       }, 
 
       scaleX: { 
 
        type: 'range', 
 
        unit: '', 
 
        min: -3, 
 
        max: 3, 
 
        steps: 6, 
 
        value: { 
 
         start: 1, 
 
         end: 1 
 
        } 
 
       }, 
 
       scaleY: { 
 
        type: 'range', 
 
        unit: '', 
 
        min: -3, 
 
        max: 3, 
 
        steps: 6, 
 
        value: { 
 
         start: 1, 
 
         end: 1 
 
        } 
 
       }, 
 
       scaleZ: { 
 
        type: 'range', 
 
        unit: '', 
 
        min: -3, 
 
        max: 3, 
 
        steps: 6, 
 
        value: { 
 
         start: 1, 
 
         end: 1 
 
        } 
 
       }, 
 
       rotateX: { 
 
        type: 'range', 
 
        unit: 'deg', 
 
        min: -180, 
 
        max: 180, 
 
        steps: 360, 
 
        value: { 
 
         start: 0, 
 
         end: 0 
 
        } 
 
       }, 
 
       rotateY: { 
 
        type: 'range', 
 
        unit: 'deg', 
 
        min: -180, 
 
        max: 180, 
 
        steps: 360, 
 
        value: { 
 
         start: 0, 
 
         end: 0 
 
        } 
 
       }, 
 
       rotateZ: { 
 
        type: 'range', 
 
        unit: 'deg', 
 
        min: 0, 
 
        max: 360, 
 
        steps: 360, 
 
        value: { 
 
         start: 0, 
 
         end: 0 
 
        } 
 
       }, 
 
       skewX: { 
 
        type: 'range', 
 
        unit: 'deg', 
 
        min: 0, 
 
        max: 180, 
 
        steps: 180, 
 
        value: { 
 
         start: 0, 
 
         end: 0 
 
        } 
 
       }, 
 
       skewY: { 
 
        type: 'range', 
 
        unit: 'deg', 
 
        min: 0, 
 
        max: 180, 
 
        steps: 180, 
 
        value: { 
 
         start: 0, 
 
         end: 0 
 
        } 
 
       }, 
 
       perspective: { 
 
        type: 'range', 
 
        unit: 'px', 
 
        min: 200, 
 
        max: 1000, 
 
        steps: 800, 
 
        value: { 
 
         start: 1000, 
 
         end: 1000 
 
        } 
 
       }, 
 
       perspectiveOrigin: { 
 

 
        type: 'text', 
 
        unit: '', 
 
        value: { 
 
         start: '50% 50%', 
 
         end: '50% 50%' 
 
        } 
 
       } 
 
      }; 
 

 
      let player; 
 

 
      let submitedBy; 
 

 
      let elmForm, 
 
       elmPanelStart, 
 
       elmPanelEnd, 
 
       elmWrapper, 
 
       elmContent, 
 
       elmButtonAnimate, 
 
       elmButtonReset; 
 

 
      let getDoms =() => { 
 
       elmForm = document.querySelector('#form'); 
 
       elmPanelStart = document.querySelector('#panel-start'); 
 
       elmPanelEnd = document.querySelector('#panel-end'); 
 
       elmWrapper = document.querySelector('#wrapper'); 
 
       elmContent = document.querySelector('#content'); 
 
       elmButtonAnimate = document.querySelector('#button-animate'); 
 
       elmButtonReset = document.querySelector('#button-reset'); 
 
      }; 
 

 
      let init =() => { 
 
       getDoms(); 
 
       createUi('start'); 
 
       createUi('end'); 
 
       createUiHandlers('start'); 
 
       createUiHandlers('end'); 
 
       createUiHandlersControls(); 
 
      }; 
 

 
      let createUi = (type) => { 
 
       let html = ''; 
 
       Object.keys(data).forEach((name) => { 
 
        let props = data[name]; 
 
        if (props.type === 'range') { 
 
         html += `<label>${name}<input id="${name}-${type}" type="${props.type}" value="${props.value[type]}" name="${name}" min="${props.min}" max="${props.max}" steps="${props.steps}" ><input id="${name}-${type}-display" type="text" value="${props.value[type]}" name="${name}-${type}-show" readonly><br></label>`; 
 
        } 
 
        if (props.type === 'text') { 
 
         html += `<label>${name}<input id="${name}-${type}" type="${props.type}" value="${props.value[type]}" name="${name}" ></label><br>`; 
 
        } 
 
       }); 
 
       if (type === 'start') { 
 
        elmPanelStart.innerHTML = html; 
 
       } 
 
       if (type === 'end') { 
 
        elmPanelEnd.innerHTML = html; 
 
       } 
 
      }; 
 

 
      let updateDisplay = (type, name, value) => { 
 
       if (name === 'perspectiveOrigin') { 
 
        return; 
 
       } 
 
       let elmDisplay = document.querySelector(`#${name}-${type}-display`); 
 
       elmDisplay.value = value; 
 
      }; 
 

 
      let handler = (type, event) => { 
 
       let name = event.target.name, 
 
        value = event.target.value; 
 
       updateDisplay(type, name, value); 
 
       updateData(type, name, value); // update data 
 
       updateDomTarget(); 
 
      }; 
 
      let updateDomTarget =() => { 
 
       let inline = ''; 
 
       Object.keys(data).forEach((name) => { 
 
        if (name === 'perspective' || name === 'perspectiveOrigin') { 
 
         return; 
 
        } 
 
        let props = data[name]; 
 
        inline += ` ${name}(${props.value.start}${props.unit})`; 
 
       }); 
 
       inline = inline.trim(); 
 
       elmContent.style.transform = inline; 
 

 
       elmWrapper.style.perspective = `${data.perspective.value.start}${data.perspective.unit}`; 
 
       elmWrapper.style.perspectiveOrigin = `${data.perspectiveOrigin.value.start}${data.perspectiveOrigin.unit}`; 
 
      }; 
 

 
      let updateData = (type, name, value) => { 
 
       data[name].value[type] = value; 
 
      }; 
 

 
      let refresh =() => { 
 
       location.reload(); 
 
      }; 
 

 
      let resetPlayer =() => { 
 
       if (player) { 
 
        player.cancel(); 
 
        player = null; 
 
       } 
 
      }; 
 

 
      let logicAnimate =() => { 
 
       resetPlayer(); 
 
       let timing = { 
 
        duration: 1000, 
 
        fill: 'forwards' 
 
       }, 
 
       kfStart = '', 
 
       kfEnd = ''; 
 
       Object.keys(data).forEach((name) => { 
 
        if (name === 'perspective' || name === 'perspectiveOrigin') { 
 
         return; 
 
        } 
 
        let props = data[name]; 
 
        kfStart += ` ${name}(${props.value.start}${props.unit})`; 
 
        kfEnd += ` ${name}(${props.value.end}${props.unit})`; 
 
       }); 
 
       kfStart = kfStart.trim(); 
 
       kfEnd = kfEnd.trim(); 
 
       // change here 
 
       kfStartComputedStyle = window.getComputedStyle(elmContent).transform; 
 
       console.log(kfStartComputedStyle); 
 
       kfStart = { 
 
        transform: kfStartComputedStyle 
 
       }; 
 
       kfEnd = { 
 
        transform: kfEnd 
 
       }; 
 
       elmContent.animate([kfStart, kfEnd], timing); 
 

 
      }; 
 

 
      let createUiHandlers = (type) => { 
 
       Object.keys(data).forEach((name) => { 
 
        let elm = document.querySelector(`#${name}-${type}`); 
 
        elm.addEventListener('change', (event) => { 
 
         handler(type, event); 
 
        }); 
 
       }); 
 
      }; 
 

 
      let createUiHandlersControls = (type) => { 
 
       elmButtonAnimate.addEventListener('click', (event) => { 
 
        logicAnimate(); 
 
       }); 
 

 
       elmButtonReset.addEventListener('click', (event) => { 
 
        refresh(); 
 
       }); 
 
      }; 
 
      document.addEventListener('DOMContentLoaded',() => { 
 
       init(); 
 
      }); 
 
     })();
h1 { 
 
      font-size: 15px; 
 
     } 
 

 
     #content { 
 
      width: 150px; 
 
      height: 200px; 
 
      background-color: red; 
 
     } 
 

 
     #panel-start-wrapper { 
 
      position: fixed; 
 
      top: 0; 
 
      right: 0; 
 
      margin: 10px; 
 
     } 
 

 
     #panel-end-wrapper { 
 
      position: fixed; 
 
      top: 420px; 
 
      right: 0; 
 
      margin: 10px; 
 
     } 
 

 
     #panel-controls { 
 
      position: fixed; 
 
      top: 850px; 
 
      right: 0; 
 
      margin: 10px; 
 
     } 
 

 
     label { 
 
      display: block; 
 
     } 
 

 
     input[type=text] { 
 
      width: 50px; 
 
     }
<div id="wrapper" style="position:absolute; perspective: 500px; top:10%; left:10%;"> 
 
     <div id="content"> 
 
      Hello world! 
 
     </div> 
 
    </div> 
 
    <form id="form"> 
 
     <div id="panel-start-wrapper"> 
 
      <h1>Keyframe Start</h1> 
 
      <div id="panel-start"> 
 
      </div> 
 
     </div> 
 
     <div id="panel-end-wrapper"> 
 
      <h1>Keyframe End</h1> 
 
      <div id="panel-end"> 
 
      </div> 
 
     </div> 
 
     <div id="panel-controls"> 
 
      <button id="button-animate" type="button">Animate</button> 
 
      <button id="button-reset" type="button">Reset</button> 
 
     </div> 
 
    </form>

+0

Chciałbym podziękować za uroki za wskazanie mnie we właściwym kierunku (+1). – GibboK

Powiązane problemy