拖放绘图线 React-Highcharts
Drag and drop plotline React-Highcharts
我想将拖放功能添加到 y 轴上的绘图线,因为我的图表是倒置的。
我发现了几个问题,这些问题似乎让我非常接近解决方案,但我无法使用 React-Highcharts 包来实现这些解决方案。
- . (http://jsfiddle.net/VXTeR/1/ - link 来自答案)
- HighCharts Draggable Plotline with Logarithmic axis scale (JSFiddle Link: http://jsfiddle.net/48awM/30/)
两种解决方案都说明了一个非常可行的解决方案。我的问题是将解决方案转换为 React-Highcharts 组件。
这是 JSFiddle 我的图表的精简版。
下面是我当前的 yAxis 配置
config.yaxis = {
title: 'Times',
descrition: 'Times within a 24 hour day.',
endOnTick: false,
opposite: true,
min: Date.UTC(0,0,0,0,0,0),
max: Date.UTC(0,0,0,24,30,0),
plotLines: [{
value: Date.UTC(0,0,0,6,0,0),
id: 'plotLineId',
color: colorObj.open,
dashStyle: 'shortdash',
width: 2,
zIndex: 4,
onDragStart: function (new_value) {
$("#x_value").text(new_value + ' (Not changed yet)');
},
onDragChange: function (new_value) {
$("#x_value").text(new_value + ' (Dragging)');
},
onDragFinish: function (new_value) {
$("#x_value").text(new_value);
}
}, {
value: Date.UTC(0,0,0,21,0,0),
id: 'plotLineId',
color: colorObj.close,
dashStyle: 'shortdash',
width: 2,
zIndex: 4,
onDragStart: function (new_value) {
$("#x_value").text(new_value + ' (Not changed yet)');
},
onDragChange: function (new_value) {
$("#x_value").text(new_value + ' (Dragging)');
},
onDragFinish: function (new_value) {
$("#x_value").text(new_value);
}
}],
type: 'datetime',
dateTimeLabelFormats: {
minute: '%l:%M%p',
hour: '%l %p',
day: '%l %p'
},
events: {
mouseOver: function (e) {
console.log('mouseOver - ', e);
}
}
}
以及我在 ReactHighcharts 组件文件中的内容
import React, { Component } from 'react';
import ReactHighcharts from 'react-highcharts'
import { allViewConfig } from './graphConfigs/graphConfigs';
class Graph extends Component {
afterRender = (chart) => {
function draggablePlotLine(axis, plotLineId) {
var clickX, clickY;
var getPlotLine = function () {
for (var i = 0; i < axis.plotLinesAndBands.length; i++) {
if (axis.plotLinesAndBands[i].id === plotLineId) {
return axis.plotLinesAndBands[i];
}
}
};
var getValue = function() {
var plotLine = getPlotLine();
var translation = axis.horiz ? plotLine.svgElem.translateX : plotLine.svgElem.translateY;
var new_value = axis.toValue(translation) - axis.toValue(0) + plotLine.options.value;
new_value = Math.max(axis.min, Math.min(axis.max, new_value));
return new_value;
};
var drag_start = function (e) {
$(document).bind({
'mousemove.line': drag_step,
'mouseup.line': drag_stop
});
var plotLine = getPlotLine();
clickX = e.pageX - plotLine.svgElem.translateX;
clickY = e.pageY - plotLine.svgElem.translateY;
if (plotLine.options.onDragStart) {
plotLine.options.onDragStart(getValue());
}
};
var drag_step = function (e) {
var plotLine = getPlotLine();
var new_translation = axis.horiz ? e.pageX - clickX : e.pageY - clickY;
var new_value = axis.toValue(new_translation) - axis.toValue(0) + plotLine.options.value;
new_value = Math.max(axis.min, Math.min(axis.max, new_value));
new_translation = axis.toPixels(new_value + axis.toValue(0) - plotLine.options.value);
plotLine.svgElem.translate(
axis.horiz ? new_translation : 0,
axis.horiz ? 0 : new_translation);
if (plotLine.options.onDragChange) {
plotLine.options.onDragChange(new_value);
}
};
var drag_stop = function () {
$(document).unbind('.line');
var plotLine = getPlotLine();
var plotLineOptions = plotLine.options;
//Remove + Re-insert plot line
//Otherwise it gets messed up when chart is resized
if (plotLine.svgElem.hasOwnProperty('translateX')) {
plotLineOptions.value = getValue()
axis.removePlotLine(plotLineOptions.id);
axis.addPlotLine(plotLineOptions);
if (plotLineOptions.onDragFinish) {
plotLineOptions.onDragFinish(plotLineOptions.value);
}
}
getPlotLine().svgElem
.css({'cursor': 'pointer'})
.translate(0, 0)
.on('mousedown', drag_start);
};
drag_stop();
};
}
render(){
return (
<div>
<ReactHighcharts
config={allViewConfig(this.props.configArr, this.props.bandRow, this.props.configVars)}
callback = {this.afterRender}
/>
</div>
);
}
};
export default Graph;
成功了。有几点需要调整。
- 需要遵循 React-Highcharts optional after-render callback 格式。
- 将任何 JQuery 操作转换为原始操作,以便它可以与 React 一起使用。基本上遍历并替换所有
$
- 出于我的目的,yAxis 配置中的
onDragStart
、onDragChange
和 onDragFinish
不是必需的。如果您执行 need/want,他们只需转换 JQuery 并像第 2 步中那样,您就可以开始了。
- 额外提示:如果您在 Redux 中保存新位置,请在更新图表时注意图表的重新渲染。这导致了一些奇怪的错误,直到我意识到 Redux 中的设置信息导致我的图表重新呈现之前,这些错误很难弄清楚。
下面是工作 ReactHighcharts 组件的代码。
import React, { PureComponent } from 'react';
import ReactHighcharts from 'react-highcharts'
import { allViewConfig } from './graphConfigs/graphConfigs';
import moment from 'moment'
class Graph extends PureComponent {
// Step 1a code
afterRender = (chart) => {
// this.draggablePlotLine(chart.xAxis[0], 'foo');
this.draggablePlotLine(chart.yAxis[0], 'plotLineIdOpen');
this.draggablePlotLine(chart.yAxis[0], 'plotLineIdClose');
console.log('ready');
}
// End Step 1a code
draggablePlotLine = (axis, plotLineId) => {
var clickX, clickY;
var getPlotLine = () => {
for (var i = 0; i < axis.plotLinesAndBands.length; i++) {
if (axis.plotLinesAndBands[i].id === plotLineId) {
return axis.plotLinesAndBands[i];
}
}
};
var getValue = () => {
var plotLine = getPlotLine();
var translation = axis.horiz ? plotLine.svgElem.translateX : plotLine.svgElem.translateY;
var new_value = axis.toValue(translation) - axis.toValue(0) + plotLine.options.value;
new_value = Math.max(axis.min, Math.min(axis.max, new_value));
return new_value;
};
var drag_start = (e) => {
// Step 2a code
document.addEventListener('mousemove', drag_step);
document.addEventListener('mouseup', drag_stop);
// Step 2a code
var plotLine = getPlotLine();
clickX = e.pageX - plotLine.svgElem.translateX;
clickY = e.pageY - plotLine.svgElem.translateY;
if (plotLine.options.onDragStart) {
plotLine.options.onDragStart(getValue());
}
};
var drag_step = (e) => {
var plotLine = getPlotLine();
var new_translation = axis.horiz ? e.pageX - clickX : e.pageY - clickY;
var new_value = axis.toValue(new_translation) - axis.toValue(0) + plotLine.options.value;
new_value = Math.max(axis.min, Math.min(axis.max, new_value));
new_translation = axis.toPixels(new_value + axis.toValue(0) - plotLine.options.value);
plotLine.svgElem.translate(
axis.horiz ? new_translation : 0,
axis.horiz ? 0 : new_translation);
if (plotLine.options.onDragChange) {
plotLine.options.onDragChange(new_value);
}
};
var test = (value) => {
console.log(value);
console.log(this);
this.props.updateState({key:['plotClose'], value: 'test' });
// this.props.updateState({key:['plotOpen'], value: value });
}
var drag_stop = () => {
// Step 2b code
document.removeEventListener('mousemove', drag_step);
document.removeEventListener('mouseup', drag_stop);
// Step 2b code
var plotLine = getPlotLine();
var plotLineOptions = plotLine.options;
//Remove + Re-insert plot line
//Otherwise it gets messed up when chart is resized
if (plotLine.svgElem.hasOwnProperty('translateX')) {
plotLineOptions.value = getValue()
// console.log(moment.utc(plotLineOptions.value).format('MMMM Do YYYY, h:mm:ss a'));
// console.log(plotLineOptions);
axis.removePlotLine(plotLineOptions.id);
axis.addPlotLine(plotLineOptions);
if (plotLineOptions.onDragFinish) {
plotLineOptions.onDragFinish(plotLineOptions.value);
}
}
getPlotLine().svgElem
.css({'cursor': 'pointer'})
.translate(0, 0)
.on('mousedown', drag_start);
};
drag_stop();
}
render(){
return (
<div>
<ReactHighcharts
config={allViewConfig(this.props.configArr.toArray(), this.props.bandRow, this.props.configVars)}
// Step 1b code
callback = {this.afterRender}
// End Step 1b code
/>
</div>
);
}
};
export default Graph;
我想将拖放功能添加到 y 轴上的绘图线,因为我的图表是倒置的。
我发现了几个问题,这些问题似乎让我非常接近解决方案,但我无法使用 React-Highcharts 包来实现这些解决方案。
- . (http://jsfiddle.net/VXTeR/1/ - link 来自答案)
- HighCharts Draggable Plotline with Logarithmic axis scale (JSFiddle Link: http://jsfiddle.net/48awM/30/)
两种解决方案都说明了一个非常可行的解决方案。我的问题是将解决方案转换为 React-Highcharts 组件。
这是 JSFiddle 我的图表的精简版。
下面是我当前的 yAxis 配置
config.yaxis = {
title: 'Times',
descrition: 'Times within a 24 hour day.',
endOnTick: false,
opposite: true,
min: Date.UTC(0,0,0,0,0,0),
max: Date.UTC(0,0,0,24,30,0),
plotLines: [{
value: Date.UTC(0,0,0,6,0,0),
id: 'plotLineId',
color: colorObj.open,
dashStyle: 'shortdash',
width: 2,
zIndex: 4,
onDragStart: function (new_value) {
$("#x_value").text(new_value + ' (Not changed yet)');
},
onDragChange: function (new_value) {
$("#x_value").text(new_value + ' (Dragging)');
},
onDragFinish: function (new_value) {
$("#x_value").text(new_value);
}
}, {
value: Date.UTC(0,0,0,21,0,0),
id: 'plotLineId',
color: colorObj.close,
dashStyle: 'shortdash',
width: 2,
zIndex: 4,
onDragStart: function (new_value) {
$("#x_value").text(new_value + ' (Not changed yet)');
},
onDragChange: function (new_value) {
$("#x_value").text(new_value + ' (Dragging)');
},
onDragFinish: function (new_value) {
$("#x_value").text(new_value);
}
}],
type: 'datetime',
dateTimeLabelFormats: {
minute: '%l:%M%p',
hour: '%l %p',
day: '%l %p'
},
events: {
mouseOver: function (e) {
console.log('mouseOver - ', e);
}
}
}
以及我在 ReactHighcharts 组件文件中的内容
import React, { Component } from 'react';
import ReactHighcharts from 'react-highcharts'
import { allViewConfig } from './graphConfigs/graphConfigs';
class Graph extends Component {
afterRender = (chart) => {
function draggablePlotLine(axis, plotLineId) {
var clickX, clickY;
var getPlotLine = function () {
for (var i = 0; i < axis.plotLinesAndBands.length; i++) {
if (axis.plotLinesAndBands[i].id === plotLineId) {
return axis.plotLinesAndBands[i];
}
}
};
var getValue = function() {
var plotLine = getPlotLine();
var translation = axis.horiz ? plotLine.svgElem.translateX : plotLine.svgElem.translateY;
var new_value = axis.toValue(translation) - axis.toValue(0) + plotLine.options.value;
new_value = Math.max(axis.min, Math.min(axis.max, new_value));
return new_value;
};
var drag_start = function (e) {
$(document).bind({
'mousemove.line': drag_step,
'mouseup.line': drag_stop
});
var plotLine = getPlotLine();
clickX = e.pageX - plotLine.svgElem.translateX;
clickY = e.pageY - plotLine.svgElem.translateY;
if (plotLine.options.onDragStart) {
plotLine.options.onDragStart(getValue());
}
};
var drag_step = function (e) {
var plotLine = getPlotLine();
var new_translation = axis.horiz ? e.pageX - clickX : e.pageY - clickY;
var new_value = axis.toValue(new_translation) - axis.toValue(0) + plotLine.options.value;
new_value = Math.max(axis.min, Math.min(axis.max, new_value));
new_translation = axis.toPixels(new_value + axis.toValue(0) - plotLine.options.value);
plotLine.svgElem.translate(
axis.horiz ? new_translation : 0,
axis.horiz ? 0 : new_translation);
if (plotLine.options.onDragChange) {
plotLine.options.onDragChange(new_value);
}
};
var drag_stop = function () {
$(document).unbind('.line');
var plotLine = getPlotLine();
var plotLineOptions = plotLine.options;
//Remove + Re-insert plot line
//Otherwise it gets messed up when chart is resized
if (plotLine.svgElem.hasOwnProperty('translateX')) {
plotLineOptions.value = getValue()
axis.removePlotLine(plotLineOptions.id);
axis.addPlotLine(plotLineOptions);
if (plotLineOptions.onDragFinish) {
plotLineOptions.onDragFinish(plotLineOptions.value);
}
}
getPlotLine().svgElem
.css({'cursor': 'pointer'})
.translate(0, 0)
.on('mousedown', drag_start);
};
drag_stop();
};
}
render(){
return (
<div>
<ReactHighcharts
config={allViewConfig(this.props.configArr, this.props.bandRow, this.props.configVars)}
callback = {this.afterRender}
/>
</div>
);
}
};
export default Graph;
成功了。有几点需要调整。
- 需要遵循 React-Highcharts optional after-render callback 格式。
- 将任何 JQuery 操作转换为原始操作,以便它可以与 React 一起使用。基本上遍历并替换所有
$
- 出于我的目的,yAxis 配置中的
onDragStart
、onDragChange
和onDragFinish
不是必需的。如果您执行 need/want,他们只需转换 JQuery 并像第 2 步中那样,您就可以开始了。 - 额外提示:如果您在 Redux 中保存新位置,请在更新图表时注意图表的重新渲染。这导致了一些奇怪的错误,直到我意识到 Redux 中的设置信息导致我的图表重新呈现之前,这些错误很难弄清楚。
下面是工作 ReactHighcharts 组件的代码。
import React, { PureComponent } from 'react';
import ReactHighcharts from 'react-highcharts'
import { allViewConfig } from './graphConfigs/graphConfigs';
import moment from 'moment'
class Graph extends PureComponent {
// Step 1a code
afterRender = (chart) => {
// this.draggablePlotLine(chart.xAxis[0], 'foo');
this.draggablePlotLine(chart.yAxis[0], 'plotLineIdOpen');
this.draggablePlotLine(chart.yAxis[0], 'plotLineIdClose');
console.log('ready');
}
// End Step 1a code
draggablePlotLine = (axis, plotLineId) => {
var clickX, clickY;
var getPlotLine = () => {
for (var i = 0; i < axis.plotLinesAndBands.length; i++) {
if (axis.plotLinesAndBands[i].id === plotLineId) {
return axis.plotLinesAndBands[i];
}
}
};
var getValue = () => {
var plotLine = getPlotLine();
var translation = axis.horiz ? plotLine.svgElem.translateX : plotLine.svgElem.translateY;
var new_value = axis.toValue(translation) - axis.toValue(0) + plotLine.options.value;
new_value = Math.max(axis.min, Math.min(axis.max, new_value));
return new_value;
};
var drag_start = (e) => {
// Step 2a code
document.addEventListener('mousemove', drag_step);
document.addEventListener('mouseup', drag_stop);
// Step 2a code
var plotLine = getPlotLine();
clickX = e.pageX - plotLine.svgElem.translateX;
clickY = e.pageY - plotLine.svgElem.translateY;
if (plotLine.options.onDragStart) {
plotLine.options.onDragStart(getValue());
}
};
var drag_step = (e) => {
var plotLine = getPlotLine();
var new_translation = axis.horiz ? e.pageX - clickX : e.pageY - clickY;
var new_value = axis.toValue(new_translation) - axis.toValue(0) + plotLine.options.value;
new_value = Math.max(axis.min, Math.min(axis.max, new_value));
new_translation = axis.toPixels(new_value + axis.toValue(0) - plotLine.options.value);
plotLine.svgElem.translate(
axis.horiz ? new_translation : 0,
axis.horiz ? 0 : new_translation);
if (plotLine.options.onDragChange) {
plotLine.options.onDragChange(new_value);
}
};
var test = (value) => {
console.log(value);
console.log(this);
this.props.updateState({key:['plotClose'], value: 'test' });
// this.props.updateState({key:['plotOpen'], value: value });
}
var drag_stop = () => {
// Step 2b code
document.removeEventListener('mousemove', drag_step);
document.removeEventListener('mouseup', drag_stop);
// Step 2b code
var plotLine = getPlotLine();
var plotLineOptions = plotLine.options;
//Remove + Re-insert plot line
//Otherwise it gets messed up when chart is resized
if (plotLine.svgElem.hasOwnProperty('translateX')) {
plotLineOptions.value = getValue()
// console.log(moment.utc(plotLineOptions.value).format('MMMM Do YYYY, h:mm:ss a'));
// console.log(plotLineOptions);
axis.removePlotLine(plotLineOptions.id);
axis.addPlotLine(plotLineOptions);
if (plotLineOptions.onDragFinish) {
plotLineOptions.onDragFinish(plotLineOptions.value);
}
}
getPlotLine().svgElem
.css({'cursor': 'pointer'})
.translate(0, 0)
.on('mousedown', drag_start);
};
drag_stop();
}
render(){
return (
<div>
<ReactHighcharts
config={allViewConfig(this.props.configArr.toArray(), this.props.bandRow, this.props.configVars)}
// Step 1b code
callback = {this.afterRender}
// End Step 1b code
/>
</div>
);
}
};
export default Graph;