JavaScript 代码优化:根据图片加载状态动态调整 Tooltip 位置
JavaScript 代码优化:根据图片加载状态动态调整 Tooltip 位置
在使用 JavaScript 创建 Tooltip 时,如果 Tooltip 中包含图片,并且图片的加载状态会影响 Tooltip 的位置,那么就需要根据图片加载状态来动态调整 Tooltip 的位置。
例如,在以下代码中,当 label 元素包含  data-img 属性时,Tooltip 会根据图片的高度来调整其位置,如果图片加载失败,Tooltip 的位置就会出现问题:
let selectedLabel = null;
let currentTooltip = null;
let tooltipTimer = null;
labels.forEach((label) => {
    label.addEventListener("mouseover", (e) => {
        if (currentTooltip) {
            document.querySelector(".category-options-wrapper").removeChild(currentTooltip);
            clearTimeout(tooltipTimer);
        }
        const tooltip = document.createElement("div");
        tooltip.classList.add("tooltip");
        tooltip.innerHTML = label.getAttribute("data-title");
        tooltip.style.position = "absolute";
        const imgSrc = label.getAttribute("data-img");
        if (imgSrc) {
            const img = new Image();
            img.src = imgSrc;
            img.onload = function() {
                tooltip.appendChild(document.createElement('br'));
                tooltip.appendChild(img);
                if (img.width > 150 || img.height > 150) {
                    tooltip.style.position = "fixed";
                    tooltip.style.right = "10px";
                    tooltip.style.top = "10px";
                    tooltip.style.minWidth = "300px";
                } else {
                    tooltip.style.top = e.pageY - 30 + "px";
                }
                if (tooltip.querySelector('img')) {
                    tooltip.style.top = parseInt(tooltip.style.top) - tooltip.querySelector('img').height + "px";
                }
            };
            img.onerror = function() {
                console.log("Error: Failed to load image '" + imgSrc + "'");
                tooltip.style.top = e.pageY - 30 + "px";
            };
        }
        tooltip.style.maxWidth = "300px";
        document.querySelector(".category-options-wrapper").appendChild(tooltip);
        const tooltipWidth = tooltip.offsetWidth;
        const tooltipHeight = tooltip.offsetHeight;
        const mouseX = e.clientX;
        const mouseY = e.clientY;
        const wrapperRect = document.querySelector(".category-options-wrapper").getBoundingClientRect();
        let left = mouseX - wrapperRect.left + 10;
        let top = mouseY - wrapperRect.top - tooltipHeight -10;
        if (!imgSrc || !tooltip.querySelector('img')) {
            left = e.pageX + 10;
            top = e.pageY - 30;
        } else if (left + tooltipWidth > wrapperRect.left + wrapperRect.width) {
            // tooltip 超出右侧边界
            left = wrapperRect.left + wrapperRect.width - tooltipWidth;
        }
        tooltip.style.left = left + "px";
        tooltip.style.top = top + "px";
        tooltip.addEventListener("mousemove", () => {
            clearTimeout(tooltipTimer);
        });
        tooltip.addEventListener("mouseout", () => {
            tooltipTimer = setTimeout(() => {
                document.querySelector(".category-options-wrapper").removeChild(tooltip);
                currentTooltip = null;
                // 如果该 label 元素是当前选中的元素,则不还原其背景颜色
                if (label == selectedLabel) {
                    label.style.backgroundColor = "";
                }
            }, 5000);
        });
        currentTooltip = tooltip;
        // 如果当前已有选中的 label 元素,则将其背景颜色还原
        if (selectedLabel && label !== selectedLabel) {
            selectedLabel.style.backgroundColor = "";
        }
        // 将当前 label 元素设置为选中,并将其背景颜色设置为 '#40b40d'
        selectedLabel = label;
        selectedLabel.style.backgroundColor = "rgba(64, 180, 13, 0.6)";
    });
    label.addEventListener("mouseleave", () => {
        if (currentTooltip) {
            tooltipTimer = setTimeout(() => {
                document.querySelector(".category-options-wrapper").removeChild(currentTooltip);
                currentTooltip = null;
                // 如果该 label 元素是当前选中的元素,则不还原其背景颜色
                if (label == selectedLabel) {
                    label.style.backgroundColor = "";
                }
            }, 2000);
        }
    });
});
为了解决这个问题,可以将判断图片是否存在的逻辑放在图片加载完成后的回调函数中,然后根据图片是否存在来决定是否要减去图片高度。修改后的代码如下:
let selectedLabel = null;
let currentTooltip = null;
let tooltipTimer = null;
labels.forEach((label) => {
    label.addEventListener("mouseover", (e) => {
        if (currentTooltip) {
            document.querySelector(".category-options-wrapper").removeChild(currentTooltip);
            clearTimeout(tooltipTimer);
        }
        const tooltip = document.createElement("div");
        tooltip.classList.add("tooltip");
        tooltip.innerHTML = label.getAttribute("data-title");
        tooltip.style.position = "absolute";
        const imgSrc = label.getAttribute("data-img");
        if (imgSrc) {
            const img = new Image();
            img.src = imgSrc;
            img.onload = function() {
                tooltip.appendChild(document.createElement('br'));
                tooltip.appendChild(img);
                if (img.width > 150 || img.height > 150) {
                    tooltip.style.position = "fixed";
                    tooltip.style.right = "10px";
                    tooltip.style.top = "10px";
                    tooltip.style.minWidth = "300px";
                } else {
                    tooltip.style.top = e.pageY - 30 + "px";
                }
                if (tooltip.querySelector('img')) {
                    tooltip.style.top = parseInt(tooltip.style.top) - tooltip.querySelector('img').height + "px";
                }
            };
            img.onerror = function() {
                console.log("Error: Failed to load image '" + imgSrc + "'");
                tooltip.style.top = e.pageY - 30 + "px";
            };
        }
        tooltip.style.maxWidth = "300px";
        document.querySelector(".category-options-wrapper").appendChild(tooltip);
        const tooltipWidth = tooltip.offsetWidth;
        const tooltipHeight = tooltip.offsetHeight;
        const mouseX = e.clientX;
        const mouseY = e.clientY;
        const wrapperRect = document.querySelector(".category-options-wrapper").getBoundingClientRect();
        let left = mouseX - wrapperRect.left + 10;
        let top = mouseY - wrapperRect.top - tooltipHeight -10;
        if (!imgSrc || !tooltip.querySelector('img')) {
            left = e.pageX + 10;
            top = e.pageY - 30;
        } else if (left + tooltipWidth > wrapperRect.left + wrapperRect.width) {
            // tooltip 超出右侧边界
            left = wrapperRect.left + wrapperRect.width - tooltipWidth;
        }
        tooltip.style.left = left + "px";
        tooltip.style.top = top + "px";
        tooltip.addEventListener("mousemove", () => {
            clearTimeout(tooltipTimer);
        });
        tooltip.addEventListener("mouseout", () => {
            tooltipTimer = setTimeout(() => {
                document.querySelector(".category-options-wrapper").removeChild(tooltip);
                currentTooltip = null;
                // 如果该 label 元素是当前选中的元素,则不还原其背景颜色
                if (label == selectedLabel) {
                    label.style.backgroundColor = "";
                }
            }, 5000);
        });
        currentTooltip = tooltip;
        // 如果当前已有选中的 label 元素,则将其背景颜色还原
        if (selectedLabel && label !== selectedLabel) {
            selectedLabel.style.backgroundColor = "";
        }
        // 将当前 label 元素设置为选中,并将其背景颜色设置为 '#40b40d'
        selectedLabel = label;
        selectedLabel.style.backgroundColor = "rgba(64, 180, 13, 0.6)";
    });
    label.addEventListener("mouseleave", () => {
        if (currentTooltip) {
            tooltipTimer = setTimeout(() => {
                document.querySelector(".category-options-wrapper").removeChild(currentTooltip);
                currentTooltip = null;
                // 如果该 label 元素是当前选中的元素,则不还原其背景颜色
                if (label == selectedLabel) {
                    label.style.backgroundColor = "";
                }
            }, 2000);
        }
    });
});
通过这种方式,就可以确保 Tooltip 的位置与图片加载状态保持一致,从而避免出现位置不协调的问题。
总结
在使用 JavaScript 创建 Tooltip 时,如果 Tooltip 中包含图片,并且图片的加载状态会影响 Tooltip 的位置,那么就需要根据图片加载状态来动态调整 Tooltip 的位置。将判断图片是否存在的逻辑放在图片加载完成后的回调函数中,然后根据图片是否存在来决定是否要减去图片高度,可以有效地解决这个问题。
 
原文地址: https://www.cveoy.top/t/topic/oiAA 著作权归作者所有。请勿转载和采集!