Страницы

Поиск по вопросам

четверг, 5 декабря 2019 г.

Закрасить текст, слово, букву

#c_sharp #wpf


Доброго времени суток.

WPF Разрабатываю караоке плеер. Основную часть сделал. Получаю текст и музыку всё
проигрываю всё хорошо) Встала задача теперь все это дело красиво вывести, как в настоящем
караоке. что бы две строчки и текст закрашивать постепенно по тайм коду. 

Так вот и вопрос как сделать красиво закрасить текст. Что для этого можно использовать?
Подскажите, направьте. Заранее спасибо. 
    


Ответы

Ответ 1



Вот вам решение с контурами букв и побуквенной постепенной заливкой. Идея решения одолжена из комментария @S.Kost и здесь. Для начала определим наш XAML. Определяем невидимый TextBlock с текстом. Мы стащим из него свойства, и отрендерим текст самостоятельно. Почему нельзя было использовать видимый TextBlock? Дело в том, что он не умеет отрисовывать границу глифов, а мы хотим в начале, чтобы буквы были «пустыми». Под ним в том же Grid'е кладём Path, который и будет содержать наш текст. У него есть Stroke, задающий границу, установим его цвет в чётный и толщину в пол-пикселя. Затем, в заполнении кладётся наша градиентная заливка. Кладём 2 контрольных точки, которые будут пробегаться по каждой букве. Слева от первой точки будет чёрная, справа — белая заливка. Между точками — переход. Затем, анимация. Мы анимируем продвижение контрольных точек вдоль букв. Откуда и докуда происходит анимация, устанавливается в code-behind. С XAML'ом покончено, теперь code-behind. Для начала, нам нужна функция, которая вытащит из текста его геометрию, и измерит ширины всех букв. Заодно пропустим пробелы, их анимировать не стоит. Для измерения геометрии текста воспользуемся удобным классом FormattedText. double extent; // общая ширина текста List boundingBoxes; // прямоугольники с каждым символом void Create() // https://msdn.microsoft.com/en-us/library/ms745816(v=vs.110).aspx { TextBlock tb = Source; var text = tb.Text; FormattedText formattedText = new FormattedText( text, CultureInfo.GetCultureInfo("en-US"), FlowDirection.LeftToRight, new Typeface( tb.FontFamily, tb.FontStyle, tb.FontWeight, tb.FontStretch), tb.FontSize, Brushes.Black // конкретная кисть нам не важна, мы используем только геометрию ); // стащили геометрию у текста... var geo = formattedText.BuildGeometry(new Point()); // ...и отдали её Path'у Target.Data = geo; var bb = formattedText.BuildHighlightGeometry(new Point()); extent = bb.Bounds.Width; // общая ширина boundingBoxes = // побуквенная ширина и позиции Enumerable.Range(0, text.Length) .Where(k => !char.IsWhiteSpace(text[k])) .Select(k => formattedText.BuildHighlightGeometry(new Point(), k, 1) .Bounds) .ToList(); } Ну и нам нужна функция, запускающая в цикле для каждой буквы анимацию. Это совсем просто: async void Play() { var storyboard = (Storyboard)Target.Resources["AnimationStoryboard"]; var fromAnimation = (DoubleAnimation)storyboard.Children[0]; var toAnimation = (DoubleAnimation)storyboard.Children[1]; foreach (var b in boundingBoxes) { await Task.Delay(250); // перерыв между буквами fromAnimation.From = b.Left / extent; fromAnimation.To = b.Right / extent; toAnimation.From = b.Left / extent; toAnimation.To = b.Right / extent; storyboard.Begin(); await Task.Delay(250); // дождёмся конца анимации } } Результат:

Ответ 2



Посмотрите в сторону RichTextBox. Позволяет получить часть текста TextRange и отформатировать методом ApplyPropertyValue.

Ответ 3



Можете исползовать The TextBlock control - Inline formatting TextBlock tb = new TextBlock(); tb.TextWrapping = TextWrapping.Wrap; tb.Margin = new Thickness(10); tb.Inlines.Add("An example on "); tb.Inlines.Add(new Run("the TextBlock control ") { FontWeight = FontWeights.Bold }); tb.Inlines.Add("using "); tb.Inlines.Add(new Run("inline ") { FontStyle = FontStyles.Italic }); tb.Inlines.Add(new Run("text formatting ") { Foreground = Brushes.Blue }); tb.Inlines.Add("from "); tb.Inlines.Add(new Run("Code-Behind") { TextDecorations = TextDecorations.Underline }); tb.Inlines.Add(".");

Комментариев нет:

Отправить комментарий