/**
* Highcharts Draggable Legend Plugin
* legend对象需添加 {floating: true, draggable:true}属性
* @param HC Highcharts 对象
* @author CG
* @date 2024-09-05 14:35:21
* @remark 使用方法 DraggableLegend(Highcharts)
*/
const DraggableLegend = (HC) => {
/*一切的一切需在Highcharts实例存在的前提下执行*/
if (!HC || !HC instanceof Object) {
return
}
//事件枚举
const MouseEvent = Object.freeze({
MOUSE_DOWN: 'mousedown',
MOUSE_MOVE: 'mousemove',
MOUSE_UP: 'mouseup'
//...其他事件没用到定义了也是浪费内存
})
/*通过wrap扩展Chart类的init方法并保留原来的init功能完整*/
HC.wrap(HC.Chart.prototype, 'init', function (proceed) {
/*包装器回调函数*/
proceed.apply(this, Array.prototype.slice.call(arguments, 1));
/*获取到Chart this指向HC.Chart.prototype*/
const chart = this
//如果legend的draggable为true
if (chart.legend.options.draggable) {
const {legend: {box}} = chart//获取到legend.box对象
//添加鼠标样式为move标志
box.css({cursor: 'move'});
//定义鼠标按下时的Function对象
const handleMousedown = (event) => {
/*获取到Chart this指向HC.Chart.prototype ⚠在此处取值可以防止全屏模式无法拖动问题*/
const {chartWidth, chartHeight, legend, legend: {options, legendWidth, legendHeight}} = chart//获取到chart及legend的相关对象
event = chart.pointer.normalize(event);
const {chartX, chartY} = event;//获取到鼠标按下时的x,y坐标
const {x, y} = options;//获取到legend的x,y坐标
const currentX = legend.group.attr('translateX');//记录鼠标按下时x的位置
const currentY = legend.group.attr('translateY');//记录鼠标按下时y的位置
let dragging = true;//标记鼠标是否正在拖动状态
//使用闭包模式定义鼠标移动时的Function对象(一切起源于你在legend上按下了鼠标)
const handleMousemove = (event) => {
if (dragging) {
event = chart.pointer.normalize(event);
const draggedX = event.chartX - chartX;//获取到鼠标移动时的x坐标
const draggedY = event.chartY - chartY;//获取到鼠标移动时的y坐标
options.x = x + draggedX;//获取到legend的x坐标
options.y = y + draggedY;//获取到legend的y坐标
//拖动过程中判断是否出轨
const isInsideBox = (currentX + draggedX > 0 && currentX + draggedX + legendWidth < chartWidth && currentY + draggedY > 0 && currentY + draggedY + legendHeight < chartHeight);
//没出轨则更新位置
if (isInsideBox) {
legend.group.placed = false;//防止触发动画
legend.group.align(HC.extend({width: legendWidth, height: legendHeight}, options), true, 'spacingBox');//定位
}
//如果有被选择的标记点
if (chart.pointer.selectionMarker) {
chart.pointer.selectionMarker = chart.pointer.selectionMarker.destroy();//销毁标记点dom元素
}
}
};
//使用闭包模式定义鼠标抬起时的Function对象(一切起源于你在legend上按下了鼠标)
const handleMouseup = () => {
dragging = false;//改变拖拽状态为false
//本次拖动结束及时扫地释放内存
HC.removeEvent(chart.container, MouseEvent.MOUSE_MOVE, handleMousemove);
HC.removeEvent(document, MouseEvent.MOUSE_UP, handleMouseup);
};
//事件注册
HC.addEvent(chart.container, MouseEvent.MOUSE_MOVE, handleMousemove);
HC.addEvent(document, MouseEvent.MOUSE_UP, handleMouseup);
};
//在legend挂载鼠标按下事件
HC.addEvent(box.element, MouseEvent.MOUSE_DOWN, handleMousedown);
}
});
}
export default DraggableLegend;//导出
使用方法:
import Highcharts from "highcharts";
import DraggableLegend from "@/{your path}/draggable-legend"
DraggableLegend(Highcharts)
//Highcharts legend 配置
legend: {
enabled: true,
floating: true,
draggable:true,
//others legend options.....
}