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.