#flutter #canvas #imagefilter
Вопрос:
Я пытаюсь применить последовательность ImageFilter
s к текущему нарисованному Canvas
слою.
canvas.drawCircle(...)
canvas.drawCircle(...)
// TODO Apply ImageFilter 1: Blur
// TODO Apply ImageFilter 2: Blur again
Есть ли простой способ сделать это? Вероятно, мне не хватает какого-то простого метода, но я ничего не смог найти…
Вещи, которые я пробовал:
Я знаю, что могу указать объединенные ImageFilter
в Paint
, но это не работает — я хочу применять их последовательно после того, как все фигуры будут нарисованы, а к каждой фигуре отдельно.
saveLayer
кажется, это ближе всего к достижению того, что мне нужно, но, согласно документам, это применимо только ColorFilter
. Они также говорят, что это немного неэффективно.
saveLayer(null, Paint()..colorFilter = filter2)
saveLayer(null, Paint()..colorFilter = filter1)
..
canvas.draw
canvas.draw
...
restore()
restore()
Спасибо!
Комментарии:
1. Спасибо, это применит эффект к каждой нарисованной фигуре отдельно. Я нашел кое-что в то же время PaintingContext.addLayer может быть решением, попробовав его…
2. Да, спасибо, мне удалось сделать это со слоями и полем рендеринга.
Ответ №1:
Для дальнейшего использования я смог добиться желаемого эффекта с помощью RenderBox
(это можно использовать, например, из LeafRenderObjectWidget
).
RenderBox
Имеет метод рисования:
@override
void paint(PaintingContext context, Offset offset) {
context.pushLayer(
ColorFilterLayer(colorFilter: ColorFilter.matrix(...)),
(PaintingContext context2, Offset offset2) =>
context2.pushLayer(
ImageFilterLayer(imageFilter: ui.ImageFilter.blur(...)),
(PaintingContext context3, Offset offset3) =>
simulation.draw(context3.canvas),
offset2),
offset);
Не то, что simulation.draw(context3.canvas)
будет отображаться на холсте, за которым следует размытие ImageFilter
, а затем ColorFilter
. Layers
Можно добавить любое количество, хотя синтаксис немного болезненный. При необходимости его можно упростить с некоторыми усилиями:
/// Returns the painter with the given layer applied.
PaintingContextCallback withLayer(
ContainerLayer layer, PaintingContextCallback painter) {
return (PaintingContext context, Offset offset) =>
context.pushLayer(layer, painter, offset);
}
...
final List<ContainerLayer> layers = [...];
var painter = ...
for (final layer in layers) {
painter = withLayer(layer, painter);
}
painter(context, offset);
Комментарии:
1. Спасибо, уже намного чище! В моем случае я применял переменное количество фильтров, поэтому в итоге я получил простую вспомогательную функцию, обновил ответ.
2. Ваша вставка имеет тайм-аут, поэтому не может включать ее в качестве альтернативного предложения: (Я думаю, что в некоторых случаях ваш может быть лучше.