使用 Panzoom 库防止地图平移上的点击事件

问题描述 投票:0回答:1

我在 .svg 文件中创建了一个用于学习的世界地图,并希望使用 panzoom 库来启用缩放。然而,我遇到了一个似乎无法解决的问题。

我创建了一个简单的游戏,您需要单击正确的国家或岛屿。其中一些非常小,因此需要缩放或平移地图。出现此问题的原因是,通过单击并按住鼠标按钮平移地图时,释放按钮会触发该国家/地区的单击事件,该事件被视为玩家的尝试。

对于如何在平移地图时释放鼠标后防止这种点击,您有什么建议吗?

    // Tooltip
const tooltip = document.getElementById('tooltip');
const svgContainer = document.getElementById('panzoom-container');

// Add hover and tooltip only to selected elements
idsToHighlight.forEach(id => {
    const element = document.getElementById(id);
    if (element) {
        // Add hover
        element.addEventListener('click', (event) => {
            element.classList.add('region-hover');
            const title = element.getAttribute('title') || 'No title';
            tooltip.textContent = title;
            tooltip.style.opacity = '1';
        });

        // Remove hover
        element.addEventListener('mouseleave', () => {
            element.classList.remove('region-hover');
            tooltip.style.opacity = '0';
        });

        // Update tooltip position
        element.addEventListener('mousemove', (event) => {
            const bounds = svgContainer.getBoundingClientRect();
            tooltip.style.left = `${event.clientX - bounds.left + 10}px`;
            tooltip.style.top = `${event.clientY - bounds.top + 10}px`;
        });
    }
});

// Panzoom Initialization with zoom limits
const svgMap = document.getElementById('svg1');
const panzoom = Panzoom(svgMap, { 
    contain: 'outside', 
    minScale: 0.5, // Minimum zoom level
    maxScale: 300    // Maximum zoom level
});
svgContainer.addEventListener('wheel', panzoom.zoomWithWheel);

// Button controls
document.getElementById('zoom-in').addEventListener('click', () => panzoom.zoomIn());
document.getElementById('zoom-out').addEventListener('click', () => panzoom.zoomOut());
document.getElementById('reset').addEventListener('click', () => panzoom.reset());


// Global attempts
const correctAnswers = [];
const incorrectAnswers = [];
const attempts = {};
let numberOfSelectedCountries = 0;

// Function to initialize map interactions
function initMapInteraction() {
    // Initialize number of selected countries
    numberOfSelectedCountries = 1;
    document.getElementById('liczba_wylosowanych_krajow').innerText = `${numberOfSelectedCountries}`;

    // Select random country
    currentTarget = idsToHighlight[Math.floor(Math.random() * idsToHighlight.length)];
    document.getElementById('losowy_kraj').innerText = "Choose country: " + document.getElementById(currentTarget).getAttribute('title'); // Display the selected country

    console.log(`Current target: ${currentTarget}`);

    // Add click listeners for each country
    idsToHighlight.forEach((id) => {
        const element = document.getElementById(id);
        if (element) {
            attempts[id] = 0; // Initialize attempt count

            element.addEventListener("click", () => {
                console.log(`Clicked on country: ${id}`);
                
                if (id === currentTarget) {
                    // Mark correct answer
                    if (attempts[currentTarget] >= 2) {
                        // If there were more than 2 attempts, remove flashing and mark in red
                        element.classList.remove('migajacy');
                        element.style.fill = "red";
                        incorrectAnswers.push(currentTarget);
                        console.log(`Added to incorrect answers: ${currentTarget}`);
                        let incorrectCount = incorrectAnswers.length;
                        document.getElementById('bledne_kraje').innerText = "incorrect: " + incorrectCount;
                    } else if (attempts[currentTarget] === 1) {
                        // On the second attempt
                        element.style.fill = "orange"; // Orange mark
                        incorrectAnswers.push(currentTarget);
                        console.log(`Added to incorrect answers: ${currentTarget}`);
                        let incorrectCount = incorrectAnswers.length;
                        document.getElementById('bledne_kraje').innerText = "incorrect: " + incorrectCount;
                    } else {
                        // On the first attempt
                        element.style.fill = "white"; // White mark
                        correctAnswers.push(currentTarget);
                        console.log(`Added to correct answers: ${currentTarget}`);
                        let correctCount = correctAnswers.length;
                        document.getElementById('Poprawne_kraje').innerText = "Correct: " + correctCount;
                    }
                    element.style.pointerEvents = "none"; // Disable clicks
                    correctAnswers.push(currentTarget);
                    console.log(`Country ${id} marked as correct.`);

                    numberOfSelectedCountries++; // Increase selected countries count
                    document.getElementById('liczba_wylosowanych_krajow').innerText = `${numberOfSelectedCountries}`;

                    // Check if there are still countries to choose
                    const remaining = idsToHighlight.filter(
                        (country) => !correctAnswers.includes(country) && !incorrectAnswers.includes(country)
                    );
                    if (remaining.length > 0) {
                        currentTarget = remaining[Math.floor(Math.random() * remaining.length)];
                        document.getElementById('losowy_kraj').innerText = document.getElementById(currentTarget).getAttribute('title'); // Update the selected country
                        attempts[currentTarget] = 0; // Reset attempts for new country
                    } else {
                        console.log("Game finished. All countries marked correctly.");
                        alert("All countries have been marked correctly!");
                    }
                } else {
                    // Handle incorrect selection
                    attempts[currentTarget]++; // Increase attempts globally
                    console.log(`Attempts for ${currentTarget}: ${attempts[currentTarget]}`);

                    if (attempts[currentTarget] === 2) {
                        // After 2 attempts, add flashing
                        document.getElementById(currentTarget).classList.add('migajacy');
                    }
                }
            });
        } else {
            console.error(`Element with id ${id} does not exist.`);
        }
    });
}

// CSS for flashing effect
const style = document.createElement('style');
style.textContent = `
@keyframes blink-red {
    0%, 100% { fill: red; }
    50% { fill: white; }
}

.migajacy {
    animation: blink-red 1s infinite;
}
`;
document.head.appendChild(style);

// Initialize interactions after DOM is loaded
window.addEventListener("DOMContentLoaded", initMapInteraction);

const occurrences = [];
function checkIdOccurrences() {
    const allElements = document.querySelectorAll('[id]');
    const idCounts = {};
    
    allElements.forEach((element) => {
        const id = element.id.toUpperCase(); // Use uppercase for consistency
        if (idsToHighlight.includes(id)) {
            if (idCounts[id]) {
                idCounts[id]++;
            } else {
                idCounts[id] = 1;
            }
        }
    });

    // Find the div with id `wszystkie_kraje`
    const allCountriesDiv = document.getElementById('wszystkie_kraje');
    
    if (allCountriesDiv) {
        allCountriesDiv.innerHTML = `${Object.keys(idCounts).length} `;
    } 
}

// Call the function after DOM is loaded
document.addEventListener('DOMContentLoaded', () => {
    checkIdOccurrences();
});
javascript svg panzoom
1个回答
0
投票

您可以“设置计时器”。如果 mousedown 和 mouseup 事件的时间戳之间的差异大于 x,则停止单击事件。

let mouseevents = {};

document.addEventListener('mousedown', e => {
  mouseevents.down = e.timeStamp;
  console.log('mousedown', e.timeStamp);
});

document.addEventListener('mouseup', e => {
  mouseevents.up = e.timeStamp;
  console.log('mouseup', e.timeStamp);
});

document.addEventListener('click', e => {
  let diff = mouseevents.up - mouseevents.down;
  if (diff > 250) {
    e.stopImmediatePropagation();
  }
  mouseevents = {};
});

// the "real" click event callback
document.addEventListener('click', e => {
  console.log('click', e.timeStamp);
});
<p>Click somewhere</p>

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.