json绘制热力图

首先需要一段热力信息的json,我放在头部了。

然后就是需要de-geo库了。

实现代码如下:

javascript 复制代码
    import * as d3geo from 'd3-geo'
    import trafficJSON from '../assets/json/traffic.json'

    let geoFun;// 地理投影函数
    // 
    let info = {
        max: Number.MIN_SAFE_INTEGER,
        min: Number.MAX_SAFE_INTEGER,
        maxlng: Number.MIN_SAFE_INTEGER,
        minlng: Number.MAX_SAFE_INTEGER,
        maxlat: Number.MIN_SAFE_INTEGER,
        minlat: Number.MAX_SAFE_INTEGER,
        data: []
    };

    // 初始化地理投影
    const initGeo = (size) => {
        geoFun = d3geo.geoMercator().scale(size || 100)
    }

    // 经纬度转像素坐标
    const latlng2px = (pos) => {
        if (pos[0] >= -180 && pos[0] <= 180 && pos[1] >= -90 && pos[1] <= 90) {
            return geoFun(pos);
        }
        return pos;
    };

    // 创建颜色
    const createColors = (option) => {
        const canvas = document.createElement('canvas');
        document.body.appendChild(canvas);
        const ctx = canvas.getContext('2d');
        canvas.width = 256;
        canvas.height = 1;
        const grad = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
        for (let k in option.colors) {
            grad.addColorStop(k, option.colors[k]);
        }
        ctx.fillStyle = grad;
        ctx.fillRect(0, 0, canvas.width, canvas.height);
        return ctx.getImageData(0, 0, canvas.width, 1).data;
    }

    // 绘制圆
    const drawCircle = (ctx, option, item) => {
        let { lng, lat, value } = item;
        let x = lng - option.minlng + option.radius;
        let y = lat - option.minlat + option.radius;
        const grad = ctx.createRadialGradient(x, y, 0, x, y, option.radius);
        grad.addColorStop(0.0, 'rgba(0,0,0,1)');
        grad.addColorStop(1.0, 'rgba(0,0,0,0)');
        ctx.fillStyle = grad;
        ctx.beginPath();
        ctx.arc(x, y, option.radius, 0, 2 * Math.PI);
        ctx.closePath();
        ctx.globalAlpha = (value - option.min) / option.size;
        ctx.fill();
    }

    // 创建热力图
    const createHeatmap = (option) => {
        const canvas = document.createElement('canvas');
        document.body.appendChild(canvas);
        canvas.width = option.width;
        canvas.height = option.height;
        const ctx = canvas.getContext('2d');
        option.size = option.max - option.min;
        option.data.forEach((item) => {
            drawCircle(ctx, option, item);
        });
        const colorData = createColors(option);
        const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
        for (let i = 3; i < imageData.data.length; i = i + 4) {
            let opacity = imageData.data[i];
            let offset = opacity * 4;
            //red
            imageData.data[i - 3] = colorData[offset];
            //green
            imageData.data[i - 2] = colorData[offset + 1];
            //blue
            imageData.data[i - 1] = colorData[offset + 2];
        }
        ctx.putImageData(imageData, 0, 0);
    }

    // 初始化
    const init = () => {
        initGeo(1000)
        // 处理数据
        trafficJSON.features.forEach((item) => {
            let pos = latlng2px(item.geometry.coordinates);// 经纬度转像素坐标
            let newitem = {
                lng: pos[0],
                lat: pos[1],
                value: item.properties.avg
            }
            info.max = Math.max(newitem.value, info.max);
            info.maxlng = Math.max(newitem.lng, info.maxlng);
            info.maxlat = Math.max(newitem.lat, info.maxlat);
            info.min = Math.min(newitem.value, info.min);
            info.minlng = Math.min(newitem.lng, info.minlng);
            info.minlat = Math.min(newitem.lat, info.minlat);
            info.data.push(newitem);
        })
        info.size = info.max - info.min;
        info.sizelng = info.maxlng - info.minlng;
        info.sizelat = info.maxlat - info.minlat;
        const radius = 50;
        createHeatmap({
            width: info.sizelng + radius * 2,
            height: info.sizelng + radius * 2,
            colors: {
                0.1: '#2A85B8',
                0.2: '#16B0A9',
                0.3: '#29CF6F',
                0.4: '#5CE182',
                0.5: '#7DF675',
                0.6: '#FFF100',
                0.7: '#FAA53F',
                1: '#D04343'
            },
            radius,
            ...info
        })
    }
    init();
相关推荐
YUDAMENGNIUBI1 小时前
day20_逻辑回归
算法·机器学习·逻辑回归
KaMeidebaby4 小时前
卡梅德生物技术快报|骆驼纳米抗体:从原核表达、高通量测序到分子对接全流程实现
前端·数据库·其他·百度·新浪微博
澈2075 小时前
C++并查集:高效解决连通性问题
java·c++·算法
子兮曰6 小时前
Node.js v26.1.0 深度解读:FFI、后量子密码与调试器的进化
前端·后端·node.js
测试员周周6 小时前
【Appium 系列】第06节-页面对象实现 — LoginPage 实战
开发语言·前端·人工智能·python·功能测试·appium·测试用例
旖-旎6 小时前
深搜练习(单词搜索)(12)
c++·算法·深度优先·力扣
企客宝CRM7 小时前
2026年中小企业CRM选型指南:企客宝CRM处于什么位置?
android·算法·企业微信·rxjava·crm
西洼工作室7 小时前
前端直传OSS服务端签名(Policy+Signature)/STS临时凭证
前端·文件上传·oss
橙淮7 小时前
二叉树核心概念与Java实现详解
数据结构·算法
米罗篮8 小时前
DSU并查集 & 拓展欧几里得-逆元
c++·经验分享·笔记·算法·青少年编程