Project

General

Profile

Actions

Web tech » History » Revision 27

« Previous | Revision 27/29 (diff) | Next »
jun chen, 03/13/2025 09:12 PM


Web tech

How to visualize data:

D3 ref: https://observablehq.com/@d3/gallery , https://johan.github.io/d3/ex/
Plotly ref: https://plotly.com/javascript/


交互功能对比

功能 JavaScript/Plotly Python/Plotly JavaScript/d3
缩放/平移 ✔️ ✔️ ✔️
悬停显示数值 ✔️ ✔️ ✔️
数据点高亮 ✔️ ✔️ ✔️
导出为图片(PNG/JPEG) ✔️ ✔️ ✔️
动态更新数据 ✔️(需额外代码) ✔️
旧firefox支持 ❌(globalthis) ? ✔️

drc 网页显示


<!DOCTYPE html>
<html>
<head>
    <style>
        .category { margin: 20px 0; }
        .thumbnails {
            display: grid;
            grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
            gap: 8px;
        }
        .thumbnail {
            width: 120px;
            height: 90px;
            object-fit: cover;
            cursor: pointer;
            transition: transform 0.2s;
        }
        .thumbnail:hover { transform: scale(1.05); }
        /* 模态框样式 */
        .modal {
            position: fixed;
            top: 0;
            left: 0;
            width: 100vw;
            height: 100vh;
            background: rgba(0,0,0,0.8);
            display: none;
            justify-content: center;
            align-items: center;
        }
        .modal-img {
            max-width: 80%;
            max-height: 80%;
        }
        .close-btn {
            position: absolute;
            top: 20px;
            right: 20px;
            color: white;
            font-size: 30px;
            cursor: pointer;
        }
        .nav-btn {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            color: white;
            font-size: 30px;
            cursor: pointer;
        }
        .prev { left: 20px; }
        .next { right: 20px; }
    </style>
</head>
<body>
    <div id="gallery"></div>
</body>
</html>

// 模拟数据结构
const categories = [
    {
        name: "自然",
        photos: ["nature/1.jpg", "nature/2.jpg", /*...*/]
    },
    // 其他四个分类...
];

// 创建照片墙
const gallery = d3.select("#gallery");

// 创建分类容器
const categoryDivs = gallery.selectAll(".category")
    .data(categories)
    .join("div")
    .attr("class", "category");

// 添加分类标题
categoryDivs.append("h2")
    .text(d => d.name);

// 创建缩略图网格
categoryDivs.each(function(category) {
    const container = d3.select(this);
    
    container.append("div")
        .attr("class", "thumbnails")
        .selectAll(".thumbnail")
        .data(category.photos)
        .join("img")
        .attr("class", "thumbnail")
        .attr("src", d => d) // 根据实际路径调整
        .on("click", function(event, imgPath) {
            showModal(category.photos, imgPath);
        });
});

// 创建模态框
const modal = d3.select("body")
    .append("div")
    .attr("class", "modal");

modal.append("span")
    .attr("class", "close-btn")
    .html("&times;")
    .on("click", hideModal);

const img = modal.append("img")
    .attr("class", "modal-img");

modal.append("div")
    .attr("class", "nav-btn prev")
    .html("&#10094;")
    .on("click", () => navigate(-1));

modal.append("div")
    .attr("class", "nav-btn next")
    .html("&#10095;")
    .on("click", () => navigate(1));

let currentImages = [];
let currentIndex = 0;

// 显示模态框
function showModal(images, selectedImage) {
    currentImages = images;
    currentIndex = images.indexOf(selectedImage);
    img.attr("src", selectedImage);
    modal.style("display", "flex");
}

// 隐藏模态框
function hideModal() {
    modal.style("display", "none");
}

// 图片导航
function navigate(direction) {
    currentIndex = (currentIndex + direction + currentImages.length) % currentImages.length;
    img.attr("src", currentImages[currentIndex]);
}

// 点击外部关闭
window.onclick = function(event) {
    if (event.target === modal.node()) {
        hideModal();
    }
}

// 键盘导航
document.addEventListener("keydown", (e) => {
    if (modal.style("display") === "flex") {
        if (e.key === "ArrowLeft") navigate(-1);
        if (e.key === "ArrowRight") navigate(1);
        if (e.key === "Escape") hideModal();
    }
});

实现在X轴下方添加可缩放和拖动的滑块条:

show code...

交互,圆圈,准心

show code...

button 切换图表

show code...

js d3 内嵌数据显示折线

show code...

JavaScript + Plotly(纯前端实现)

show code...

使用步骤:

  1. 将CSV文件命名为 data.csv,格式如下:
    x,y
    1,5
    2,3
    3,7
    4,2
    5,8
    
  2. 将HTML文件和 data.csv 放在同一目录下,用浏览器打开HTML文件。
  3. 效果:支持缩放、悬停显示数值、拖拽平移等交互。

Python + Plotly(生成独立HTML文件)

特点:适合Python用户,自动化生成图表文件。

show code...

使用步骤:

  1. 安装依赖:
    pip install pandas plotly
    
  2. 运行代码后,生成 interactive_chart.html,用浏览器打开即可看到图表。

进阶方案(可选)

  1. 动态数据加载(JavaScript):

View details...

  • 用户可上传任意CSV文件,实时生成图表。
  1. 添加控件(Python + Dash):
    View details...

    • 运行后访问 http://localhost:8050,支持动态交互和按钮触发操作。

Updated by jun chen 3 months ago · 29 revisions