在 highcharts 中,我正在尝试向点的数据标签添加拖动效果。我找到了几种定位给定标签的方法。在这个小提琴中,你可以看到我的一些尝试。(我在这里的一个小提琴中结合了不同的尝试来炫耀我尝试过的东西)
现在使用 chart.series[0].data[0].dataLabel 和使用点单击事件都使我能够更改 dataLabel 的属性。但是我无法将 jquery ui .draggable() 附加到标签上。是否有可能使图表内的元素可拖动?
如果需要更多信息,请告诉我
在 highcharts 中,我正在尝试向点的数据标签添加拖动效果。我找到了几种定位给定标签的方法。在这个小提琴中,你可以看到我的一些尝试。(我在这里的一个小提琴中结合了不同的尝试来炫耀我尝试过的东西)
现在使用 chart.series[0].data[0].dataLabel 和使用点单击事件都使我能够更改 dataLabel 的属性。但是我无法将 jquery ui .draggable() 附加到标签上。是否有可能使图表内的元素可拖动?
如果需要更多信息,请告诉我
您实际上可以将draggable
小部件附加到数据标签上。但是,由于数据标签是SVG元素,它们完全忽略了对其position
,left
和top
CSS 属性所做的更改。
相反,<g>
包装标签的元素公开了一个transform
属性:
<g zIndex="1" transform="translate(9, 152)">
<!-- data label content -->
</g>
我们仍然可以使用draggable
小部件(这非常方便,因为它抽象了较低级别的拖动事件)并在拖动事件处理程序中更新transform
数据标签包装器的属性。由于拖动坐标是相对的,我们必须解析原始属性并使用生成的坐标作为原点。transform
现在,所有标签包装器本身都是用该类装饰的组的子highcharts-data-labels
级。这为我们提供了一个很好的起点,因此我们可以编写如下内容:
$(".highcharts-data-labels").children().filter(function() {
var $this = $(this);
// Parse original translation.
var coords = $this.attr("transform")
.match(/translate\((-?\d+),\s*(-?\d+)\)/);
if (coords) {
// Associate origin with element.
return $this.data("origin", {
x: +coords[1],
y: +coords[2]
});
} else {
// Parsing failed, reject element.
return false;
}
}).draggable({
drag: function(event, ui) {
var $this = $(this);
// Fetch back origin.
var origin = $this.data("origin");
// Update current transform.
$this.attr("transform", "translate("
+ (origin.x + ui.position.left) + ", "
+ (origin.y + ui.position.top) + ")");
}
});
你会在这里找到一个更新的小提琴。
关于上面代码的几点说明:
使用filter()而不是each()因为它允许我们过滤掉transform
属性无法解析的元素(你永远不知道),而不是彻底失败或向drag
处理程序中的计算提供垃圾,
使用attr()代替prop()来强调我们正在修改 SVG 片段中的属性这一事实。prop()
可能会以完全相同的方式工作,所以这只是风格和个人喜好的问题。
最后,一个警告:我现在只能在 Firefox 上进行测试,但似乎很难mousedown
在某些标签上触发事件,尤其是在曲线和数据提示争夺空间的“拥挤”区域。调整zIndex
数据标签包装器的属性并没有太大的作用。多次点击有时会有所帮助。如果这在所有浏览器上都是一致的,则可能必须设计其他解决方案(可能是透明覆盖,或者只是将mousedown
事件从数据点本身中继到数据标签)。
$(document).ready(function() {
chart = new Highcharts.Chart({
chart: {
renderTo: 'container',
type: 'line'
},
title: {
text: 'Monthly Average Temperature'
},
subtitle: {
text: 'Source: WorldClimate.com'
},
xAxis: {
categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
},
yAxis: {
title: {
text: 'Temperature'
},
plotLines: [{
value: 0,
width: 1,
color: '#808080'
}]
},
plotOptions: {
series: {
dataLabels: {
enabled: true
},
events: {
//Here I'm able to move the labels by using the click and shift-click.
//I wish to do this by dragging
click: function(event) {
var current_y = event.point.dataLabel.attr('y');
if(event.shiftKey) {
var new_y = current_y + 2;
event.point.dataLabel.attr({y: new_y});
} else {
var new_y = current_y - 2;
event.point.dataLabel.attr({y: new_y});
}
}
}
}
},
series: [{
name: 'Tokyo',
data: [7.0, 6.9, 9.5, 14.5, 18.2, 21.5, 25.2, 26.5, 23.3, 18.3, 13.9, 9.6]
}, {
name: 'New York',
data: [-0.2, 0.8, 5.7, 11.3, 17.0, 22.0, 24.8, 24.1, 20.1, 14.1, 8.6, 2.5]
}, {
name: 'Berlin',
data: [-0.9, 0.6, 3.5, 8.4, 13.5, 17.0, 18.6, 17.9, 14.3, 9.0, 3.9, 1.0]
}]
});
//Second attempt to grab a point. Works for chaning attributes
var point = chart.series[0].data[0].dataLabel;
} , function(chart){
});
$(function() {
console.log(chart) ;
$( "#draggable" ).draggable()
.text(chart.series[0].data[0].y + 'drag and drop me ');
});
</p>