[英]Copying a vis-network network to another canvas
我正在實施“放大鏡”,即。 跟隨鼠標指針的“放大鏡”。 可見網絡圖的一部分在放大鏡內放大顯示(這樣您就可以在不放大整個網絡的情況下看到細節)。 我通過創建一個與可見網絡具有相同節點和邊緣以及相同視點的屏幕外可見網絡來做到這一點,但規模是其三倍。 然后,我使用canvas
drawImage
將這個較大網絡的 canvas 的一部分復制到浮動在可見網絡上方的div
中,並以鼠標指針為中心。 這一切都很好,除了我在將放大的圖像與正在放大的可見 map 的部分對齊時遇到問題。
在我的第一次嘗試中,放大的 map 部分距離可見 map 上的鼠標指針位置很遠。 但是在一個繁瑣的實驗過程中,我設法弄清楚我需要一個乘數(我在下面的代碼中將其稱為magicNumber
)來使其大致正確,即放大鏡顯示網絡位的放大視圖在指針下。 我希望這個幻數實際上是 vis-network 中的某個常數,但我想不出它會是什么——正確的值可能不完全是我通過實驗獲得的 1.92。
因此,我的問題是:這個數字應該是多少,它是什么意思?
這里有一個MVE https://codepen.io/micrology/pen/eYBbKVX
這是我的代碼的摘錄 - 首先是放大鏡的 CSS,然后是 JavaScript:
.magnifier {
display: none;
position: absolute;
border: 1px black solid;
box-shadow: 5px 5px 10px #1e1e1e;
border-radius: 50%;
z-index: 5000;
}
const magSize = 300; // diameter of loupe
const magnification = 3; // magnification
let main = elem('main'); // div holding the visible network
let mainRect = main.getBoundingClientRect();
let magnifier = document.createElement('canvas'); // the 'magnifying glass'
magnifier.width = magSize;
magnifier.height = magSize;
magnifier.className = 'magnifier';
let magnifierCtx = magnifier.getContext('2d');
magnifierCtx.fillStyle = 'white';
main.appendChild(magnifier);
let bigNetPane = null;
let bigNetwork = null;
let bigNetCanvas = null;
const magicNumber = 1.92; / the mysterious magic number
// the loupe pops up when the user holds down the SHIFT key and moves the mouse
window.addEventListener('keydown', (e) => {
if (e.shiftKey) createMagnifier();
});
window.addEventListener('mousemove', (e) => {
if (e.shiftKey) showMagnifier(e);
});
window.addEventListener('keyup', (e) => {
if (e.key == 'Shift') closeMagnifier();
});
function createMagnifier() {
if (bigNetPane) {
bigNetwork.destroy();
bigNetPane.remove();
}
// the triple sized version of the netowrk is generated inside the bigNetPane div, which is off screen
bigNetPane = document.createElement('div');
bigNetPane.id = 'big-net-pane';
bigNetPane.style.position = 'absolute';
bigNetPane.style.top = '-9999px';
bigNetPane.style.left = '-9999px';
bigNetPane.style.width = `${netPane.offsetWidth * magnification}px`;
bigNetPane.style.height = `${netPane.offsetHeight * magnification}px`;
main.appendChild(bigNetPane);
bigNetwork = new Network(bigNetPane, data, options);
bigNetCanvas = bigNetPane.firstElementChild.firstElementChild;
bigNetwork.moveTo({
position: network.getViewPosition(),
scale: magnification * network.getScale(),
});
main.style.cursor = 'none';
magnifier.style.display = 'none';
}
function showMagnifier(e) {
e.preventDefault();
if (bigNetCanvas == null) createMagnifier(e);
magnifierCtx.fillRect(0, 0, magSize, magSize);
// this is where the magicNumber is required to line up the enlarged image with where the pointer is
magnifierCtx.drawImage(
bigNetCanvas,
(e.x - mainRect.x) * magicNumber * magnification,
(e.y - mainRect.y) * magicNumber * magnification,
magSize,
magSize,
0,
0,
magSize,
magSize
);
magnifier.style.top = e.clientY - mainRect.y - magSize / 2 + 'px';
magnifier.style.left = e.clientX - mainRect.x - magSize / 2 + 'px';
magnifier.style.display = 'block';
}
function closeMagnifier() {
if (bigNetPane) {
bigNetwork.destroy();
bigNetPane.remove();
}
main.style.cursor = 'default';
magnifier.style.display = 'none';
}
我現在已經開始工作了。 CodePen 演示已經過編輯,現在可以按需要工作。 更正的代碼片段(與問題中的代碼進行比較)是:
const magSize = 300; // diameter of loupe
const magnification = 3; // magnification
const halfMagSize = magSize / 2.0;
let main = elem("mynetwork");
let mainRect = main.getBoundingClientRect();
let magnifier = document.createElement("canvas");
magnifier.width = magSize;
magnifier.height = magSize;
magnifier.className = "magnifier";
let magnifierCtx = magnifier.getContext("2d");
magnifierCtx.fillStyle = "white";
main.appendChild(magnifier);
let bigNetPane = null;
let bigNetwork = null;
let bigNetCanvas = null;
let netPaneCanvas = container.firstElementChild.firstElementChild;
window.addEventListener("keydown", (e) => {
if (e.shiftKey) createMagnifier();
});
window.addEventListener("mousemove", (e) => {
if (e.shiftKey) showMagnifier(e);
});
window.addEventListener("keyup", (e) => {
if (e.key == "Shift") closeMagnifier();
});
function showMagnifier(e) {
e.preventDefault();
if (bigNetCanvas == null) createMagnifier(e);
magnifierCtx.fillRect(0, 0, magSize, magSize);
magnifierCtx.drawImage(
bigNetCanvas,
((e.clientX - mainRect.x) * bigNetCanvas.width) /
netPaneCanvas.clientWidth -
halfMagSize,
((e.clientY - mainRect.y) * bigNetCanvas.height) /
netPaneCanvas.clientHeight -
halfMagSize,
magSize,
magSize,
0,
0,
magSize,
magSize
);
magnifier.style.top = e.clientY - halfMagSize + "px";
magnifier.style.left = e.clientX - halfMagSize + "px";
magnifier.style.display = "block";
}
function createMagnifier() {
if (bigNetPane) {
bigNetwork.destroy();
bigNetPane.remove();
}
network.storePositions();
bigNetPane = document.createElement("div");
bigNetPane.id = "big-net-pane";
bigNetPane.style.position = "absolute";
bigNetPane.style.top = "-9999px";
bigNetPane.style.left = "-9999px";
bigNetPane.style.width = `${main.offsetWidth * magnification}px`;
bigNetPane.style.height = `${main.offsetHeight * magnification}px`;
main.appendChild(bigNetPane);
bigNetwork = new vis.Network(bigNetPane, data, {
physics: { enabled: false }
});
bigNetCanvas = bigNetPane.firstElementChild.firstElementChild;
bigNetwork.moveTo({
position: network.getViewPosition(),
scale: network.getScale() * magnification,
animation: false
});
main.style.cursor = "none";
magnifier.style.display = "none";
}
function closeMagnifier() {
if (bigNetPane) {
bigNetwork.destroy();
bigNetPane.remove();
}
main.style.cursor = "default";
magnifier.style.display = "none";
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.