Friday, October 20, 2006 1:56 PM
pmanach
Optimiser les performances d'animations sur des objets
Lorsque l'on souhaite animer de nombreux objets en appliquant des effets (ombrage par exemple), on peut rapidement tomber sur des problèmes de performance. Un exemple : soit des fiches produits avec une animation à la iTunes. Chaque fiche contient des images, du texte et des boutons. L'une des images a une ombrage. Lorsqu'on anime une quinzaine de fiches en même temps, on a le temps de prendre un café :(
Une solution peut alors consister à animer une image de l'objet, et non l'objet. Le bout de code suivant montre comment le faire sur un objet image avec un effet ombrage, mais cela marche aussi sur des boutons ou des canvas :
// un peu de code en dur pour le principe :)
int width = 88;
int height = 98;
int pixelsize = 4;
int stride = width * pixelsize;
// Chargement de l'image compilée comme ressource
BitmapImage ImageFromAssembly = new BitmapImage();
ImageFromAssembly.BeginInit();
ImageFromAssembly.UriSource = new Uri("pack://application:,,,/1786538.png");
ImageFromAssembly.EndInit();
// Création de l'objet image
Image notebook = new Image();
notebook.Source = ImageFromAssembly;
// Application de l'ombre
DropShadowBitmapEffect be = new DropShadowBitmapEffect();
be.Opacity = 0.8;
notebook.BitmapEffect = be;
// On force le rendu en mémoire
RenderTargetBitmap rtb = new RenderTargetBitmap(width, height, 96, 96, PixelFormats.Pbgra32);
notebook.Measure(new Size(width, height));
notebook.Arrange(new Rect(0, 0, width, height));
notebook.UpdateLayout();
rtb.Render(notebook);
// On copie les pixels, on créé une nouvelle source d'image et on l'affecte à l'objet à animer
Array pixels = new int[width * height * pixelsize];
rtb.CopyPixels(pixels, stride, 0);
BitmapSource newBms = BitmapSource.Create((int)width, (int)height, 96, 96, PixelFormats.Pbgra32, null, pixels, stride);
img.Source = newBms;
Ce faisant, on peut maintenant faire bouger l'image ombrée sans payer le prix de l'effet à chaque recalcul.