快速移动鼠标触发问题及解决方法(ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave)


Posted in Javascript onAugust 29, 2016

记录两个项目开发中遇到的问题,一个是ECharts外部调用保存为图片操作,一个是workflow工作流连接曲线onmouseenter和onmouseleave事件由于鼠标移动过快触发问题。

一、外部按钮调用ECharts图表的保存为图片操作

最近使用ECharts库绘制图表,依据需求希望可以把图表设置的保存为图片操作可以在图表外部调用,主要是希望可以和项目之前的下载图片操作界面保持一致。然后上网找了一些方法,看了看也没遇到一个可以满意的。后来,突然想到了echart开放了源码,可以看看源码,找到下载的方法,然后调用不就可以了(可能是我技术忒次,看了看不只到如何直接调用方法,所以把源方法copy下来,改了改,只需要传递图表的容器id即可)

echart图表示例(工具栏中有下载图片按钮)

快速移动鼠标触发问题及解决方法(ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave)

附上代码记录一下

//传递图表容器idfunction downloadImpByChart(chartId){
var myChart = echarts.getInstanceByDom(document.getElementById(chartId));
var url = myChart.getConnectedDataURL({
pixelRatio: 5,//导出的图片分辨率比率,默认是1
backgroundColor: '#fff',
//图表背景色
excludeComponents:[
//保存图表时忽略的工具组件,默认忽略工具栏
'toolbox'
],
type:'png'
//图片类型支持png和jpeg
});
var $a = document.createElement('a');
var type = 'png';
$a.download = myChart.getOption().title[0].text + '.' + type;
$a.target = '_blank';
$a.href = url;
// Chrome and Firefox
if (typeof MouseEvent === 'function') {
var evt = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: false
});
$a.dispatchEvent(evt);
}
// IE
else {
var html = ''
+ '<body style="margin:0;">'
+ '<img src="' + url + '" style="max-width:100%;" title="' + myChart.getOption().title[0].text + '" />'
+ '</body>';
var tab = window.open();
tab.document.write(html);
}
};

这样,我们就可以不使用它自带的下载操作了,就可以在外部自定义按钮、超链接,直接调用上面的方法就可以实现外部调用保存图片功能了。

二、onmouseenter和onmouseleave移动速度过快导致不能正确的时机触发事件机制

上图说明一下

快速移动鼠标触发问题及解决方法(ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave)

希望鼠标在曲线上移动时不仅可以高亮展示曲线,还要在鼠标位置增加剪刀图标,按下剪刀时可以删除曲线。之前就直接在曲线上使用的mouseener和mouseleave方法,然后鼠标在多条曲线上快速移动时,就会出现诸多问题(剪刀不会在光标离开时消失,多条曲线都变为高亮效果)。试了多加上一些逻辑判定和换用mouseover和mouseout方法均不管用。后来突然想到,可以使用mousemove方法。判定鼠标是否在剪刀图表的区域范围内,若在则高亮该条曲线,不再,则所有曲线恢复默认样式。然后居然成功了。困扰了一整天的问题终于解决了。(由于mousemove在鼠标移动时需要不断的去监听和触发事件,所以最好可以有一个状态标识表明在该状态在再去调用高亮曲线和绘制剪刀的方法。图上的调用时机是,当鼠标进入曲线时,设定一个全局变量为true,此后的mousemove操作根据该变量判定

记录一下部分关键代码

鼠标就进入高亮及绘制剪刀图表

$(document).on("mouseenter","svg .curve",function(e){
//每次进入后都将恢复成原始状态
$("svg .node").each(function(){
this.setAttribute("opacity","1");
});
$.each(relation.links,function(l,link){
var in_node_id=link.input.nodeId;
var out_node_id=link.output.nodeId;
$("#"+out_node_id+link.output.pointName+in_node_id+link.input.pointName)[0].setAttribute("opacity","1");
$("#"+out_node_id+link.output.pointName+in_node_id+link.input.pointName).attr("class","curve");
});
//编辑状态下需要显示可操作图标
if(args.state=="edit"){
del_Curve.ref_Curve=this;
del_Curve.has_del_curve=true;
if($("#del-curve-icon").length>0){
$("#del-curve-icon").css({
position:"absolute",
top: e.pageY-obj.offset().top-10,
left: e.pageX-obj.offset().left-10,
color:"#ff0000"
}).show();
}else{
var del_icon=$("<i id='del-curve-icon' class='fa fa-scissors'></i>").css({
position:"absolute",
top: e.pageY-obj.offset().top-10,
left: e.pageX-obj.offset().left-10,
color:"#ff0000",
fontSize:"20px"
});
obj.parent().append(del_icon);
}
del_Curve.xAxis=$("#del-curve-icon").offset().left;
del_Curve.yAxis=$("#del-curve-icon").offset().top;
}
//然后高亮当前曲线
if($(this).attr("start")!=undefined && $(this).attr("end")!=undefined){
//设置透明度
$("svg .node").each(function(){
this.setAttribute("opacity","0.1");
});
$.each(relation.links,function(l,link){
var in_node_id=link.input.nodeId;
var out_node_id=link.output.nodeId;
$("#"+out_node_id+link.output.pointName+in_node_id+link.input.pointName)[0].setAttribute("opacity","0.1");
});
obj.children("g").eq(0).children("g").eq(0).before($(this));
$(this).attr("class","curve curve-hover");
var in_node=$("#"+$(this).attr("start")).children("g").eq(0).children("circle").eq(1);
in_node.attr("class",in_node.attr("class")+" node-hover");
$("#"+$(this).attr("start"))[0].setAttribute("opacity","1");
var out_node=$("#"+$(this).attr("end")).children("g").eq(0).children("circle").eq(1);
out_node.attr("class",out_node.attr("class")+" node-hover");
$("#"+$(this).attr("end"))[0].setAttribute("opacity","1");
}
});

移动鼠标判定触发操作

$(document).on("mousemove",function(e){if(del_Curve.has_del_curve){
var del_icon_width=$("#del-curve-icon").width();
var del_icon_height=$("#del-curve-icon").height()



//判定当前光标位置,若不在剪刀图表区域内则恢复默认样式
if(e.pageX<del_Curve.xAxis || e.pageX>(del_Curve.xAxis+del_icon_width) || e.pageY<del_Curve.yAxis || e.pageY>(del_Curve.yAxis+del_icon_height)){
del_Curve.has_del_curve=false;
$("svg .node").each(function(){
this.setAttribute("opacity","1");
});
$.each(relation.links,function(l,link){
var in_node_id=link.input.nodeId;
var out_node_id=link.output.nodeId;
$("#"+out_node_id+link.output.pointName+in_node_id+link.input.pointName)[0].setAttribute("opacity","1");
$("#"+out_node_id+link.output.pointName+in_node_id+link.input.pointName).attr("class","curve");
});
$(del_Curve.ref_Curve).attr("class","curve");
var in_node=$("#"+$(del_Curve.ref_Curve).attr("start")).children("g").eq(0).children("circle").eq(1);
in_node.attr("class",in_node.attr("class").replace("node-hover","").trim());
var out_node=$("#"+$(del_Curve.ref_Curve).attr("end")).children("g").eq(0).children("circle").eq(1);
out_node.attr("class",out_node.attr("class").replace("node-hover","").trim());
$("#del-curve-icon").hide();
}
}
})

okay,其实工作流的问题,如果单单只是高亮曲线,mouseenter和mouseleave的效果就足够了。不过示例中,需要在曲线上覆盖一个剪刀图标,这就会跟原来曲线的mouseenter和mouseleave有冲突。因为删除曲线的触发元素是剪刀图标。

Javascript 相关文章推荐
JS实现简单的Canvas画图实例
Jul 04 Javascript
javascript中setAttribute()函数使用方法及兼容性
Jul 19 Javascript
Hallo.js基于jQuery UI所见即所得的Web编辑器
Jan 26 Javascript
jQuery Mobile动态刷新页面样式的实现方法
May 28 Javascript
Javascript必知必会(四)js类型转换
Jun 08 Javascript
原生js图片轮播效果实现代码
Oct 19 Javascript
angular.JS实现网页禁用调试、复制和剪切
Mar 31 Javascript
react router4+redux实现路由权限控制的方法
May 03 Javascript
使用Object.defineProperty如何巧妙找到修改某个变量的准确代码位置
Nov 02 Javascript
Javascript的this详解
Mar 23 Javascript
微信小程序API—获取定位的详解
Apr 30 Javascript
bootstrap中的导航条实例代码详解
May 20 Javascript
浅谈JSON.stringify()和JOSN.parse()方法的不同
Aug 29 #Javascript
jQuery EasyUI编辑DataGrid用combobox实现多级联动
Aug 29 #Javascript
对js中回调函数的一些看法
Aug 29 #Javascript
Web打印解决方案之普通报表打印功能
Aug 29 #Javascript
jQuery获取select选中的option的value值实现方法
Aug 29 #Javascript
js 判断各种数据类型的简单方法(推荐)
Aug 29 #Javascript
Web打印解决方案之证件套打的实现思路
Aug 29 #Javascript
You might like
php生成二维码的几种方式整理及使用实例
2013/06/03 PHP
分享3个php获取日历的函数
2015/09/25 PHP
把textarea中字符串里含有的回车换行替换成&amp;lt;br&amp;gt;的javascript代码
2007/04/20 Javascript
dropdownlist之间的互相联动实现(显示与隐藏)
2009/11/24 Javascript
JS通过分析userAgent属性来判断浏览器的类型及版本
2014/03/28 Javascript
js实现带缓冲效果的仿QQ面板折叠菜单代码
2015/09/06 Javascript
JavaScript 经典实例日常收集整理(常用经典)
2016/03/30 Javascript
jquery对dom节点的操作【推荐】
2016/04/15 Javascript
JavaScript中子对象访问父对象的方式详解
2016/09/01 Javascript
React Js 微信禁止复制链接分享禁止隐藏右上角菜单功能
2017/05/26 Javascript
Swiper 4.x 使用方法(移动端网站的内容触摸滑动)
2018/05/17 Javascript
Vue父子组件之间的通信实例详解
2018/09/28 Javascript
在Create React App中启用Sass和Less的方法示例
2019/01/16 Javascript
微信小程序点击图片实现长按预览、保存、识别带参数二维码、转发等功能
2019/07/20 Javascript
kafka调试中遇到Connection to node -1 could not be established. Broker may not be available.
2019/09/17 Javascript
async/await让异步操作同步执行的方法详解
2019/11/01 Javascript
解决vue项目运行npm run serve报错的问题
2020/10/26 Javascript
[03:17]DOTA2英雄基础教程 剧毒术士
2013/12/12 DOTA
用Python的Tornado框架结合memcached页面改善博客性能
2015/04/24 Python
[原创]pip和pygal的安装实例教程
2017/12/07 Python
python判断列表的连续数字范围并分块的方法
2018/11/16 Python
Python http接口自动化测试框架实现方法示例
2018/12/06 Python
Python3.5面向对象程序设计之类的继承和多态详解
2019/04/24 Python
dpn网络的pytorch实现方式
2020/01/14 Python
使用已经得到的keras模型识别自己手写的数字方式
2020/06/29 Python
解决python 虚拟环境删除包无法加载的问题
2020/07/13 Python
如何利用python生成MD5并去重
2020/12/07 Python
html5使用canvas画空心圆与实心圆
2014/12/15 HTML / CSS
中国领先的专业演出票务网:永乐票务
2016/08/29 全球购物
Luxplus丹麦:香水和个人护理折扣
2018/04/23 全球购物
欧尚俄罗斯网上超市:Auchan俄罗斯
2018/05/03 全球购物
内勤主管岗位职责
2014/04/03 职场文书
单位租车协议书
2015/01/29 职场文书
2019森林防火宣传标语大全!
2019/07/03 职场文书
详解MongoDB的条件查询和排序
2021/06/23 MongoDB
适合后台管理系统开发的12个前端框架(小结)
2021/06/29 Javascript