Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Mouse events don't work on Pie charts (sencha-chart) with only one slice visibile

    You found a bug! We've classified it as EXTJS-16617 . We encourage you to continue the discussion and to find an acceptable workaround while we work on a permanent fix.
  1. #1
    Sencha User
    Join Date
    Feb 2014
    Posts
    20

    Default Mouse events don't work on Pie charts (sencha-chart) with only one slice visibile

    Ext version tested:
    • Ext 5.1.0.107
    • Ext 5.0.0.970




    Browser versions tested against:
    • Chrome
    • IE9
    • IE10




    DOCTYPE tested against:



    Description:
    • Mouse events don't work on Pie charts (sencha-chart) with only one slice visibile
    • No tooltip showing
    • No itemclick fires if item is clicked
    • This happens with stores containing only one record
    • This happens too with stores having more than one record but only one showed (after deselecting categories in legend)




    Steps to reproduce the problem:




    The result that was expected:
    • Tooltip on mouse over item, and itemclick if clicked




    The result that occurs instead:

    • No tooltip and no itemclick event fired

    I think that the problem is in :
    /ext/packages/sencha-charts/src/chart/series/Pie.js
    getItemForPoint and betweenAngle

  2. #2
    Sencha User joel.watson's Avatar
    Join Date
    Nov 2014
    Posts
    3,120

    Default

    Thanks for the report! I have opened a bug in our bug tracker.

  3. #3
    Sencha User
    Join Date
    Feb 2014
    Posts
    20

    Default

    thank you,
    are there any news? or a workaround?
    thank you in advance

  4. #4
    Sencha User
    Join Date
    Jan 2015
    Posts
    104

    Default

    Hi guys,I just hit the same bug, and didn't fin any workaround. If you have any ideas, they will be more than welcomed !

  5. #5
    Sencha User
    Join Date
    Feb 2014
    Posts
    20

    Default

    I tried fixing it modifying "/ext/packages/sencha-charts/src/chart/series/Pie.js"
    row:
    if (me.betweenAngle(direction, attr.startAngle, attr.endAngle)) {

    to:
    if (records.length==1||(attr.startAngle==0&&attr.endAngle>=me.getTotalAngle()-0.0001)||me.betweenAngle(direction, attr.startAngle, attr.endAngle)) {

    it's not so clean... but it seems to work

  6. #6
    Sencha User
    Join Date
    Jan 2015
    Posts
    104

    Default

    Thanks a lot Bartoleo, I'll try your code tomorrow morning and will update this thread ! Thanks a lot !

  7. #7
    Sencha User
    Join Date
    Jan 2015
    Posts
    104

    Default

    Bartoleo your workaround works nice !! Thanks again buddy !

  8. #8
    Sencha User
    Join Date
    Feb 2014
    Posts
    20

    Default

    I hope this will be fixed with 'better' solution

  9. #9
    Sencha Premium User westy's Avatar
    Join Date
    Feb 2009
    Location
    Bath, UK
    Posts
    1,038

    Default

    Hi guys,

    Took me a while to get my head around the code... had to write a version with variable names that made sense.

    I think I have a better fix.

    Code:
    Ext.define('Altus.overrides.chart.series.Pie', {
        override: 'Ext.chart.series.Pie',
        
        
        /**
             * Added a version with named parameters, so can figure out what is going on when only
             * have a single segment.
             * @param  {Number} angle The angle we are trying to determine whether is in between start and end.
             * @param  {Number} startAngle The startAngle for the test.
             * @param  {Number} endAngle The endAngle for the test.
             * @return {Boolean} true if the angle is between start and end, false otherwise.
             */
        betweenAngle: function (angle, startAngle, endAngle) {
            var twoPi = Math.PI * 2,
                offset = this.rotationOffset;
            
            
            if (!this.getClockwise()) {
                // If working anti-clockwise then need to reverse some values...
                angle *= -1;
                startAngle *= -1;
                endAngle *= -1;
                
                
                // Rotate start/end by our rotation offset (anti-clockwise)
                startAngle -= offset;
                endAngle -= offset;
            } else {
                // Rotate start/end by our rotation offset (clockwise)
                startAngle += offset;
                endAngle += offset;
            }
            
            
            endAngle -= startAngle;
            angle -= startAngle;
            
            
            // Ensure within 2 pi
            angle %= twoPi;
            endAngle %= twoPi;
            
            
            // Ensure angles are both +ve
            angle += twoPi;
            endAngle += twoPi;
            angle %= twoPi;
            endAngle %= twoPi;
            
            
            // Cope with start and end being at same point
            return endAngle === 0 || (angle < endAngle);
        }
    });
    Seems to work for me.

    Here's an updated version of the fiddle: https://fiddle.sencha.com/#fiddle/itu

    Cheers,
    Westy
    Product Architect
    Altus Ltd.

  10. #10
    Sencha Premium User westy's Avatar
    Join Date
    Feb 2009
    Location
    Bath, UK
    Posts
    1,038

    Default

    Ok, not quite right due to the wonders of floating point numbers on computers.

    Updated to be:
    Code:
            /**
             * Added a version with named parameters, so can figure out what is going on when only
             * have a single segment.
             * @param  {Number} angle The angle we are trying to determine whether is in between start and end.
             * @param  {Number} startAngle The startAngle for the test.
             * @param  {Number} endAngle The endAngle for the test.
             * @return {Boolean} true if the angle is between start and end, false otherwise.
             */
            betweenAngle: function (angle, startAngle, endAngle) {
                var twoPi = Math.PI * 2,
                    offset = this.rotationOffset;
    
    
                if (!this.getClockwise()) {
                    // If working anti-clockwise then need to reverse some values...
                    angle *= -1;
                    startAngle *= -1;
                    endAngle *= -1;
    
    
                    // Rotate start/end by our rotation offset (anti-clockwise)
                    startAngle -= offset;
                    endAngle -= offset;
                } else {
                    // Rotate start/end by our rotation offset (clockwise)
                    startAngle += offset;
                    endAngle += offset;
                }
    
    
                endAngle -= startAngle;
                angle -= startAngle;
    
    
                // Ensure within 2 pi
                angle %= twoPi;
                endAngle %= twoPi;
    
    
                // Ensure angles are both +ve
                angle += twoPi;
                endAngle += twoPi;
                angle %= twoPi;
                endAngle %= twoPi;
    
    
                // Cope with start and end being at same point (or close enough)
                return (angle < endAngle) || Altus.Number.equals(endAngle, 0);
            }
    Where Altus.Number is (slightly modified):
    Code:
    Ext.define('Altus.Number', {
    
    
        singleton: true,
    
    
        /**
         * The minimum machine epsilon value to use.
         * See: http://stackoverflow.com/a/2411661/1097608
         * @type {Number}
         */
        minimumEpsilon: 1e-15,
    
    
        /**
         * Compares two numbers, returning whether they are deemed to be "equal enough".
         * If undefined or null is passed in the value is taken to be zero.
         * If something that is not a Number is passed in an attempt to convert is made, using parseFloat.
         * If either are NaN, or do not parse an error is thrown.
         * @param {Number} x The first number being compared.
         * @param {Number} y The second number being compared.
         * @return {Boolean}
         */
        equals: function(x, y) {
            // Cope with undefined/null.
            x = x || 0;
            y = y || 0;
    
    
            // Cope with numbers as strings being passed in
            if (!Ext.isNumber(x)) {
                x = parseFloat(x);
            }
            if (!Ext.isNumber(y)) {
                y = parseFloat(y);
            }
    
    
            // Check against unparseable strings or NaN being passed in.
            if (isNaN(x)) {
                Ext.Error.raise('X is not a number: ' + x);
            }
            if (isNaN(y)) {
                Ext.Error.raise('Y is not a number: ' + y);
            }
    
    
            return Math.abs(x - y) <= Altus.Number.computeEpsilonForComparison(x, y);
        },
    
    
        // FIXME: greaterThan, lessThan needed?
    
    
        /**
         * Computes the epsilon to use for comparing two floating point numbers.
         * @param {Number} x The first number being compared.
         * @param {Number} y The second number being compared.
         * @return {Number} The epsilon to use for the comparison.
         */
        computeEpsilonForComparison: function(x, y) {
            return Math.max(Math.abs(x), Math.abs(y), 1) * Altus.Number.minimumEpsilon;
        }
    });
    Hope that helps.

    Westy
    Product Architect
    Altus Ltd.

Page 1 of 2 12 LastLast

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •