2012-08-28 19 views
7

tengo imagen estática 500x640 sentado en la carpeta catted por 20x20 piezas con sprites CSS, me he fijado background-position para mostrar cada pieza, necesito este tipo de pantalla para que sea capaz de manipular con cada pieza posterior.CSS Sprites de rendimiento

css:

.piece 
     { 
      width: 20px; 
      height: 20px; 
      display: inline-block; 
      //display: inline; 
      //zoom:1; 
     }   

    .ob { background-image: url("/Images/ob.jpg");} 

JS:

<script id="flipTemplate" type="text/html"> 
    <div class="piece ob" data-bind="style: { backgroundPosition: viewModel.getLeftValue($index) + ' ' + viewModel.getTopValue($index) }, attr: {cond: Cond, id: Id }, click: viewModel.setClick "> 
       </div> 
</script> 
<script type="text/javascript"> 
    viewModel = { 
     flips: ko.observableArray([]),  

     setClick: function (data, e) { 
      e.preventDefault();    
      //doing click 
     }, 

     getLeftValue: function (index) { 

      var position = 0; 

      var currentLine = div(index(), 25); 

      if (currentLine > 0) 
       return '-' + (index() - (currentLine * 25)) * 20 + 'px'; 
      else 
       return '-' + index() * 20 + 'px'; 
     }, 

     getTopValue: function (index) { 

      return '-' + (div(index(), 25)) * 20 + 'px'; 
     } 
    };  

    ko.applyBindings(viewModel); 
</script> 
function div(val, by){ 
    return (val - val % by)/by; 
} 

Así que estoy teniendo algunos problemas de rendimiento. Por ejemplo, en imágenes Opera y FF carga muy rápidamente alrededor de 1 seg, en IE unos 3 segundos, pero en Chrome se está cargando muy lento enter image description here

que está tomando alrededor de 17 segundos para mostrar todas las piezas en Chrome ...

navegador haciendo sólo una solicitud para obtener la imagen y de cortar pequeños trozos de ella, por lo que puede tardar tanto tiempo en Chrome?

¿Hay alguna manera puedo mejorar el rendimiento? enter image description here

acaba de hacer CTRL + Actualizar y aquí extraña consecuencia de carga: enter image description here

ACTUALIZACIÓN: que acaba de colocar una muestra aquí: http://bit.ly/TrcCdp

ACTUALIZACIÓN: En mi muestra no es JSON array, contiene 800 elementos, así que solo sé si lo hago menos; por ejemplo, entre 600 y 700 elementos, el rendimiento es cada vez mejor, pero de todos modos necesito 800 elementos.

por ejemplo cuando sólo hay 600 elementos que se reduce la carga en Chrome a aproximadamente 6 segundos ....

Así que probablemente puede ser el problema en alguna parte en el punto donde la iteración nocaut plantilla?

+0

Disculpe, la imagen es un poco pequeña. ¿Qué tan grande es tu sprite? – canon

+0

¿Eso es reproducible? – SLaks

+0

@canon si hace clic derecho en la imagen y presiona abrir, se abrirá en tamaño real (http://i.stack.imgur.com/WGdAr.jpg). Mi sprite es 83.78kb. – Kuncevic

Respuesta

4

El problema no es la imagen. La imagen se puede fijar mediante la colocación de una precarga en la parte superior, antes de cualquiera de las etiquetas de hojas de estilo o script:

<meta name="viewport" content="width=device-width"> 

<script type="text/javascript"> 
    var img = new Image(); 
    img.src = 'TestApp_files/obm000.jpg'; 
</script> 

<link href="TestApp_files/jquery00.css" rel="stylesheet"> 
<link href="TestApp_files/jquery01.css" rel="stylesheet"> 
<!-- ad nauseum --> 

Después de esto, la imagen se carga en 170 ms (localmente). Sin embargo, la página todavía se ensucia por otros 10-15 segundos después tratando de decidir qué hacer.

La raíz del asunto es que el Javascript es un caos absoluto. Los nombres de imagen/archivo/función son crípticos. Las cosas en el medio de la página dependen del código al final depende del código al principio depende del código al final. La lógica del controlador/vista/modelo está en todo el mapa. Variables globales y acoplamiento de archivos múltiples ... hokay, </soapbox>, ahora sobre el tratamiento del síntoma.

Problema 1: knockout de unión antes de la carga de DOM

applyBindings poner en una devolución de llamada domready:

jQuery(function($) { 
    ko.applyBindings(viewModel); 
}); 

Problema 2: foreach es lento

unión El foreach knockout es increíblemente lento con grandes conjuntos de datos. Puede probar las plantillas jQuery y mover el foreach dentro de la plantilla, as described in this SO question. Parece bajar el tiempo a unos 3 segundos.

Realmente no entiendo por qué es necesario, ya que parece funcionar bien con su foreach actual, simplemente se cuelga para siempre mientras que el nocaut hace algo de magia en el fondo que, por lo que puedo ver, ocurre después de foreach completa.

Nota al margen: ¿es necesario poner los flips en una matriz observable? Supongo que tiene la intención de usarlo más tarde ya que nada en el código actual lo necesita. De lo contrario, sáquelo y ayudará al rendimiento (aunque no resolverá este problema).

Saludos, espero que esto ayude.

2

Es una especie de error de representación extraño entre el enlace foreach y Chrome. Intenté simplemente agregar un personaje en tu plantilla antes del div y eso solucionó el retraso (pero también arruinó el diseño).

Una buena manera de arreglar esto es usar algo que no sea foreach. Mi repeat binding funciona bien aquí y resuelve el problema de demora.

aquí es que la sección de su código usando repeat:

<div class="condListHolder" style="width:558px"> 
    <div class="cond2" title="Click to flip" data-bind="repeat: flips"> 
     <div class="piece obm" data-bind=" 
      style: { backgroundPosition: getLeftValue($index) + ' ' + getTopValue($index) }, 
      attr: {cond: $item().cond, id: $item().Id }, 
      click: setClick "></div> 
    </div> 
</div> 

Debido repeat no utiliza un observable para $index, también tendrá que cambiar sus getTopValue y getLeftValue funciones para sacar los paréntesis () después de index.

1

También debe considerar la racionalización de su código que es llamado por el bucle foreach. No sé con qué frecuencia llama a los métodos getLeftValue y getTopValue pero no están muy optimizados.

  • Trate de limitar las llamadas a funciones que le dan el mismo resultado, utilice VARs locales para almacenar en caché ya que son baratos
  • no concatenar cadenas en grandes bucles, esto es mucho más lento que utilizar un conjunto para unirse a ellos.

Intenté optimizar sus dos funciones. Debería ver al menos alguna mejora:

getLeftValue: function (index) { 

    var position = 0, 
     realIndex = index(), 
     currentLine = div(realIndex, 25); 


    if (currentLine > 0) 
     return ["-", (realIndex - (currentLine * 25)) * 20, "px"].join(""); 
    else 
     return ["-", realIndex, "px"].join(""); 
}, 

getTopValue: function (index) { 

    return ["-",(div(index(), 25)) * 20,"px"].join(""); 
} 
Cuestiones relacionadas