// Just copy & paste these functions as-is: function sendMessageToStreamlitClient(type, data) { var outData = Object.assign({ isStreamlitMessage: true, type: type, }, data); window.parent.postMessage(outData, "*"); } function init() { sendMessageToStreamlitClient("streamlit:componentReady", {apiVersion: 1}); } function setFrameHeight(height) { sendMessageToStreamlitClient("streamlit:setFrameHeight", {height: height}); } // The `data` argument can be any JSON-serializable value. function sendDataToPython(data) { // console.log("Sending data: ", data.value); sendMessageToStreamlitClient("streamlit:setComponentValue", data); } // Now modify this part of the code to fit your needs: let damaged_parts = {}; let severity_colors = {0: "#FFFFFF", 1: "#FFFF00", 2: "#FFA500", 3: "#FF0000"}; var paths = document.querySelectorAll("[data-name]"); paths.forEach(function (path) { path.setAttribute('data-severity', 0); }); function getDamagedParts() { var damaged_parts = {}; paths.forEach(function (path) { var severity = parseInt(path.getAttribute('data-severity')); var part_name = path.dataset.name; damaged_parts[part_name] = severity; }); return damaged_parts; } paths.forEach(function (path) { path.addEventListener("click", function () { let severity = parseInt(path.getAttribute('data-severity')); severity = (severity + 1) % 4; path.setAttribute('data-severity', severity); path.style.fill = severity_colors[severity]; // damaged_parts[path.dataset.name] = severity; // Update the damaged parts state document.getElementById("details-box").innerHTML = `${path.dataset.name} - ${severity}`; sendDataToPython({ value: getDamagedParts(), dataType: "json", }); }); }); paths.forEach(function (path) { path.addEventListener("contextmenu", function (e) { e.preventDefault(); let severity = (parseInt(path.getAttribute('data-severity')) + 3) % 4; path.setAttribute('data-severity', severity); path.style.fill = severity_colors[severity]; // damaged_parts[path.dataset.name] = severity; // Update the damaged parts state document.getElementById("details-box").innerHTML = `${path.dataset.name} - ${severity}`; sendDataToPython({ value: getDamagedParts(), dataType: "json", }); }); }); var tooltipSpan = document.getElementById('details-box'); document.addEventListener('mouseover', function (e) { if (e.target.tagName == 'path') { var severity = parseInt(e.target.getAttribute('data-severity')); var part_name = e.target.dataset.name; if (part_name == undefined) { document.getElementById("details-box").style.opacity = "0%"; } else { document.getElementById("details-box").innerHTML = part_name + " - " + severity; document.getElementById("details-box").style.opacity = "100%"; document.getElementById("details-box").style.display = "block"; } } else { document.getElementById("details-box").style.opacity = "0%"; } }); window.onmousemove = function (e) { var x = e.clientX, y = e.clientY; tooltipSpan.style.top = (y + 20) + 'px'; tooltipSpan.style.left = (x) + 'px'; }; // data is any JSON-serializable value you sent from Python, and it's already deserialized for you. function onDataFromPython(event) { if (event.data.type !== "streamlit:render") return; damaged_parts = event.data.args.damages; // Access values sent from Python here! img_name = event.data.args.img_name; reset = event.data.args.reset; view = event.data.args.view; if (view == "Front") { document.getElementById("car-map").style.transform = `rotate(180deg)`; document.getElementById("front").style.top = `90%`; document.getElementById("back").style.bottom = `90%`; document.getElementById("arrow").style.rotate = `180deg`; } // Reset annotations if requested if (reset) { for (var key in damaged_parts) { damaged_parts[key] = 0; // Set each key's value to 0 } paths.forEach(function (path) { path.setAttribute('data-severity', 0); path.style.fill = severity_colors[0]; // Reset to default color }); } for (var key in damaged_parts) { try { var path = document.querySelector("[data-name='" + unescape(encodeURIComponent(key)) + "']"); path.style.fill = severity_colors[damaged_parts[key]]; path.setAttribute('data-severity', damaged_parts[key]); } catch (error) { console.log("Error: " + key); } } sendDataToPython({ value: damaged_parts, dataType: "json", }); } // Hook things up! window.addEventListener("message", onDataFromPython); init(); // Hack to autoset the iframe height. window.addEventListener("load", function() { window.setTimeout(function() { setFrameHeight(document.documentElement.clientHeight) }, 0); }); // Optionally, if the automatic height computation fails you, give this component a height manually setFrameHeight(440);