AlexSychovUN's picture
Updated all code
543ad41
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>NGL Visualization</title>
<script src="https://unpkg.com/ngl@2.0.0-dev.37/dist/ngl.js"></script>
<style>
html, body { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; font-family: 'Segoe UI', sans-serif; }
#viewport { width: 100%; height: 100%; background: linear-gradient(to bottom, #ffffff, #f0f2f5); }
#tooltip {
display: none;
position: absolute;
z-index: 100;
pointer-events: none;
background-color: rgba(30, 30, 30, 0.9);
color: #fff;
padding: 8px 12px;
border-radius: 6px;
font-size: 13px;
box-shadow: 0 4px 12px rgba(0,0,0,0.3);
white-space: nowrap;
border: 1px solid rgba(255,255,255,0.1);
}
#controls {
position: absolute;
top: 20px; right: 20px; z-index: 50;
background: rgba(255, 255, 255, 0.90);
padding: 15px; border-radius: 12px;
box-shadow: 0 4px 20px rgba(0,0,0,0.1);
display: flex; flex-direction: column; gap: 10px;
backdrop-filter: blur(5px);
border: 1px solid #eee;
}
.control-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.label-text { font-size: 14px; font-weight: 600; color: #333; }
.btn-shot {
background: #007bff; color: white; border: none; padding: 8px 12px;
border-radius: 6px; cursor: pointer; font-size: 13px; font-weight: bold;
transition: background 0.2s; display: flex; align-items: center; justify-content: center; gap: 5px;
}
.btn-shot:hover { background: #0056b3; }
input[type=checkbox] { cursor: pointer; transform: scale(1.2); accent-color: #007bff; }
</style>
</head>
<body>
<div id="controls">
<div class="control-row">
<span class="label-text">Heatmap Colors</span>
<input type="checkbox" id="heatmapToggle">
</div>
<div class="control-row">
<span class="label-text">Auto Spin</span>
<input type="checkbox" id="spinToggle">
</div>
<div style="height: 1px; background: #ddd; margin: 5px 0;"></div>
<button class="btn-shot" id="screenshotBtn">📷 Screenshot</button>
</div>
<div id="tooltip"></div>
<div id="viewport"></div>
<script>
var pdbData = `{{ pdb_block }}`;
var selectionString = "{selection_str}";
var component;
var stage;
document.addEventListener("DOMContentLoaded", function () {
stage = new NGL.Stage("viewport", { backgroundColor: "white" });
var tooltip = document.getElementById("tooltip");
var toggleHeatmap = document.getElementById("heatmapToggle");
var toggleSpin = document.getElementById("spinToggle");
var btnScreenshot = document.getElementById("screenshotBtn");
var stringBlob = new Blob([pdbData], {type: 'text/plain'});
stage.loadFile(stringBlob, { ext: 'pdb' }).then(function (o) {
component = o;
updateVisualization();
o.autoView();
});
function updateVisualization() {
if (!component) return;
component.removeAllRepresentations();
var useHeatmap = toggleHeatmap.checked;
if (useHeatmap) {
component.addRepresentation("ball+stick", {
colorScheme: "bfactor",
colorDomain: [0.1, 0.9],
colorScale: ["#2d34bf", "#ffffff", "#d90429"],
radiusScale: 1.0
});
} else {
component.addRepresentation("ball+stick", {
colorScheme: "element",
radiusScale: 1.0
});
}
if (selectionString.length > 1 && selectionString !== "@-1") {
component.addRepresentation("label", {
sele: selectionString,
labelType: "atomindex",
color: "black",
radius: 1.1,
yOffset: 0.0,
zOffset: 2.0,
attachment: "middle_center",
pickable: true
});
}
}
toggleHeatmap.addEventListener("change", updateVisualization);
toggleSpin.addEventListener("change", function() {
if(toggleSpin.checked) { stage.setSpin(true); } else { stage.setSpin(false); }
});
btnScreenshot.addEventListener("click", function() {
stage.makeImage({factor: 1, antialias: true, trim: false, transparent: false}).then(function(blob) {
NGL.download(blob, "biobind_visualization.png");
});
});
stage.mouseControls.remove("hoverPick");
stage.signals.hovered.add(function (pickingProxy) {
if (pickingProxy && (pickingProxy.atom || pickingProxy.closestBondAtom)) {
var atom = pickingProxy.atom || pickingProxy.closestBondAtom;
var score = atom.bfactor.toFixed(3);
var idx = atom.index;
var name = atom.atomname;
if (!name) name = atom.element;
if (!name) name = "Unknown";
var html = '<div><b>ID:</b> ' + idx + ' <span style="color:#aaa">|</span> <b>Atom:</b> ' + name + '</div>' +
'<div style="margin-top:4px;"><b>Importance:</b> <span style="color: #ff6b6b; font-weight:bold;">' + score + '</span></div>';
tooltip.innerHTML = html;
tooltip.style.display = "block";
var cp = pickingProxy.canvasPosition;
tooltip.style.left = (cp.x + 20) + "px";
tooltip.style.top = (cp.y + 20) + "px";
} else {
tooltip.style.display = "none";
}
});
window.addEventListener("resize", function(event){ stage.handleResize(); }, false);
});
</script>
</body>
</html>