如何在QtWebEngineView谷歌地图应用中计算并显示真实FPS
问题描述
我用QtWebEngineView开发了一个项目,通过加载谷歌地图展示从CSV文件读取的车辆位置。项目逻辑为每16ms读取一组经纬度数据并更新地图上的车辆标记,预期达到60FPS,但无法确认实际帧率是否符合预期。此前尝试通过统计getLocation()函数的调用次数计算FPS,但该方式不准确——真实FPS取决于地图的渲染操作(如拖拽窗口、缩放地图时的渲染),而非数据更新频率。需要解决正确计算并显示真实FPS的问题。
现有代码
MyMap.qml
Window { id: myMap title: "Google Map" width: 1600 height: 900 QtObject{ id: backendId WebChannel.id: "backend" } WebChannel { id: myWebChannel registeredObjects: backendId } WebEngineView { id: webview anchors.fill: parent webChannel: myWebChannel settings.javascriptEnabled: true url: "html/index.html" settings { autoLoadImages: true dnsPrefetchEnabled: false accelerated2dCanvasEnabled: true javascriptEnabled: true webGLEnabled:true pdfViewerEnabled: false } } }
index.html
<!DOCTYPE html> <html> <head> <title>Google Maps Example</title> <link rel="stylesheet" type="text/css" href="style.css"> <script src="qwebchannel.js"></script> </head> <body> <div id="map-container"> <div id="map"></div> <div class="velocity"> <p id="Fps">0 </p> </div> </div> <br> <script async src="https://maps.googleapis.com/maps/api/js?v=3.54&key=apiKey&language=ja&callback=initMap"> </script> <script src="index.js"></script> <br> </body> </html>
index.js
// Define let TILT = 55; let HEADING = 0; let ZOOM = 18; // Variable let map; let directionsRenderer; let directionsService; let backend; let rawMarker; let icon; //calculate fps let m_fps; let prevTime; let curTime; let isFirstCount; // Function function initMap() { var webChannel = new QWebChannel(qt.webChannelTransport, function(channel){ backend = channel.objects.backend; }); map = new google.maps.Map(document.getElementById("map"), mapOptions); directionsRenderer = new google.maps.DirectionsRenderer(); directionsRenderer.setMap(map); directionsService = new google.maps.DirectionsService(); geocoder = new google.maps.Geocoder(); rawMarker = new google.maps.Marker({ position: { lat: 21.007571859312662, lng: 105.79382411840304 }, map: map, draggable: false, title: "Raw Marker", icon: { url: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png', scaledSize: new google.maps.Size(40, 40) } }); fps_disp = document.getElementById("Fps"); //fps m_fps = 0; prevTime = 0; curTime = 0; isFirstCount = true; } function getLocation(lat0, lon0) { var rawLocation = new google.maps.LatLng(lat0, lon0); myMarker.setPosition(rawLocation); map.setCenter(rawLocation); calFps(); } function calFps() { window.requestAnimationFrame(() => { curTime = performance.now(); if(isFirstCount) { isFirstCount = false; prevTime = curTime; } if(curTime-prevTime>= 1000) { dispFps(m_fps) m_fps = 0; prevTime = curTime; } else { m_fps++; } }); } function dispFps(m_fps){ fps_disp.innerHTML = "<b>FPS:</b> " + m_fps; }
解决方案
核心思路:用requestAnimationFrame的回调次数统计真实渲染帧率——这个API会在浏览器每次准备绘制新帧时触发,完全同步于渲染周期,能准确反映地图的实际渲染FPS,覆盖数据更新、拖拽、缩放等所有触发渲染的场景。
修改步骤:
- 移除
getLocation()中的calFps()调用,避免数据更新频率干扰渲染帧率统计。 - 重构FPS统计逻辑,启动持续的
requestAnimationFrame循环,独立统计渲染帧数量。 - 修复原代码中
myMarker未定义、mapOptions缺失的问题,确保代码可正常运行。
修改后的index.js代码:
// Define let TILT = 55; let HEADING = 0; let ZOOM = 18; // Variable let map; let directionsRenderer; let directionsService; let backend; let rawMarker; let icon; // FPS统计变量 let fpsCount = 0; let lastTimestamp = 0; let fpsDisplay = null; // Function function initMap() { var webChannel = new QWebChannel(qt.webChannelTransport, function(channel){ backend = channel.objects.backend; }); // 补充缺失的地图配置 const mapOptions = { center: { lat: 21.007571859312662, lng: 105.79382411840304 }, zoom: ZOOM, tilt: TILT, heading: HEADING }; map = new google.maps.Map(document.getElementById("map"), mapOptions); directionsRenderer = new google.maps.DirectionsRenderer(); directionsRenderer.setMap(map); directionsService = new google.maps.DirectionsService(); geocoder = new google.maps.Geocoder(); rawMarker = new google.maps.Marker({ position: { lat: 21.007571859312662, lng: 105.79382411840304 }, map: map, draggable: false, title: "Raw Marker", icon: { url: 'http://maps.google.com/mapfiles/ms/icons/green-dot.png', scaledSize: new google.maps.Size(40, 40) } }); fpsDisplay = document.getElementById("Fps"); // 启动FPS统计循环 requestAnimationFrame(updateFps); } function getLocation(lat0, lon0) { var rawLocation = new google.maps.LatLng(lat0, lon0); // 修正原代码中myMarker未定义的问题 rawMarker.setPosition(rawLocation); map.setCenter(rawLocation); } // 持续统计FPS的函数 function updateFps(timestamp) { if (!lastTimestamp) { lastTimestamp = timestamp; } fpsCount++; const elapsed = timestamp - lastTimestamp; // 每1秒计算并展示一次FPS if (elapsed >= 1000) { const fps = Math.round(fpsCount / (elapsed / 1000)); fpsDisplay.innerHTML = `<b>FPS:</b> ${fps}`; fpsCount = 0; lastTimestamp = timestamp; } // 持续循环,同步渲染周期 requestAnimationFrame(updateFps); }
关键说明:
requestAnimationFrame(updateFps)会持续触发,每次触发对应浏览器的一次渲染帧,计数该回调的次数即为真实渲染帧率。- 使用浏览器提供的
timestamp参数计算时间差,比performance.now()更贴合渲染周期的时间基准。 - 修复了原代码中的两处错误,确保项目可正常运行。
内容的提问来源于stack exchange,提问作者Huy Nguyễn
相关产品推荐
相关产品推荐

