1

I use this SVG Pie Chart on my website. It has a pretty animation on load (as you can see by running the snippet below) but I don't want it to be visible by default. I want it show up with its animation on a button click after the page is loaded.

Its probably controlled by triggerAnimation(); function in pie.js but it gets called automatically when the page is loaded as the script is external.

 <!-- Pie chart JS-->

<script src="js/pie.js"></script>

How can I control the function from a button click? Help would be appreciated.

Below is a live snippet of the pie chart :

PIE.js, PIE.css and PIE.html

$(function(){
  $("#pieChart").drawPieChart([
    { title: "Tokyo",         value : 180,  color: "#02B3E7" },
    { title: "San Francisco", value:  60,   color: "#CFD3D6" },
    { title: "London",        value : 50,   color: "#736D79" },
    { title: "New York",      value:  30,   color: "#776068" },
    { title: "Sydney",        value : 20,   color: "#EB0D42" },
    { title: "Berlin",        value : 20,   color: "#FFEC62" },
    { title: "Osaka",         value : 7,    color: "#04374E" }
  ]);
});

/*!
 * jquery.drawPieChart.js
 * Version: 0.3(Beta)
 * Inspired by Chart.js(http://www.chartjs.org/)
 *
 * Copyright 2013 hiro
 * https://github.com/githiro/drawPieChart
 * Released under the MIT license.
 */
;(function($, undefined) {
  $.fn.drawPieChart = function(data, options) {
    var $this = this,
      W = $this.width(),
      H = $this.height(),
      centerX = W/2,
      centerY = H/2,
      cos = Math.cos,
      sin = Math.sin,
      PI = Math.PI,
      settings = $.extend({
        segmentShowStroke : true,
        segmentStrokeColor : "#fff",
        segmentStrokeWidth : 1,
        baseColor: "#fff",
        baseOffset: 15,
        edgeOffset: 30,//offset from edge of $this
        pieSegmentGroupClass: "pieSegmentGroup",
        pieSegmentClass: "pieSegment",
        lightPiesOffset: 12,//lighten pie's width
        lightPiesOpacity: .3,//lighten pie's default opacity
        lightPieClass: "lightPie",
        animation : true,
        animationSteps : 90,
        animationEasing : "easeInOutExpo",
        tipOffsetX: -15,
        tipOffsetY: -45,
        tipClass: "pieTip",
        beforeDraw: function(){  },
        afterDrawed : function(){  },
        onPieMouseenter : function(e,data){  },
        onPieMouseleave : function(e,data){  },
        onPieClick : function(e,data){  }
      }, options),
      animationOptions = {
        linear : function (t){
          return t;
        },
        easeInOutExpo: function (t) {
          var v = t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t;
          return (v>1) ? 1 : v;
        }
      },
      requestAnimFrame = function(){
        return window.requestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.oRequestAnimationFrame ||
          window.msRequestAnimationFrame ||
          function(callback) {
            window.setTimeout(callback, 1000 / 60);
          };
      }();

    var $wrapper = $('<svg width="' + W + '" height="' + H + '" viewBox="0 0 ' + W + ' ' + H + '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>').appendTo($this);
    var $groups = [],
        $pies = [],
        $lightPies = [],
        easingFunction = animationOptions[settings.animationEasing],
        pieRadius = Min([H/2,W/2]) - settings.edgeOffset,
        segmentTotal = 0;

    //Draw base circle
    var drawBasePie = function(){
      var base = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
      var $base = $(base).appendTo($wrapper);
      base.setAttribute("cx", centerX);
      base.setAttribute("cy", centerY);
      base.setAttribute("r", pieRadius+settings.baseOffset);
      base.setAttribute("fill", settings.baseColor);
    }();

    //Set up pie segments wrapper
    var pathGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
    var $pathGroup = $(pathGroup).appendTo($wrapper);
    $pathGroup[0].setAttribute("opacity",0);

    //Set up tooltip
    var $tip = $('<div class="' + settings.tipClass + '" />').appendTo('body').hide(),
      tipW = $tip.width(),
      tipH = $tip.height();

    for (var i = 0, len = data.length; i < len; i++){
      segmentTotal += data[i].value;
      var g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
      g.setAttribute("data-order", i);
      g.setAttribute("class", settings.pieSegmentGroupClass);
      $groups[i] = $(g).appendTo($pathGroup);
      $groups[i]
        .on("mouseenter", pathMouseEnter)
        .on("mouseleave", pathMouseLeave)
        .on("mousemove", pathMouseMove)
        .on("click", pathClick);

      var p = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      p.setAttribute("stroke-width", settings.segmentStrokeWidth);
      p.setAttribute("stroke", settings.segmentStrokeColor);
      p.setAttribute("stroke-miterlimit", 2);
      p.setAttribute("fill", data[i].color);
      p.setAttribute("class", settings.pieSegmentClass);
      $pies[i] = $(p).appendTo($groups[i]);

      var lp = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      lp.setAttribute("stroke-width", settings.segmentStrokeWidth);
      lp.setAttribute("stroke", settings.segmentStrokeColor);
      lp.setAttribute("stroke-miterlimit", 2);
      lp.setAttribute("fill", data[i].color);
      lp.setAttribute("opacity", settings.lightPiesOpacity);
      lp.setAttribute("class", settings.lightPieClass);
      $lightPies[i] = $(lp).appendTo($groups[i]);
    }

    settings.beforeDraw.call($this);
    //Animation start
    triggerAnimation();

    function pathMouseEnter(e){
      var index = $(this).data().order;
      $tip.text(data[index].title + ": " + data[index].value).fadeIn(200);
      if ($groups[index][0].getAttribute("data-active") !== "active"){
        $lightPies[index].animate({opacity: .8}, 180);
      }
      settings.onPieMouseenter.apply($(this),[e,data]);
    }
    function pathMouseLeave(e){
      var index = $(this).data().order;
      $tip.hide();
      if ($groups[index][0].getAttribute("data-active") !== "active"){
        $lightPies[index].animate({opacity: settings.lightPiesOpacity}, 100);
      }
      settings.onPieMouseleave.apply($(this),[e,data]);
    }
    function pathMouseMove(e){
      $tip.css({
        top: e.pageY + settings.tipOffsetY,
        left: e.pageX - $tip.width() / 2 + settings.tipOffsetX
      });
    }
    function pathClick(e){
      var index = $(this).data().order;
      var targetGroup = $groups[index][0];
      for (var i = 0, len = data.length; i < len; i++){
        if (i === index) continue;
        $groups[i][0].setAttribute("data-active","");
        $lightPies[i].css({opacity: settings.lightPiesOpacity});
      }
      if (targetGroup.getAttribute("data-active") === "active"){
        targetGroup.setAttribute("data-active","");
        $lightPies[index].css({opacity: .8});
      } else {
        targetGroup.setAttribute("data-active","active");
        $lightPies[index].css({opacity: 1});
      }
      settings.onPieClick.apply($(this),[e,data]);
    }
    function drawPieSegments (animationDecimal){
      var startRadius = -PI/2,//-90 degree
          rotateAnimation = 1;
      if (settings.animation) {
        rotateAnimation = animationDecimal;//count up between0~1
      }

      $pathGroup[0].setAttribute("opacity",animationDecimal);

      //draw each path
      for (var i = 0, len = data.length; i < len; i++){
        var segmentAngle = rotateAnimation * ((data[i].value/segmentTotal) * (PI*2)),//start radian
            endRadius = startRadius + segmentAngle,
            largeArc = ((endRadius - startRadius) % (PI * 2)) > PI ? 1 : 0,
            startX = centerX + cos(startRadius) * pieRadius,
            startY = centerY + sin(startRadius) * pieRadius,
            endX = centerX + cos(endRadius) * pieRadius,
            endY = centerY + sin(endRadius) * pieRadius,
            startX2 = centerX + cos(startRadius) * (pieRadius + settings.lightPiesOffset),
            startY2 = centerY + sin(startRadius) * (pieRadius + settings.lightPiesOffset),
            endX2 = centerX + cos(endRadius) * (pieRadius + settings.lightPiesOffset),
            endY2 = centerY + sin(endRadius) * (pieRadius + settings.lightPiesOffset);
        var cmd = [
          'M', startX, startY,//Move pointer
          'A', pieRadius, pieRadius, 0, largeArc, 1, endX, endY,//Draw outer arc path
          'L', centerX, centerY,//Draw line to the center.
          'Z'//Cloth path
        ];
        var cmd2 = [
          'M', startX2, startY2,
          'A', pieRadius + settings.lightPiesOffset, pieRadius + settings.lightPiesOffset, 0, largeArc, 1, endX2, endY2,//Draw outer arc path
          'L', centerX, centerY,
          'Z'
        ];
        $pies[i][0].setAttribute("d",cmd.join(' '));
        $lightPies[i][0].setAttribute("d", cmd2.join(' '));
        startRadius += segmentAngle;
      }
    }

    var animFrameAmount = (settings.animation)? 1/settings.animationSteps : 1,//if settings.animationSteps is 10, animFrameAmount is 0.1
        animCount =(settings.animation)? 0 : 1;
    function triggerAnimation(){
      if (settings.animation) {
        requestAnimFrame(animationLoop);
      } else {
        drawPieSegments(1);
      }
    }
    function animationLoop(){
      animCount += animFrameAmount;//animCount start from 0, after "settings.animationSteps"-times executed, animCount reaches 1.
      drawPieSegments(easingFunction(animCount));
      if (animCount < 1){
        requestAnimFrame(arguments.callee);
      } else {
        settings.afterDrawed.call($this);
      }
    }
    function Max(arr){
      return Math.max.apply(null, arr);
    }
    function Min(arr){
      return Math.min.apply(null, arr);
    }
    return $this;
  };
})(jQuery);
.chart {
  position: absolute;
  width: 250px;
  height: 250px;
  top: 100%;
  left: 50%;
  margin: -225px 0 0 -225px;
}
.pieTip {
  position: absolute;
  float: left;
  min-width: 30px;
  max-width: 300px;
  padding: 5px 18px 6px;
  border-radius: 2px;
  background: rgba(255,255,255,.97);
  color: #444;
  font-size: 19px;
  text-shadow: 0 1px 0 #fff;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.3;
  letter-spacing: .06em;
  box-shadow: 0 0 3px rgba(0,0,0,0.2), 0 1px 2px rgba(0,0,0,0.5);
  -webkit-transform: all .3s;
     -moz-transform: all .3s;
      -ms-transform: all .3s;
       -o-transform: all .3s;
          transform: all .3s;
  pointer-events: none;
}
.pieTip:after {
      position: absolute;
      left: 50%;
      bottom: -6px;
      content: "";
      height: 0;
      margin: 0 0 0 -6px;
      border-right: 5px solid transparent;
      border-left: 5px solid transparent;
      border-top: 6px solid rgba(255,255,255,.95);
      line-height: 0;
}
.chart path { cursor: pointer; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pieChart" class="chart"></div>

1
  • instead of calling $("#pieChart").drawPieChart() on page load, why don't you do that on button click? Commented Sep 1, 2016 at 15:44

1 Answer 1

1

Call .drawPieChart() on button click event:

$(function() {
  $('button').click(function() {
    // Clean up old chart contents
    $("#pieChart").empty();
    // Clean up Tooltips created by chart
    $('.pieTip').remove();
    // Draw a new chart
    $("#pieChart").drawPieChart([{
      title: "Tokyo",
      value: 180,
      color: "#02B3E7"
    }, {
      title: "San Francisco",
      value: 60,
      color: "#CFD3D6"
    }, {
      title: "London",
      value: 50,
      color: "#736D79"
    }, {
      title: "New York",
      value: 30,
      color: "#776068"
    }, {
      title: "Sydney",
      value: 20,
      color: "#EB0D42"
    }, {
      title: "Berlin",
      value: 20,
      color: "#FFEC62"
    }, {
      title: "Osaka",
      value: 7,
      color: "#04374E"
    }]);
  });
});

/*!
 * jquery.drawPieChart.js
 * Version: 0.3(Beta)
 * Inspired by Chart.js(http://www.chartjs.org/)
 *
 * Copyright 2013 hiro
 * https://github.com/githiro/drawPieChart
 * Released under the MIT license.
 */
;
(function($, undefined) {
  $.fn.drawPieChart = function(data, options) {
    var $this = this,
      W = $this.width(),
      H = $this.height(),
      centerX = W / 2,
      centerY = H / 2,
      cos = Math.cos,
      sin = Math.sin,
      PI = Math.PI,
      settings = $.extend({
        segmentShowStroke: true,
        segmentStrokeColor: "#fff",
        segmentStrokeWidth: 1,
        baseColor: "#fff",
        baseOffset: 15,
        edgeOffset: 30, //offset from edge of $this
        pieSegmentGroupClass: "pieSegmentGroup",
        pieSegmentClass: "pieSegment",
        lightPiesOffset: 12, //lighten pie's width
        lightPiesOpacity: .3, //lighten pie's default opacity
        lightPieClass: "lightPie",
        animation: true,
        animationSteps: 90,
        animationEasing: "easeInOutExpo",
        tipOffsetX: -15,
        tipOffsetY: -45,
        tipClass: "pieTip",
        beforeDraw: function() {},
        afterDrawed: function() {},
        onPieMouseenter: function(e, data) {},
        onPieMouseleave: function(e, data) {},
        onPieClick: function(e, data) {}
      }, options),
      animationOptions = {
        linear: function(t) {
          return t;
        },
        easeInOutExpo: function(t) {
          var v = t < .5 ? 8 * t * t * t * t : 1 - 8 * (--t) * t * t * t;
          return (v > 1) ? 1 : v;
        }
      },
      requestAnimFrame = function() {
        return window.requestAnimationFrame ||
          window.webkitRequestAnimationFrame ||
          window.mozRequestAnimationFrame ||
          window.oRequestAnimationFrame ||
          window.msRequestAnimationFrame ||
          function(callback) {
            window.setTimeout(callback, 1000 / 60);
          };
      }();

    var $wrapper = $('<svg width="' + W + '" height="' + H + '" viewBox="0 0 ' + W + ' ' + H + '" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>').appendTo($this);
    var $groups = [],
      $pies = [],
      $lightPies = [],
      easingFunction = animationOptions[settings.animationEasing],
      pieRadius = Min([H / 2, W / 2]) - settings.edgeOffset,
      segmentTotal = 0;

    //Draw base circle
    var drawBasePie = function() {
      var base = document.createElementNS('http://www.w3.org/2000/svg', 'circle');
      var $base = $(base).appendTo($wrapper);
      base.setAttribute("cx", centerX);
      base.setAttribute("cy", centerY);
      base.setAttribute("r", pieRadius + settings.baseOffset);
      base.setAttribute("fill", settings.baseColor);
    }();

    //Set up pie segments wrapper
    var pathGroup = document.createElementNS('http://www.w3.org/2000/svg', 'g');
    var $pathGroup = $(pathGroup).appendTo($wrapper);
    $pathGroup[0].setAttribute("opacity", 0);

    //Set up tooltip
    var $tip = $('<div class="' + settings.tipClass + '" />').appendTo('body').hide(),
      tipW = $tip.width(),
      tipH = $tip.height();

    for (var i = 0, len = data.length; i < len; i++) {
      segmentTotal += data[i].value;
      var g = document.createElementNS('http://www.w3.org/2000/svg', 'g');
      g.setAttribute("data-order", i);
      g.setAttribute("class", settings.pieSegmentGroupClass);
      $groups[i] = $(g).appendTo($pathGroup);
      $groups[i]
        .on("mouseenter", pathMouseEnter)
        .on("mouseleave", pathMouseLeave)
        .on("mousemove", pathMouseMove)
        .on("click", pathClick);

      var p = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      p.setAttribute("stroke-width", settings.segmentStrokeWidth);
      p.setAttribute("stroke", settings.segmentStrokeColor);
      p.setAttribute("stroke-miterlimit", 2);
      p.setAttribute("fill", data[i].color);
      p.setAttribute("class", settings.pieSegmentClass);
      $pies[i] = $(p).appendTo($groups[i]);

      var lp = document.createElementNS('http://www.w3.org/2000/svg', 'path');
      lp.setAttribute("stroke-width", settings.segmentStrokeWidth);
      lp.setAttribute("stroke", settings.segmentStrokeColor);
      lp.setAttribute("stroke-miterlimit", 2);
      lp.setAttribute("fill", data[i].color);
      lp.setAttribute("opacity", settings.lightPiesOpacity);
      lp.setAttribute("class", settings.lightPieClass);
      $lightPies[i] = $(lp).appendTo($groups[i]);
    }

    settings.beforeDraw.call($this);
    //Animation start
    triggerAnimation();

    function pathMouseEnter(e) {
      var index = $(this).data().order;
      $tip.text(data[index].title + ": " + data[index].value).fadeIn(200);
      if ($groups[index][0].getAttribute("data-active") !== "active") {
        $lightPies[index].animate({
          opacity: .8
        }, 180);
      }
      settings.onPieMouseenter.apply($(this), [e, data]);
    }

    function pathMouseLeave(e) {
      var index = $(this).data().order;
      $tip.hide();
      if ($groups[index][0].getAttribute("data-active") !== "active") {
        $lightPies[index].animate({
          opacity: settings.lightPiesOpacity
        }, 100);
      }
      settings.onPieMouseleave.apply($(this), [e, data]);
    }

    function pathMouseMove(e) {
      $tip.css({
        top: e.pageY + settings.tipOffsetY,
        left: e.pageX - $tip.width() / 2 + settings.tipOffsetX
      });
    }

    function pathClick(e) {
      var index = $(this).data().order;
      var targetGroup = $groups[index][0];
      for (var i = 0, len = data.length; i < len; i++) {
        if (i === index) continue;
        $groups[i][0].setAttribute("data-active", "");
        $lightPies[i].css({
          opacity: settings.lightPiesOpacity
        });
      }
      if (targetGroup.getAttribute("data-active") === "active") {
        targetGroup.setAttribute("data-active", "");
        $lightPies[index].css({
          opacity: .8
        });
      } else {
        targetGroup.setAttribute("data-active", "active");
        $lightPies[index].css({
          opacity: 1
        });
      }
      settings.onPieClick.apply($(this), [e, data]);
    }

    function drawPieSegments(animationDecimal) {
      var startRadius = -PI / 2, //-90 degree
        rotateAnimation = 1;
      if (settings.animation) {
        rotateAnimation = animationDecimal; //count up between0~1
      }

      $pathGroup[0].setAttribute("opacity", animationDecimal);

      //draw each path
      for (var i = 0, len = data.length; i < len; i++) {
        var segmentAngle = rotateAnimation * ((data[i].value / segmentTotal) * (PI * 2)), //start radian
          endRadius = startRadius + segmentAngle,
          largeArc = ((endRadius - startRadius) % (PI * 2)) > PI ? 1 : 0,
          startX = centerX + cos(startRadius) * pieRadius,
          startY = centerY + sin(startRadius) * pieRadius,
          endX = centerX + cos(endRadius) * pieRadius,
          endY = centerY + sin(endRadius) * pieRadius,
          startX2 = centerX + cos(startRadius) * (pieRadius + settings.lightPiesOffset),
          startY2 = centerY + sin(startRadius) * (pieRadius + settings.lightPiesOffset),
          endX2 = centerX + cos(endRadius) * (pieRadius + settings.lightPiesOffset),
          endY2 = centerY + sin(endRadius) * (pieRadius + settings.lightPiesOffset);
        var cmd = [
          'M', startX, startY, //Move pointer
          'A', pieRadius, pieRadius, 0, largeArc, 1, endX, endY, //Draw outer arc path
          'L', centerX, centerY, //Draw line to the center.
          'Z' //Cloth path
        ];
        var cmd2 = [
          'M', startX2, startY2,
          'A', pieRadius + settings.lightPiesOffset, pieRadius + settings.lightPiesOffset, 0, largeArc, 1, endX2, endY2, //Draw outer arc path
          'L', centerX, centerY,
          'Z'
        ];
        $pies[i][0].setAttribute("d", cmd.join(' '));
        $lightPies[i][0].setAttribute("d", cmd2.join(' '));
        startRadius += segmentAngle;
      }
    }

    var animFrameAmount = (settings.animation) ? 1 / settings.animationSteps : 1, //if settings.animationSteps is 10, animFrameAmount is 0.1
      animCount = (settings.animation) ? 0 : 1;

    function triggerAnimation() {
      if (settings.animation) {
        requestAnimFrame(animationLoop);
      } else {
        drawPieSegments(1);
      }
    }

    function animationLoop() {
      animCount += animFrameAmount; //animCount start from 0, after "settings.animationSteps"-times executed, animCount reaches 1.
      drawPieSegments(easingFunction(animCount));
      if (animCount < 1) {
        requestAnimFrame(arguments.callee);
      } else {
        settings.afterDrawed.call($this);
      }
    }

    function Max(arr) {
      return Math.max.apply(null, arr);
    }

    function Min(arr) {
      return Math.min.apply(null, arr);
    }
    return $this;
  };
})(jQuery);
.chart {
  position: absolute;
  width: 250px;
  height: 250px;
  top: 100%;
  left: 50%;
  margin: -225px 0 0 -225px;
}
.pieTip {
  position: absolute;
  float: left;
  min-width: 30px;
  max-width: 300px;
  padding: 5px 18px 6px;
  border-radius: 2px;
  background: rgba(255, 255, 255, .97);
  color: #444;
  font-size: 19px;
  text-shadow: 0 1px 0 #fff;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.3;
  letter-spacing: .06em;
  box-shadow: 0 0 3px rgba(0, 0, 0, 0.2), 0 1px 2px rgba(0, 0, 0, 0.5);
  -webkit-transform: all .3s;
  -moz-transform: all .3s;
  -ms-transform: all .3s;
  -o-transform: all .3s;
  transform: all .3s;
  pointer-events: none;
}
.pieTip:after {
  position: absolute;
  left: 50%;
  bottom: -6px;
  content: "";
  height: 0;
  margin: 0 0 0 -6px;
  border-right: 5px solid transparent;
  border-left: 5px solid transparent;
  border-top: 6px solid rgba(255, 255, 255, .95);
  line-height: 0;
}
.chart path {
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="pieChart" class="chart"></div>
<button>Animate</button>

Sign up to request clarification or add additional context in comments.

2 Comments

Always works for me... are you sure you don't have a separate issue? I found that the tool tips were not getting cleaned up and edited the answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.