当前位置: 首页 > article >正文

json绘制热力图

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

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

实现代码如下:

    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();


http://www.kler.cn/a/388126.html

相关文章:

  • Docker入门系列——Docker-Compose
  • 【MATLAB代码】二维平面上的TDOA,使用加权最小二乘法,不限制锚点数量,代码可复制粘贴
  • 河南省的一级科技查新机构有哪些?
  • 通过脚本,发起分支合并请求和打tag
  • Android Profiler 内存分析
  • Elasticsearch中什么是倒排索引?
  • 大数据面试题--kafka夺命连环问
  • Unity——对RectTransform进行操作
  • gitlab无法创建合并请求是所有分支都不显示
  • 从特殊角度解释深度学习,一节课让你彻底明白深度学习的“前世今生”!
  • MySQL 和 PostgreSQL 的使用案例
  • docker中widows安装mysql
  • vuepress配置谷歌广告-通过vue-google-adsense库
  • 外包干了5年,技术退步太明显了。。。。。
  • MongoDB——服务端连接及查询
  • 【2048】我的创作纪念日
  • 保研考研机试攻略:python笔记(3)
  • Flutter鸿蒙next 实现长按录音按钮及动画特效
  • 链表知识汇总
  • 手机的ip地址是固定的吗?多角度深入探讨
  • 【Linux】Linux入门实操——vim、目录结构、远程登录、重启注销
  • 第9章 Apache WEB服务器企业实战
  • ChatGPT 新体验:AI 搜索功能与订阅支付指南
  • 加固筑牢安全防线:多源威胁检测响应在企业网络安全运营中的核心作用
  • leetcode 832.翻转图像
  • Vue Router 详细使用步骤:如何在 Vue 项目中配置 Vue Router