Echarts实现高亮某一个点

背景

接口会返回所有点的数据,以及最优点的数据。产品要求在绘制图形后,高亮最优点,添加一个红色的样式,如图。点击select选择器时,可选择不同指标和花费对应的关系。

以下介绍实现思路

1、自定义配置选择器的数据源,默认选中roi。
chartParams: 'roi',
chartOption: [
    {
        label: 'ROI、边际ROI和花费的关系',
        value: 'roi',
        otherValue: 'incre_roi',
        name1: 'ROI',
        name2: '边际ROI',
    },
    {
        label: '点击价值、边际点击价值和花费的关系',
        value: 'vpc',
        otherValue: 'incre_vpc',
        name1: '点击价值',name2: '边际点击价值',
    },
    {
        label: '加购成本、边际加购成本和花费的关系',
        value: 'cpca',
        otherValue: 'incre_cpca',
        name1: '加购成本',
        name2: '边际加购成本',
    },
],
<el-select v-model="chartParams" @change="handleAnalysis">
    <el-option v-for="item in chartOption"
        :key="item.value"
        :value="item.value"
        :label="item.label"></el-option>
</el-select>
2、绘制echarts
  • 引入
import * as echarts from 'echarts';
  • 设置宽高
<div ref="myChart1" style="width: 50%; height: 280px"></div>
  • 在data中,定义一个myChart1的变量用来保存eCharts实例,echarts的基础配置

其中:formatNum方法为公共方法,功能:数字增加千分位,如果有小数点保留2位小数。文章末尾有提供

tooltip对象中的formatter函数,当鼠标悬浮时,标记点(即最优点)不展示悬浮数据,其他点展示固定的指标数据

myChart1: '',
echartsData1: {
    legend: {
        data: ['ROI','边际ROI'],
        selectedMode: false, // 是否允许点击
    },
    grid: {
        show: false,
        top: '40px', // 一下数值可为百分比也可为具体像素值
        right: '50px',
        bottom: '40px',
        left: '40px',
    },
    xAxis: {
        type: 'category',
        boundaryGap: false,
        splitLine: {
            show: true,
            lineStyle: {
                type: 'dashed',
                color: '#eee', // 左边线的颜色
                width: '1', // 坐标线的宽度
            },
        },
        data: [1,2,3,4,5,6,7,8,9,10],
        axisLine: {
            show: true,
            lineStyle: {
                type: 'solid',
                color: '#ccc', // 左边线的颜色
                width: '1', // 坐标线的宽度
            },
        },
        axisLabel: {
            interale: 0,
            rotate: 45, //防止x轴坐标数据过大放不下,倾斜45°
            color: '#aaa', // 坐标轴label颜色
            formatter: (value) => {
                return formatNum(value)
            }
        },
    },
    yAxis: [
        {
            type: 'value',
            name: 'ROI',
            splitLine: {
                show: true,
                lineStyle: {
                    type: 'dashed',
                    color: '#eee', // 左边线的颜色
                    width: '1', // 坐标线的宽度
                },
            },
            axisLine: {
                show: true,
                lineStyle: {
                    type: 'solid',
                    color: '#ccc', // 左边线的颜色
                    width: '1', // 坐标线的宽度
                },
            },
            axisLabel: {
                formatter: '{value}',
                color: '#aaa',
            },
        },
        {
            type: 'value',
            name: '边际ROI',
            splitLine: {
                show: true,
                lineStyle: {
                    type: 'dashed',
                    color: '#eee', // 左边线的颜色
                    width: '1', // 坐标线的宽度
                },
            },
            axisLine: {
                show: true,
                lineStyle: {
                    type: 'solid',
                    color: '#ccc', // 左边线的颜色
                    width: '1', // 坐标线的宽度
                },
            },
            axisLabel: {
                formatter: '{value}',
                color: '#aaa',
            },
        },
    ],
    tooltip: {
        trigger: 'item', // 设置触发类型为坐标轴
        axisPointer: {
            type: 'cross',
            crossStyle: {
                color: '#999',
            },
        },
        formatter: (value) => {
            if(value.componentType === "markPoint") return
            let str= ``
            let color = value.color
            let color2 = "#91cc75"
            str += `<p style="line-height: 26px;color: ${color}">花费:${formatNum(Math.trunc(value.data['budget']))}</p>`
            str += `<p style="line-height: 26px;color: ${color}">GMV:${formatNum(Math.trunc(value.data['pred_gmv']))}</p>`
            str += `<p style="line-height: 26px">
                <span style="display: inline-block; width: 110px;color: ${color}">ROI: ${value.data['roi']}</span> 
                <span style="display: inline-block; min-width: 150px;color: ${color2};">边际ROI: ${value.data['incre_roi']}</span></p>`
            str += `<p style="line-height: 26px">
                <span style="display: inline-block; width: 110px;color: ${color}">点击价值: ${value.data['vpc']}</span> 
                <span style="display: inline-block; min-width: 150px;color:${color2};">边际点击价值: ${value.data['incre_vpc']}</span></p>`
            str += `<p style="line-height: 26px">
                <span style="display: inline-block; width: 110px;color: ${color}">加购成本: ${value.data['cpca']}</span> 
                <span style="display: inline-block; min-width: 150px;color:${color2};">边际加购成本: ${value.data['incre_cpca']}</span></p>`
            return str                  
        }
    },
    series: [
        {
            name: 'ROI',
            data: [12, 25, 45, 35, 55],
            yAxisIndex: 0, // 使用第1个Y轴
            type: 'line',
            smooth: true,
            lineStyle: {
                color: '#5470c6',
                type: 'solid',
            },
            symbol:'circle', 
            showSymbol: true,
            symbolSize: 6,
            markPoint: { //给第一条y轴添加标记点
                data: [{ 
                    value: 'best', 
                    xAxis: 1, 
                    yAxis: 2.68,
                    itemStyle: {
                        color: 'red' //颜色设置为红色
                    },
                }]
            },
        },
        {
            name: '边际ROI',
            data: [1, 2, 44, 35, 155],
            yAxisIndex: 1, // 使用第2个Y轴
            type: 'line',
            smooth: true,
            lineStyle: {
                color: '#5470c6',
                type: 'dashed'  // 这里设置线的类型为'dashed',即虚线
            },
        }
    ],
},
  • 初始化echarts,绑定点击事件(通过样式来实现高亮)
this.$nextTick(()=> {
    this.myChart1 = echarts.init(this.$refs['myChart1'])
    this.myChart1.setOption(this.echartsData1)
    this.myChart1.on('click', (event) => {
        this.echartClick(event)
    })
})
//切换最优点
echartClick(event) {
    this.bestSpotInfo = event.data
    this.handleSetHighLight(event.dataIndex)
},
//设置高亮事件
handleSetHighLight(idx) {
    this.echartsData1.series[0].data.map((item,index) => {
        item.itemStyle.color = index===idx? 'red' : '#5470c6'
        item.symbolSize = index===idx? 11 : 6
    })
    this.myChart1.setOption(this.echartsData1)
},
  • 获取数据后处理数据
//处理三个关系的折线图
handleAnalysis() {
    let tempObj = this.chartOption.find(item=>item.value==this.chartParams)
    this.echartsData1.xAxis.data = this.allSpotInfo.map(item => item.budget)
    this.echartsData1.legend.data = [tempObj.name1, tempObj.name2]
    this.echartsData1.yAxis[0].name = tempObj.name1
    this.echartsData1.yAxis[1].name = tempObj.name2
    this.echartsData1.series[0].name = tempObj.name1
    this.echartsData1.series[1].name = tempObj.name2

    //寻找最优点的坐标 设置默认高亮
    let bestIndex = this.allSpotInfo.findIndex(item => item.budget == this.bestSpotInfo.budget)
    this.echartsData1.series[0].markPoint.data[0].xAxis = bestIndex
    this.echartsData1.series[0].markPoint.data[0].yAxis = this.bestSpotInfo[tempObj.value]
    this.echartsData1.series[0].data = this.allSpotInfo.map((item,index) => {
        return {
            value: item[tempObj.value],
            ...item,
            itemStyle: {
                color: '#5470c6'
            },
            symbolSize: 6
        }
    })
    this.echartsData1.series[1].data = this.allSpotInfo.map(item => {
        return {
            value: item[tempObj.otherValue],
            ...item,
        }
    })
    this.handleSetHighLight(bestIndex)
    if(this.myChart1) {
        this.myChart1.setOption(this.echartsData1)
    }
},
4、监听eCharts的宽度变化,实现页面宽度自适应
mounted() {
    window.addEventListener('resize', () => {
        if (this.$refs['myChart1']) {
            this.myChart1.resize();
        }
    })
},

/* 页面组件销毁的时候,别忘了移除绑定的监听resize事件,否则的话,多渲染几次,容易导致内存泄漏和额外CPU或GPU占用哦 */
beforeDestroy () {
    window.removeEventListener('resize', () => {
        this.myChart1.resize()
    })
},

最后贴上

// 数字增加千分位,如果有小数点保留2位小数
function formatNum(str) {
  if (str === 0) {
    return 0;
  }
  if (str === null || str === undefined || str === "--") {
    return "- -";
  }
  var newStr = "";
  var count = 0;
  str = str.toString();
  str = str.replace(/,/g, "");
  if (str.indexOf(".") === -1) {
    for (var i = str.length - 1; i >= 0; i--) {
      if (count % 3 === 0 && count !== 0) {
        newStr = str.charAt(i) + "," + newStr;
      } else {
        newStr = str.charAt(i) + newStr;
      }
      count++;
    }
    str = newStr;
    return str;
  } else {
    for (var j = str.indexOf(".") - 1; j >= 0; j--) {
      if (count % 3 === 0 && count !== 0) {
        newStr = str.charAt(j) + "," + newStr;
      } else {
        newStr = str.charAt(j) + newStr;
      }
      count++;
    }
    str = newStr + (str + "00").substr((str + "00").indexOf("."), 3);
    return str;
  }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/508694.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

稀碎从零算法笔记Day36-LeetCode:H指数

有点绕的一个题&#xff0c;题目描述的有点奇怪&#xff08;可以看下英文&#xff1f;&#xff09; 题型&#xff1a;数组、模拟 链接&#xff1a;274. H 指数 - 力扣&#xff08;LeetCode&#xff09; 来源&#xff1a;LeetCode 题目描述 给你一个整数数组 citations &am…

ArcGIS Pro怎么进行挖填方计算

在工程实施之前&#xff0c;我们需要充分利用地形&#xff0c;结合实际因素&#xff0c;通过挖填方计算项目的标高&#xff0c;以达到合理控制成本的目的&#xff0c;这里为大家介绍一下ArcGIS Pro中挖填方计算的方法&#xff0c;希望能对你有所帮助。 数据来源 教程所使用的…

Android仿高德首页三段式滑动

最近发现很多app都使用了三段式滑动&#xff0c;比如说高德的首页和某宝等物流信息都是使用的三段式滑动方式&#xff0c;谷歌其实给了我们很好的2段式滑动&#xff0c;就是BottomSheet&#xff0c;所以这次我也是在这个原理基础上做了一个小小的修改来实现我们今天想要的效果。…

13.5k star, 免费开源 Markdown 编辑器

13.5k star, 免费开源 Markdown 编辑器 分类 开源分享 项目名: Editor.md -- Markdown 编辑器 Github 开源地址&#xff1a; https://github.com/pandao/editor.md 在线测试地址&#xff1a; Editor.md - 开源在线 Markdown 编辑器 完整实例&#xff1a; HTML Preview(mark…

LLaMA-Factory微调(sft)ChatGLM3-6B保姆教程

LLaMA-Factory微调&#xff08;sft&#xff09;ChatGLM3-6B保姆教程 准备 1、下载 下载LLaMA-Factory下载ChatGLM3-6B下载ChatGLM3windows下载CUDA ToolKit 12.1 &#xff08;本人是在windows进行训练的&#xff0c;显卡GTX 1660 Ti&#xff09; CUDA安装完毕后&#xff0c…

iPhone设备中查看应用程序崩溃日志的最佳实践与经验分享

​ 目录 如何在iPhone设备中查看崩溃日志 摘要 引言 导致iPhone设备崩溃的主要原因是什么&#xff1f; 使用克魔助手查看iPhone设备中的崩溃日志 奔溃日志分析 总结 摘要 本文介绍了如何在iPhone设备中查看崩溃日志&#xff0c;以便调查崩溃的原因。我们将展示三种不同的…

RT-Thread 学习二:基于 RT Thread studio (联合cubemx)的stm32l475VETX pwm 呼吸灯实验

1、基于芯片创建呼吸灯项目 基于rtthread studio 可以帮助我们创建好底层驱动&#xff0c;我们只需要做简单配置 2、配置pwm 设备 基于芯片生成的项目默认只打开了 uart 和 pin的驱动&#xff0c;对于其它硬件驱动需要自行配置&#xff1b; 对于pwm和设备的驱动分为四步&am…

深入理解数据结构——堆

前言&#xff1a; 在前面我们已经学习了数据结构的基础操作&#xff1a;顺序表和链表及其相关内容&#xff0c;今天我们来学一点有些难度的知识——数据结构中的二叉树&#xff0c;今天我们先来学习二叉树中堆的知识&#xff0c;这部分内容还是非常有意思的&#xff0c;下面我们…

将 Elasticsearch 向量数据库引入到数据上的 Azure OpenAI 服务(预览)

作者&#xff1a;来自 Elastic Aditya Tripathi Microsoft 和 Elastic 很高兴地宣布&#xff0c;全球下载次数最多的向量数据库 Elasticsearch 是公共预览版中 Azure OpenAI Service On Your Data 官方支持的向量存储和检索增强搜索技术。 这项突破性的功能使你能够利用 GPT-4 …

LeetCode-240. 搜索二维矩阵 II【数组 二分查找 分治 矩阵】

LeetCode-240. 搜索二维矩阵 II【数组 二分查找 分治 矩阵】 题目描述&#xff1a;解题思路一&#xff1a;从左下角或者右上角元素出发&#xff0c;来寻找target。解题思路二&#xff1a;右上角元素&#xff0c;代码解题思路三&#xff1a;暴力也能过解题思路四&#xff1a;二分…

HDLbits 刷题 -- Alwaysblock2

学习&#xff1a; For hardware synthesis, there are two types of always blocks that are relevant: Combinational: always (*)Clocked: always (posedge clk) Clocked always blocks create a blob of combinational logic just like combinational always blocks, but…

蓝桥杯真题:成绩统计

这题思路简单&#xff0c;但是输出结果的位置容易出错&#xff0c;题目要求四舍五入&#xff0c;所以要用Math.round&#xff08;&#xff09;的方法

【MySQL】DCL-数据控制语言-【管理用户&权限控制】 (语法语句&案例演示&可cv案例代码)

前言 大家好吖&#xff0c;欢迎来到 YY 滴MySQL系列 &#xff0c;热烈欢迎&#xff01; 本章主要内容面向接触过C Linux的老铁 主要内容含&#xff1a; 欢迎订阅 YY滴C专栏&#xff01;更多干货持续更新&#xff01;以下是传送门&#xff01; YY的《C》专栏YY的《C11》专栏YY的…

3、jvm基础知识(三)

如何判断堆上的对象没有被引用&#xff1f; 常见的有两种判断方法&#xff1a;引用计数法和可达性分析法。 引用计数法会为每个对象维护一个引用计数器&#xff0c;当对象被引用时加1&#xff0c;取消引用时减1。 引用计数法的优点是实现简单&#xff0c;缺点有两点&#xff1…

软件工程知识体系 Chapter3 软件构造

介绍 软件构造一词指的是通过编码、验证、单元测试、集成测试和调试等组合详细创建工作软件的过程。 软件构建知识领域&#xff08;KA&#xff09;与所有其他KA都有关联&#xff0c;但它与软件设计和软件测试的关联最为紧密&#xff0c;因为软件构建过程涉及重要的软件设计和…

Kubernetes(K8s)技术解析

1. K8s简介 Kubernetes&#xff08;简称K8s&#xff09;是一个开源的容器编排平台&#xff0c;旨在简化容器化应用程序的部署、扩展和管理。为开发者和运维人员提供了丰富的功能和灵活的解决方案&#xff0c;帮助他们更轻松地构建、部署和管理云原生应用程序。以下是关于Kubern…

vscode批量编辑行头行尾

ctrlf查找那儿将最后的星星选中即为正则表达式模式 ^ 表示行头$ 表示行尾 例如&#xff0c;在行首添加大括号{ &#xff1a; vsCode中可以使用正则表达式模式找到换行。指定字符替换成换行&#xff0c;在替换字符串里将换行用\n表示就可以了。 查找换行符也是在查找那儿使用\…

RabbitMQ Tutorial

参考API : Overview (RabbitMQ Java Client 5.20.0 API) 参考文档: RabbitMQ: One broker to queue them all | RabbitMQ 目录 结构 Hello World consumer producer 创建连接API解析 创建连接工厂 生产者生产消息 消费者消费消息 队列声明 工作队列Work Queues 公平…

【QT+QGIS跨平台编译】056:【pdal_arbiter+Qt跨平台编译】(一套代码、一套框架,跨平台编译)

点击查看专栏目录 文章目录 一、pdal_arbiter介绍二、pdal下载三、文件分析四、pro文件五、编译实践一、pdal_arbiter介绍 pdal_arbiter是 PDAL 项目的一个库,用于帮助管理应用程序运行在 EC2 实例上的 AWS 凭证。 当应用程序需要调用 AWS API 时,它们必须使用 AWS 凭据对 AP…

Dapr(一) 基于云原生了解Dapr

(这期先了解Dapr&#xff0c;之后在推出如何搭建Dapr&#xff0c;以及如何使用。) 目录 引言&#xff1a; Service Mesh定义 Service Mesh解决的痛点 Istio介绍 Service Mesh遇到的挑战 分布式应用的需求 Multiple Runtime 理念推导 Dapr 介绍 Dapr 特性 Dapr 核心…