HighCharts Draggable Plotline with Logarithmic axis scale

人盡茶涼 提交于 2019-12-12 02:54:26

问题


I have a simple Line chart using HighCharts & trying to add draggable plotlines in it.

$(function () {

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();
};

$('#container').highcharts({
    xAxis: {

        min: -10,
        max: 10,
        plotLines: [{
            id: 'foo',
            color: '#00F',
            width: 4,
            value: 5,
            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);
            }
        }]
    },

    yAxis: {
           type: 'logarithmic',  
        plotLines: [{
            label: {
                text: 'Not draggable'
            },
            id: 'y1',
            color: '#CCC',
            width: 4,
            value: 150
        }, {
            id: 'y2',
            color: '#00F',
            width: 4,
            value: 200,
            onDragStart: function (new_value) {
                $("#y_value").text(new_value + ' (Not changed yet)');
            },
            onDragChange: function (new_value) {
                $("#y_value").text(new_value + ' (Dragging)');
            },
            onDragFinish: function (new_value) {
                $("#y_value").text(new_value);
            }
        }, {
            label: {
                text: 'Not draggable'
            },
            id: 'y3',
            color: '#CCC',
            width: 4,
            value: 250
        }]
    },

    series: [{
        data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
    }]
}, function (chart) {
    draggablePlotLine(chart.xAxis[0], 'foo');
    draggablePlotLine(chart.yAxis[0], 'y2');
    console.log('ready');
});
});

JSFiddle Link: http://jsfiddle.net/48awM/30/ (actual) My Forked Update: http://jsfiddle.net/kk8322/z62nnmwe/1/

Actual JSFiddle works fine - which has normal axis scale, but forked version fails while dragging plotline. Only difference between actual & forked version is that my Y-Axis will be of type "Logarithmic".

   type: 'logarithmic'

Adding Logarithmic scale for axis is not handling drag/drop properly. Please suggest me how to handle Draggable Plotlines with Logarithmic x/y axis scale.


回答1:


There is a simpler way to move line while drag and drop. It works fine on logarithmic type axis.

Example: http://jsfiddle.net/tret53sv/

$(function () {

    var line,
    clickX,
    clickY;

    var start = function (e) {

        $(document).bind({
            'mousemove.line': step,
                'mouseup.line': stop
        });

        clickY = e.pageY - line.translateY;
        //clickY = e.pageY - line.translateY; //uncomment if plotline should be also moved vertically
    }

    var step = function (e) {
        line.translate(e.pageX - clickX, e.pageY - clickY)
    }

    var stop = function () {
        $(document).unbind('.line');
    }

    $('#container').highcharts({
        xAxis: {
            categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
        },
        yAxis:{
        type:'logarithmic',
             plotLines: [{
                color: '#FF0000',
                width: 5,
                value: 100
            }]
        },

        series: [{
            data: [29.9, 71.5, 106.4, 129.2, 144.0, 176.0, 135.6, 148.5, 216.4, 194.1, 95.6, 54.4]
        }]
    }, function (chart) {

        line = chart.yAxis[0].plotLinesAndBands[0].svgElem.attr({
            stroke: 'yellow'
        })
            .css({
            'cursor': 'pointer'
        })
            .translate(0, 0)
            .on('mousedown', start);


    });





});



回答2:


Thanks for sharing. Works pretty well. I also need to make an draggable or adjustable Plotband. For those who need an example here you can find an quick & dirty example based on Karthikeyan's solution from me.

I also used plotlines to adjust the plotband.

$(function () {
    function draggablePlotLineBand(axis, plotLineId, plotBandId, upperLine) {
        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 getPlotBand = function () {
            for (var i = 0; i < axis.plotLinesAndBands.length; i++) {
                if (axis.plotLinesAndBands[i].id === plotBandId) {
                    return axis.plotLinesAndBands[i];
                }
            }
        };

        var getFrom = function() {
            var plotBand = getPlotBand();
            var translation = axis.horiz ? plotBand.svgElem.translateX : plotBand.svgElem.translateY;
            var new_value = axis.toValue(translation) - axis.toValue(0) + plotBand.options.from;
            new_value = Math.max(axis.min, Math.min(axis.max, new_value));
            return new_value;
        };

        var getTo = function() {
            var plotBand = getPlotBand();
            var translation = axis.horiz ? plotBand.svgElem.translateX : plotBand.svgElem.translateY;
            var new_value = axis.toValue(translation) - axis.toValue(0) + plotBand.options.to;
            new_value = Math.max(axis.min, Math.min(axis.max, new_value));
            return new_value;
        };

        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();
            var plotBand = getPlotBand();
            clickX = e.pageX - plotLine.svgElem.translateX;
            clickY = e.pageY - plotLine.svgElem.translateY;
        };

        var drag_step = function (e) {
            var plotLine = getPlotLine();
            var plotBand = getPlotBand();
            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);

            var new_value_to = axis.toValue(new_translation) - axis.toValue(0) + plotBand.options.to;
            new_value_to = Math.max(axis.min, Math.min(axis.max, new_value_to));

            var new_value_from = axis.toValue(new_translation) - axis.toValue(0) + plotBand.options.from;
            new_value_from = Math.max(axis.min, Math.min(axis.max, new_value_from));

            var newPath = plotBand.svgElem.d.split(' ');

            if(upperLine) {
                new_translation = axis.toPixels(new_value_to + axis.toValue(0) - plotBand.options.to);
                newPath[2] = axis.toPixels(plotBand.options.from) - new_translation;
                newPath[5] = axis.toPixels(plotBand.options.from) - new_translation;
            } else {
                new_translation = axis.toPixels(new_value_from + axis.toValue(0) - plotBand.options.from);
                newPath[7] = axis.toPixels(plotBand.options.to) - new_translation;
                newPath[9] = axis.toPixels(plotBand.options.to) - new_translation;
            }

            newPath = newPath.join(" ");
            plotBand.svgElem.attr('d', newPath);

            plotBand.svgElem.translate(
                axis.horiz ? new_translation : 0,
                axis.horiz ? 0 : new_translation);
        };

        var drag_stop = function () {
            $(document).unbind('.line');

            var plotLine = getPlotLine();
            var plotLineOptions = plotLine.options;

            var plotBand = getPlotBand();
            var plotBandOptions = plotBand.options;

            if (plotLine.svgElem.hasOwnProperty('translateX')) {
                plotLineOptions.value = getValue();
                axis.removePlotLine(plotLineOptions.id);
                axis.addPlotLine(plotLineOptions);
            }

            if (plotBand.svgElem.hasOwnProperty('translateX')) {
                if(upperLine) {
                    plotBandOptions.to = getTo();
                    axis.removePlotBand(plotBandOptions.id);
                    axis.addPlotBand(plotBandOptions);                
                } else {
                    plotBandOptions.from = getFrom();
                    axis.removePlotBand(plotBandOptions.id);
                    axis.addPlotBand(plotBandOptions);
                }
            }

            getPlotLine().svgElem
                .css({'cursor': 'pointer'})
                .translate(0, 0)
                .on('mousedown', drag_start);
        };
        drag_stop();
    };

    $('#container').highcharts({
        xAxis: {
            min: -10,
            max: 10
        },
        yAxis: {
            tickInterval: 1,
            plotLines: [{
                id: 'pl1',
                color: "#ffcc00",
                width: 4,
                value: 3,
                zIndex: 3
            },{
                id: 'pl2',
                color: "#ffcc00",
                width: 4,
                value: 5,
                zIndex: 3
            }],
            plotBands: [{
                id: 'pb1',
                color: "#ffe682",
                width: 1,
                from: 3,
                to: 5,
                zIndex: 2
            }]
        },
        series: [{
            data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        }]
    }, function (chart) {
        // Need to use the function for both plotlines wih reference to plotband id
        // last parameter defines which is the lower(0) and upper(1) plotline
        draggablePlotLineBand(chart.yAxis[0], 'pl1', 'pb1', 0);
        draggablePlotLineBand(chart.yAxis[0], 'pl2', 'pb1', 1);
    });
});

JsFiddle Example Draggable Plotband with Plotlines



来源:https://stackoverflow.com/questions/36862453/highcharts-draggable-plotline-with-logarithmic-axis-scale

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!