热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

echarts树点击label事件_ECharts堆积木(砖块)游戏

最近突发奇想,用3D的堆叠柱图,做了一个搭积木的小游戏。主要思路用一个几乎透明的series-bar3D铺满整个grid3D,作为操作区&

8940e1c5ad0902e0b11628e87873a15f.png

最近突发奇想,用 3D 的堆叠柱图,做了一个搭积木的小游戏。

主要思路

  1. 用一个几乎透明的 series-bar3D 铺满整个 grid3D,作为操作区,监听鼠标点击事件、完成堆积木的操作;
  2. 用多层数据为 0 的 series-bar3D 放在操作层 bar3D 下方,堆积木时,按照从下向上的顺序,更新其数据 series-bar3D.data(包括数值和样式,即 value 和 itemStyle);
  3. 用一个 series-heatmap 制作菜单,也是监听鼠标点击事件,实现撤销、重做、重置、修改积木样式(高度、颜色和透明度)等功能。

效果演示

bb4d7ffa0bda00c7d1a1801ef39bb65b.gif
家里的笔记本屏幕小,菜单按钮上的文字几乎全都显示不全了……

关键代码

  • 生成数据的部分

generateData = (length) => {let ret = {x: [],y: [],boxWidth: length,boxDepth: length,boxHeight: length,operatingSeriesData: [],brickSeriesData: []};let brickSeriesDataItem = [];for (let i = 0; i };

由于一开始对 3D 堆叠柱图的堆叠机制了解不够深入(自以为是,没仔细看配置项手册[1],大家不要学我哈- -),所以一上来就把所有可能用到的砖块数据都生成出来了……也不管最终是否会用到。这里还有优化的空间……

  • series-heatmap.data 生成部分

generateMenuData = (colorList, sizeList) => {let ret = [];for (let i = 0; i };

  • option.series 生成

generateSeries = (src) => {ret = [];for (let i = 0; i {if (params.name === 'color') {return `点击更换“积木”颜色为 ${params.color}`;}if (params.name === 'size') {return `点击更换“积木”高度为 ${params.value[2]}`;}return {undo: '撤销', redo: '重做', reset: '清空', save: '导出游戏数据,
供下次赋值给 loadData 使用', load: '功能开发中…' }[params.name]; }},label: {normal:{formatter: params => { if (params.name === 'color') {return params.color;}if (params.name === 'size') {return params.value[2]; }return params.name;}}},itemStyle: {borderColor: '#AAA',borderWidth: 4},data: generateMenuData(menuConfig.colorList, menuConfig.sizeList)});return ret;
};

通过 tooltip.formatter 和 label.normal.formatter 定义按钮的文字和提示框内容

  • 撤销、重做函数定义

// 撤销
undo = () => {if (history.undoList.length === 0) {alert('操作历史记录为空,撤销未执行…');return console.log('操作历史记录为空,撤销未执行…');}// undoList 最后一条记录“剪切”到 redoListlet historyObj = history.undoList.pop();history.redoList.push(historyObj);// 将上一步操作/重做的 series[seriesIndex].data[dataIndex] 重置为初始值let val = series[historyObj.seriesIndex].data[historyObj.dataIndex].value;val[2] = 0;series[historyObj.seriesIndex].data[historyObj.dataIndex] = {value: val};myChart.setOption({series: series});console.log('撤销成功');
};// 重做
redo = () => {if (history.redoList.length === 0) {alert('操作历史记录为空,重做未执行…');return console.log('操作历史记录为空,重做未执行…');}// redoList 最后一条记录“剪切”到 undoListlet historyObj = history.redoList.pop();history.undoList.push(historyObj);// 将上一步重置的 series[seriesIndex].data[dataIndex] 重设为撤销前的状态series[historyObj.seriesIndex].data[historyObj.dataIndex].value[2] = historyObj.brickConfig.size;series[historyObj.seriesIndex].data[historyObj.dataIndex].itemStyle = {color: historyObj.brickConfig.color,opacity: historyObj.brickConfig.opacity};myChart.setOption({series: series});console.log('重做成功');
};// 撤销/重做 所用的操作历史记录
let history = {undoList: [],redoList: []
};

  • 鼠标单击事件监听处理

// 监听鼠标点击事件
myChart.on('click', params => {// 菜单操作处理if (params.seriesName === 'menu') {if (params.name === 'color') {brickConfig.color = params.color;brickConfig.opacity = 1;myChart.setOption({title:{subtext: `当前颜色:${brickConfig.color}n当前尺寸:${brickConfig.size}n当前透明度:${brickConfig.opacity}`}});return console.log(`砖块颜色更换为${params.color}`);}if (params.name === 'empty') {brickConfig.color = params.color;brickConfig.opacity = 0;myChart.setOption({title:{subtext: `当前颜色:${brickConfig.color}n当前尺寸:${brickConfig.size}n当前透明度:${brickConfig.opacity}`}});return console.log(`砖块颜色更换为透明`);}if (params.name === 'size') {brickConfig.size = params.value[2];myChart.setOption({title:{subtext: `当前颜色:${brickConfig.color}n当前尺寸:${brickConfig.size}n当前透明度:${brickConfig.opacity}`}});return console.log(`砖块 size 更换为${params.value[2]}`);}if (params.name === 'load') {// loadalert('开发中…');return console.log('开发中…');}if (params.name === 'reset') {data = generateData(xLength);series = generateSeries(data);myChart.setOption({series: series});return console.log('清空数据成功');}if (params.name === 'save') {let uri = 'data:application/json;base64,';//console.log(data);window.location.href = uri + base64(JSON.stringify(data));return console.log('导出数据成功');}if (params.name === 'undo') {return undo();}if (params.name === 'redo') {return redo();}}//alert(`正在 (${params.data[0]}, ${params.data[1]}) 处堆积一个砖块`);// 堆积木(砖块)操作处理for (let i in series) {if (series[i].name === 'bricks' && series[i].data[params.data[0] * xLength + params.data[1]].value[2] === 0) {series[i].data[params.data[0] * xLength + params.data[1]].value[2] = brickConfig.size;series[i].data[params.data[0] * xLength + params.data[1]].itemStyle = {color: brickConfig.color,opacity: brickConfig.opacity};history.undoList.push({seriesIndex: i, dataIndex: params.data[0] * xLength + params.data[1], brickConfig: JSON.parse(JSON.stringify(brickConfig)) // 深拷贝});history.redoList = [];return myChart.setOption({series: series}); }}
});

主要就是通过 echartsInstance.on 绑定事件处理函数,也就是 myChart.on('click', function(){}) 的形式。

ECharts Gallery​gallery.echartsjs.com

参考

  1. ^柱状图堆叠,相同 stack 值的柱状图系列数据会有叠加。注意不同系列需要叠加的数据项在数组中的索引必须是一样的。 https://echarts.apache.org/zh/option-gl.html#series-bar3D.stack


推荐阅读
  • C++ 异步编程中获取线程执行结果的方法与技巧及其在前端开发中的应用探讨
    本文探讨了C++异步编程中获取线程执行结果的方法与技巧,并深入分析了这些技术在前端开发中的应用。通过对比不同的异步编程模型,本文详细介绍了如何高效地处理多线程任务,确保程序的稳定性和性能。同时,文章还结合实际案例,展示了这些方法在前端异步编程中的具体实现和优化策略。 ... [详细]
  • 本文详细介绍了在 Oracle 数据库中使用 MyBatis 实现增删改查操作的方法。针对查询操作,文章解释了如何通过创建字段映射来处理数据库字段风格与 Java 对象之间的差异,确保查询结果能够正确映射到持久层对象。此外,还探讨了插入、更新和删除操作的具体实现及其最佳实践,帮助开发者高效地管理和操作 Oracle 数据库中的数据。 ... [详细]
  • 本文探讨了如何利用Java代码获取当前本地操作系统中正在运行的进程列表及其详细信息。通过引入必要的包和类,开发者可以轻松地实现这一功能,为系统监控和管理提供有力支持。示例代码展示了具体实现方法,适用于需要了解系统进程状态的开发人员。 ... [详细]
  • 在 Vue 应用开发中,页面状态管理和跨页面数据传递是常见需求。本文将详细介绍 Vue Router 提供的两种有效方式,帮助开发者高效地实现页面间的数据交互与状态同步,同时分享一些最佳实践和注意事项。 ... [详细]
  • 技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告
    技术日志:使用 Ruby 爬虫抓取拉勾网职位数据并生成词云分析报告 ... [详细]
  • 尽管我们尽最大努力,任何软件开发过程中都难免会出现缺陷。为了更有效地提升对支持部门的协助与支撑,本文探讨了多种策略和最佳实践,旨在通过改进沟通、增强培训和支持流程来减少这些缺陷的影响,并提高整体服务质量和客户满意度。 ... [详细]
  • 本文详细解析了使用C++实现的键盘输入记录程序的源代码,该程序在Windows应用程序开发中具有很高的实用价值。键盘记录功能不仅在远程控制软件中广泛应用,还为开发者提供了强大的调试和监控工具。通过具体实例,本文深入探讨了C++键盘记录程序的设计与实现,适合需要相关技术的开发者参考。 ... [详细]
  • 在优化Nginx与PHP的高效配置过程中,许多教程提供的配置方法存在诸多问题或不良实践。本文将深入探讨这些常见错误,并详细介绍如何正确配置Nginx和PHP,以实现更高的性能和稳定性。我们将从Nginx配置文件的基本指令入手,逐步解析每个关键参数的最优设置,帮助读者理解其背后的原理和实际应用效果。 ... [详细]
  • 在探讨P1923问题时,我们发现手写的快速排序在最后两个测试用例中出现了超时现象,这在意料之中,因为该题目实际上要求的是时间复杂度为O(n)的算法。进一步研究题解后,发现有选手使用STL中的`nth_element`函数成功通过了所有测试点。本文将详细分析这一现象,并提出相应的优化策略。 ... [详细]
  • 在洛谷 P1344 的坏牛奶追踪问题中,第一问要求计算最小割,而第二问则需要找到割边数量最少的最小割。通过为每条边附加一个单位权值,可以在求解最小割时优先选择边数较少的方案,从而同时解决两个问题。这种策略不仅简化了问题的求解过程,还确保了结果的最优性。 ... [详细]
  • 本文深入探讨了Ajax的工作机制及其在现代Web开发中的应用。Ajax作为一种异步通信技术,改变了传统的客户端与服务器直接交互的模式。通过引入Ajax,客户端与服务器之间的通信变得更加高效和灵活。文章详细分析了Ajax的核心原理,包括XMLHttpRequest对象的使用、数据传输格式(如JSON和XML)以及事件处理机制。此外,还介绍了Ajax在提升用户体验、实现动态页面更新等方面的具体应用,并讨论了其在当前Web开发中的重要性和未来发展趋势。 ... [详细]
  • 使用 `git stash` 可以将当前未提交的修改保存到一个临时存储区,以便在后续恢复工作目录时使用。例如,在处理中间状态时,可以通过 `git stash` 命令将当前的所有未提交更改推送到一个新的储藏中,从而保持工作目录的整洁。此外,本文还将详细介绍如何解决 `git stash pop` 时可能出现的冲突问题,帮助用户高效地管理代码变更。 ... [详细]
  • JavaScript XML操作实用工具类:XmlUtilsJS技巧与应用 ... [详细]
  • 寒假作业解析:第三周 2月12日 第7题
    尽快完成之前的练习任务!每日一练2.1 Problem A Laurenty and Shop 的题目要求是选择两条不同的路线以最小化总的等待时间。简要分析:通过对比不同路线的等待时间,可以找到最优解。此问题可以通过动态规划或贪心算法来解决,具体取决于路线的复杂性和约束条件。 ... [详细]
  • 本文探讨了如何通过检测浏览器类型来动态加载特定的npm包,从而优化前端性能。具体而言,仅在用户使用Edge浏览器时加载相关包,以提升页面加载速度和整体用户体验。此外,文章还介绍了实现这一目标的技术细节和最佳实践,包括使用User-Agent字符串进行浏览器识别、条件加载策略以及性能监控方法。 ... [详细]
author-avatar
没搜摸索摸索_685
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有