






在联网加载瓦片地图文件的过程中,当缩放切换的时候,需要一个过渡效果,如果没有这个过渡,可能会先出现一个空白界面,然后才是一张张瓦片返回来进行绘制,这样给用户的感觉是很慢,肉眼可见的在空白区域有一张图片进行加载,后面大量参考了许多gis软件,比如著名的qgc,他是在切换的过程中,如果地图放大,先将上一张整体绘制好的瓦片完整图片放大一倍,然后取中间部分,绘制到界面上作为底图,然后再慢慢加载各个区域的瓦片地图进行重新绘制,给人的感觉就是瞬间拿到了瓦片,其实不是的,仅仅是原来的放大的图片,恰好将要下载的最终生成的也是这块区域的,只是强制放大的会模糊一点,不影响使用,而且给人的感官非常好,以为瞬间下载好了,然后慢慢调整了清晰度。于是在这个地图组件中也使用了这个策略,感觉非常棒,用户终于不再抱怨说对比其他gis软件怎么感觉我的要慢一些了。

//缩放动画/正弦缓出曲线
m_zoom_anim.setDuration(300);
m_zoom_anim.setTargetObject(this);
m_zoom_anim.setEasingCurve(QEasingCurve::OutSine);
connect(&m_zoom_anim, SIGNAL(valueChanged(QVariant)), this, SLOT(onZoomAnimValueChanged(QVariant)));
connect(&m_zoom_anim, SIGNAL(finished()), this, SLOT(stopZoomAnim()));
void MapControl::startZoomAnim(int target_zoom, const QPointF &anchor)
{
//先取消瓦片下载
m_image_manager->abortLoading();
//未启用缩放动画/直接切换缩放级别
if (!m_zoom_anim_enabled || !this->isVisible()) {
m_cur_zoom = target_zoom;
this->changeZoom();
return;
}
//停止正在进行的动画
if (m_zoom_anim_active) {
m_zoom_anim.stop();
}
//直接使用主屏幕缓冲作为动画素材/记录绘制偏移量
m_zoom_anim_screen = m_screen_primary;
m_zoom_anim_offset = -(m_viewport_center_px + mapFocusPointWorldPx() - m_screen_focus_point).rawPoint();
//设置缩放锚点/滚轮缩放为鼠标位置/按钮缩放为视口中心
m_zoom_anim_anchor = anchor.isNull() ? QPointF(m_viewport_center_px.x(), m_viewport_center_px.y()) : anchor;
//计算目标缩放比例/每级差2倍
int diff = target_zoom - m_cur_zoom;
m_zoom_anim_target = qPow(2.0, diff);
m_zoom_anim_scale = 1.0;
m_zoom_anim_active = true;
//启动动画/从1.0插值到目标比例
m_zoom_anim.setStartValue(1.0);
m_zoom_anim.setEndValue(m_zoom_anim_target);
m_zoom_anim.start();
//立即更新缩放级别/触发新瓦片加载
m_cur_zoom = target_zoom;
m_screen_primary.fill(Qt::transparent);
this->changeZoom();
}
void MapControl::stopZoomAnim()
{
if (m_zoom_anim_active) {
m_zoom_anim_active = false;
m_zoom_anim.stop();
m_zoom_anim_scale = 1.0;
this->update();
}
}
void MapControl::drawZoomAnim(QPainter *painter)
{
qreal cx = m_zoom_anim_anchor.x();
qreal cy = m_zoom_anim_anchor.y();
painter->save();
painter->translate(cx, cy);
painter->scale(m_zoom_anim_scale, m_zoom_anim_scale);
painter->translate(-cx, -cy);
painter->drawPixmap(m_zoom_anim_offset, m_zoom_anim_screen);
painter->restore();
}
void MapControl::onZoomAnimValueChanged(const QVariant &value)
{
//从1.0插值到目标比例
m_zoom_anim_scale = value.toReal();
this->update();
}
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。