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();
相关推荐
Cachel wood9 分钟前
python round四舍五入和decimal库精确四舍五入
java·linux·前端·数据库·vue.js·python·前端框架
Jasmine_llq10 分钟前
《 火星人 》
算法·青少年编程·c#
学代码的小前端11 分钟前
0基础学前端-----CSS DAY9
前端·css
joan_8515 分钟前
layui表格templet图片渲染--模板字符串和字符串拼接
前端·javascript·layui
闻缺陷则喜何志丹21 分钟前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
Lenyiin39 分钟前
01.02、判定是否互为字符重排
算法·leetcode
m0_748236111 小时前
Calcite Web 项目常见问题解决方案
开发语言·前端·rust
鸽鸽程序猿1 小时前
【算法】【优选算法】宽搜(BFS)中队列的使用
算法·宽度优先·队列
Jackey_Song_Odd1 小时前
C语言 单向链表反转问题
c语言·数据结构·算法·链表