如何在 canvas 上绘制大量矩形且性能良好?
How to draw a lot of rectangles on canvas with good performance?
我必须渲染带有扇区、行和座位的电影院大厅地图。
目前我有大约 1000 个座位(实心矩形)要绘制,我正在为每个座位绘制:
canvas.drawRect(seatRect, seatPaint)
我的视图还必须支持缩放、滚动和滑动。
表现很糟糕。我试图通过显式启用硬件加速来改进它,但没有任何改变,它似乎在我的 Nexus 4 上默认启用 (Api 22)
你能推荐一些高速渲染大量矩形的方法吗?所以移动,缩放动画很流畅。
自定义视图class代码:
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor); // scaling support
canvas.translate(mTranslateX, mTranslateY); // scrolling support
if (mEventMap != null) {
mEventMap.paint(canvas);
}
canvas.restore();
}
EventMap代码:
public void paint(Canvas canvas) {
for (EventPlace place : places) {
if (place.isSelected())
placePaint.setColor(0xFF00FF00);
else if (place.isAvailable())
placePaint.setColor(place.getColor());
else
placePaint.setColor(0xFF000000);
canvas.drawRect(place.getBounds(), placePaint);
}
}
None 在 onDraw 中调用的方法创建任何实例。
只有很多矩形...
你现在面临的主要问题基本上是你执行了大量的绘图循环(等于你拥有的 Rects 的数量),最好将所有这些 rects 存储在 Path 对象中,以减少绘图周期数。由于您有三种座位状态,我建议创建三个路径。我建议这样做:
private void init() {
mSelectedPath = new Path();
mAvailablePath = new Path();
mUnavalablePath = new Path();
mAvailablePaint = new Paint();
mSelectedPaint = new Paint();
mUnavalablePaint = new Paint();
mUnavalablePaint.setColor(Color.RED);
mSelectedPaint.setColor(Color.YELLOW);
mAvailablePaint.setColor(Color.GREEN);
for (EventPlace place : mData) {
if (place.isSelected())
mSelectedPath.addRect(rectF, Path.Direction.CW);
else if (place.isAvailable())
mAvailablePath.addRect(rectF, Path.Direction.CW);
else
mUnavalablePath.addRect(rectF, Path.Direction.CW);
}
}
然后当你想将日期与这个视图相关联时,你应该这样做:
public void setData(List<EventPlace> data) {
mData = data;
init();
invalidate();
}
实际上你可以随心所欲地做,只是要记住你必须调用 init 方法然后 invalidate。在 onDraw 中:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor); // scaling support
canvas.translate(mTranslateX, mTranslateY); // scrolling support
canvas.drawPath(mAvailablePath, mAvailablePaint);
canvas.drawPath(mUnavalablePath, mUnavalablePaint);
canvas.drawPath(mSelectedPath, mSelectedPaint);
canvas.restore();
}
也许您还想添加一些逻辑以从路径中排除那些目前不可见的 Rect,以调整性能。
我尝试在 Rects 的测试集上对我的方法进行动画处理,它 运行 顺利地使用了 200 个 rects,但我没有尝试执行严格的基准测试
我必须渲染带有扇区、行和座位的电影院大厅地图。 目前我有大约 1000 个座位(实心矩形)要绘制,我正在为每个座位绘制:
canvas.drawRect(seatRect, seatPaint)
我的视图还必须支持缩放、滚动和滑动。 表现很糟糕。我试图通过显式启用硬件加速来改进它,但没有任何改变,它似乎在我的 Nexus 4 上默认启用 (Api 22)
你能推荐一些高速渲染大量矩形的方法吗?所以移动,缩放动画很流畅。
自定义视图class代码:
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor); // scaling support
canvas.translate(mTranslateX, mTranslateY); // scrolling support
if (mEventMap != null) {
mEventMap.paint(canvas);
}
canvas.restore();
}
EventMap代码:
public void paint(Canvas canvas) {
for (EventPlace place : places) {
if (place.isSelected())
placePaint.setColor(0xFF00FF00);
else if (place.isAvailable())
placePaint.setColor(place.getColor());
else
placePaint.setColor(0xFF000000);
canvas.drawRect(place.getBounds(), placePaint);
}
}
None 在 onDraw 中调用的方法创建任何实例。 只有很多矩形...
你现在面临的主要问题基本上是你执行了大量的绘图循环(等于你拥有的 Rects 的数量),最好将所有这些 rects 存储在 Path 对象中,以减少绘图周期数。由于您有三种座位状态,我建议创建三个路径。我建议这样做:
private void init() {
mSelectedPath = new Path();
mAvailablePath = new Path();
mUnavalablePath = new Path();
mAvailablePaint = new Paint();
mSelectedPaint = new Paint();
mUnavalablePaint = new Paint();
mUnavalablePaint.setColor(Color.RED);
mSelectedPaint.setColor(Color.YELLOW);
mAvailablePaint.setColor(Color.GREEN);
for (EventPlace place : mData) {
if (place.isSelected())
mSelectedPath.addRect(rectF, Path.Direction.CW);
else if (place.isAvailable())
mAvailablePath.addRect(rectF, Path.Direction.CW);
else
mUnavalablePath.addRect(rectF, Path.Direction.CW);
}
}
然后当你想将日期与这个视图相关联时,你应该这样做:
public void setData(List<EventPlace> data) {
mData = data;
init();
invalidate();
}
实际上你可以随心所欲地做,只是要记住你必须调用 init 方法然后 invalidate。在 onDraw 中:
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor); // scaling support
canvas.translate(mTranslateX, mTranslateY); // scrolling support
canvas.drawPath(mAvailablePath, mAvailablePaint);
canvas.drawPath(mUnavalablePath, mUnavalablePaint);
canvas.drawPath(mSelectedPath, mSelectedPaint);
canvas.restore();
}
也许您还想添加一些逻辑以从路径中排除那些目前不可见的 Rect,以调整性能。
我尝试在 Rects 的测试集上对我的方法进行动画处理,它 运行 顺利地使用了 200 个 rects,但我没有尝试执行严格的基准测试