【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集

質問失礼致します。

html5を使って複雑な円グラフを描画したいのですが、できなくて困っています。
Raphael.jsを使って円グラフを書いていますが、添付した画像のような円グラフはどうつくれば良いかわかりません。
どなたか知識をご教授頂けると幸いでございます。

「html5で複雑な円グラフを描画」の質問画像

A 回答 (13件中1~10件)

html5ならcanvasが使えるのでは?



扇形を作るものを用意しておけば、それで事足りそう。
html5もcanvasも使ったことはありませんが、お勉強のためにサンプルを。

参考にしたサイト
https://developer.mozilla.org/ja/Canvas_tutorial


fx6.0でしか確認していません。
数値の意味が不明でしたので、角度などは適当です。
(全角空白は半角に)

<!DOCTYPE html>
<html lang="ja">
<head>
<title>sample</title>
</head>
<body>

<canvas id="graph" width="400" height="400"></canvas>

<script type="text/javascript">
(function(){

 var fanShape = (function(rad){
  return function(ctx, r, ang1, ang2, col, frame){
   ctx.fillStyle = col;
   ctx.beginPath();
   ctx.moveTo(0, 0);
   ctx.arc(0, 0, r, rad(ang1), rad(ang2));
   ctx.fill();
   if(frame){
    ctx.closePath();
    ctx.stroke();
   }
  }
 })(function(a){
  return Math.PI*(a-90)/180;
 });

 var context, graph = document.getElementById("graph");
 if(graph.getContext && (context = graph.getContext("2d"))){
  context.translate(200, 200);

  fanShape(context, 180, 0, 360, "#ddd");
  fanShape(context, 160, 0, 10, "#0c0", true);
  fanShape(context, 90, 10, 240, "#c00", true);
  fanShape(context, 60, 240, 360, "#00c", true);

 }
})();
</script>
</body>
</html>
「html5で複雑な円グラフを描画」の回答画像3
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。正常に動きました!
コードも非常に簡潔でしたので、取り入れてみたいと思ってます!ちなみにNo2さんのほうにも記載させて頂きましたが、
http://elycharts.com/examples#example_p1
こうしたサンプルのように、ひとつひとつの扇形に対してアニメーションもつけたいんです。。
また、ひとつひとつの扇形をオフジェクトとして取り出して、クリックしたらajaxを使って該当データを引っ張ってきて、ツールチップに表示、こうしたことをやっていきたいとおもっているんですね。
どうかfujillin様からも知識をご教授頂けないでしょうか?

お礼日時:2011/11/16 10:47

[ANo.10] 改変


まじめに SVG 要素でアニメーションバージョン。

https://ideone.com/l5Rjx

Firefox 8 だと意図したとおりに気持ちわるく動いてくれるけど、
Google Chrome 15 だと、mouseover と mouseout の順番が逆転してヘンテコ。


そういえば、円グラフの項目が一つで 100% のときはどうするか考えてないけど、
やっぱり『動かない』が正解かなぁ?
    • good
    • 0
この回答へのお礼

ありがとうございます。
いまひとつひとつ確認をさせてもらっているのですが、firefox8だとうまくうごきますね!!

100%の場合確かに「動かない」がいいとはおもいますが、他の比率の場合は「動く」ので「動く」で統一しようかなとはおもってます。

お礼日時:2011/11/21 12:45

 


 function PieChart (canvas, ctx, offsetX, offsetY, radius, data) {
  this.canvas = canvas;
  this.ctx = ctx;
  this.offsetX = offsetX;
  this.offsetY = offsetY;
  this.radius = radius;
  this.data = data;
  this.parts = [];
 }
 
 PieChart.prototype.check = function (parm) {
  if (this.canvas === parm.canvas)
   this.parts.forEach (function (p) { p.check (this.x, this.y) }, parm);
 };
 
 
 PieChart.prototype.draw = function () {
  var total = this.data.reduce (function (r, d) { return r + d.value; }, 0);
  var square0 = 0;
  var square1;
  var i = 0;
  var d;
  var obj;
  
  this.parts = [];
  
  while (d = this.data[i++]) {
   square1 = square0 + (360 / 100) * (d.value / total) * 100;
   obj = Arc.create (this.ctx, this.offsetX, this.offsetY, this.radius, square0, square1, d);
   this.parts.push (obj);
   square0 = square1;
  }
 };
 
 
 
 PieChart.create = function (canvas, offsetX, offsetY, radius, data) {
  if (arguments.length < 5)
   return null;
  
  var ctx = canvas.getContext ('2d');
  var chart = new PieChart (canvas, ctx, offsetX, offsetY, radius, data);
  chart.draw ();

  return chart;
 };
 
 this.PieChart = PieChart;
 
 //_______________________
 
 var Manager = new function () {
  this.x = null;
  this.y = null;
  this.stock = [];
 };
 
 
 Manager.check = function (e) {
  var offset = getElementPosition (e);
  var parm = { canvas: e, x: this.x - offset.x, y: this.y - offset.y };
  
  this.stock.forEach (function (s) { s.check (this); }, parm);
 };
 
 
 Manager.add = function (obj) {
  this.stock.push (obj);
 };
 
 
 Manager.handleEvent = function (event) {
  var e = event.target;
  var v = e.ownerDocument.defaultView;
  var offset = { x: null, y: null };
  
  switch (event.type) {
  case 'mousemove' :
  case 'mouseover' :
   this.x = event.clientX + v.pageXOffset;
   this.y = event.clientY + v.pageYOffset;
   if ('CANVAS' === e.nodeName) {
    this.check (e);
   }
  
   break;
  
  case 'click' :
   break;
  }
 }

 document.addEventListener ('mousemove', Manager, false);
 document.addEventListener ('mouseover', Manager, false);
 document.addEventListener ('click', Manager, false);
 
 this.Manager = Manager;
})();

//__________________________

var data = [
 { caption: 'A', value: 512, radius: 90, color: '#080' },
 { caption: 'B', value: 6534, radius: 60, color: '#f00' },
 { caption: 'C', value: 3056, radius: 30, color: '#008' }
];
var data2 = [
 { caption: 'A', value: 12, radius: 40, color: '#080' },
 { caption: 'B', value: 34, radius: 80, color: '#f00' },
 { caption: 'C', value: 56, radius: 20, color: '#008' }
];

var canvas = document.getElementById ('HOGE');

Manager.add (PieChart.create (canvas, 200, 200, 180, data));
Manager.add (PieChart.create (canvas, 400, 200, 180, data2));

</script>

ぜんかくくうはくは、はんかくに。
そして、「弧」のぶぶんは、いつものようにちからつきてぐだぐだです。
わたしも、Fujillinさんとどうよう、みようみまねでかいているので、ごしどうのほど・・・
    • good
    • 0
この回答へのお礼

ご丁寧にありがとうございます。
週末にかけてみなさんの書いて頂いたコードをじっくり勉強させて頂きます。
ありがとうございます。

お礼日時:2011/11/19 05:50

かなりじかんをさいて canvas でかいてみた。


ぜんたいをかいてけすのではなく、うわがきでけしているのですが、ごみがのこります。
くにくのさくとして、せんをふとくしてごまかしています。
たぶん、ながいのでぶんかつです。

<!DOCTYPE html>
<html lang="ja">
<title>Test</title>
<meta charset="utf-8">
<style>
 canvas { background : #FFC; }
</style>
<body>
<canvas id="HOGE" width="800" height="400">
 canvas による描画
</canvas>

<script>

(function () {
 var DEG = Math.PI / 180;
 var HOVER_SCALE = 1.5;
 var HOVER_MOVE = 20; //px
 var HOVER_STEP = 10;
 
 function getElementPosition (e) {
  for (var x = 0, y = 0; e; e = e.offsetParent) {
   x += e.offsetLeft;
   y += e.offsetTop;
  }
  return { 'x': x, 'y': y };
 }

 
 function Arc (ctx, x, y, r, sq0, sq1, data) {
  this.ctx = ctx;
  this.x = x;
  this.y = y;
  this.r = r;
  this.sq0 = sq0;
  this.sq1 = sq1;
  this.sq2 = (sq0 + sq1) / 2;
  this.data = data;
  this.timerId = null;
  this.direction = 0;
  this.scale = 1;
 }
 
 Arc.prototype.check = function (x, y) {
  var result;
  var ctx = this.ctx;
  
  ctx.save ();
   ctx.beginPath ();
   this.trace ();
   result = ctx.isPointInPath (x, y);
   ctx.closePath ();
  ctx.restore ();
  
  (result)
  ? this.focus ()
  : this.focusout ();
 };
 
 Arc.prototype.trace = function () {
  var ctx = this.ctx;
  ctx.translate (this.x, this.y);
  ctx.scale (this.scale, this.scale);
  ctx.moveTo (0,0);
  ctx.arc (0, 0, this.r, this.sq0, this.sq1, false);
 };
 
 Arc.prototype.draw = function () {
  var ctx = this.ctx;
  ctx.save ();
   ctx.fillStyle = this.data.color;
   ctx.strokeStyle = 'black';
   ctx.beginPath ();
   this.trace ();
   ctx.fill ();
   ctx.closePath ();
   ctx.stroke ();
  ctx.restore ();
 };

 Arc.prototype.focus = function () {
  this.direction = 1;
  if (! this.timerId)
   this.timerId = setInterval (changer, 50, this);
 };


 Arc.prototype.focusout = function () {
  this.direction = -1;
  if (! this.timerId)
   this.timerId = setInterval (changer, 50, this);
 };


 function changer (that) {
  var ctx = that.ctx;
  ctx.globalCompositeOperation = 'destination-out';
  ctx.save ();
   ctx.fillStyle = that.data.color;
   ctx.strokeStyle = 'black';
   ctx.lineWidth = 2;
   ctx.beginPath ();
   that.trace ();
   ctx.closePath ();
   ctx.fill ();
   ctx.stroke ();
  ctx.restore ();
  
  that.scale += that.direction * (HOVER_SCALE / HOVER_STEP);
  if (that.scale < 1) {
   that.scale = 1;
   clearInterval (that.timerId);
   that.timerId = null;
  }
  if (HOVER_SCALE < that.scale) {
   that.scale = HOVER_SCALE
   clearInterval (that.timerId);
   that.timerId = null;
  }
  ctx.globalCompositeOperation = 'source-over';
  ctx.save ();
   ctx.fillStyle = that.data.color;
   ctx.strokeStyle = 'black';
   ctx.beginPath ();
   that.trace ();
   ctx.closePath ();
   ctx.fill ();
   ctx.stroke ();
  ctx.restore ();
 }

 
 Arc.create = function (ctx, x, y, r, sq0, sq1, data) {
  var obj = new Arc (ctx, x, y, r * data.radius / 100, (sq0 - 90) * DEG, (sq1 - 90) * DEG, data);
  obj.draw ();
  return obj;
 };
 
 //________________________
    • good
    • 0

ちょっと時間できたから書いてみた。




<svg id="svg" width="150px" height="150px" viewBox="-150 -150 300 300"
     xmlns="http://www.w3.org/2000/svg" version="1.1">

  <script type="text/ecmascript"><![CDATA[
    window.onload = function () {
      var svg = document.getElementById("svg");
      var pie = null;
      
      pie = createPieceOfPie(0, 90, 120, {
          onmouseout:"pie_mouseout(evt);", onmouseover:"pie_mouseover(evt);"
        , fill:"#fcc", stroke:"white", "stroke-width":"2" })
      svg.appendChild(pie);
      pie = createPieceOfPie(90, 60, 100, {
          onmouseout:"pie_mouseout(evt);", onmouseover:"pie_mouseover(evt);"
        , fill:"#ccf", stroke:"white", "stroke-width":"2" })
      svg.appendChild(pie);
      pie = createPieceOfPie(150, 30, 80, {
          onmouseout:"pie_mouseout(evt);", onmouseover:"pie_mouseover(evt);"
        , fill:"#cec", stroke:"white", "stroke-width":"2" })
      svg.appendChild(pie);
      pie = createPieceOfPie(180, 180, 60, {
          onmouseout:"pie_mouseout(evt);", onmouseover:"pie_mouseover(evt);"
        , fill:"#ccc", stroke:"white", "stroke-width":"2" })
      svg.appendChild(pie);
    }

    function createSVGElement(tagName, attrs) {
      var path = document.createElementNS("http://www.w3.org/2000/svg",tagName);
      for (var name in attrs) {
        path.setAttribute(name, attrs[name]);
      }
      return path;
    }

    function createPieceOfPie(start, deg, r, attrs) {
      // 座標計算が面倒なので、扇形の頂上を y 軸の - 方向に作成
      var large_arc_flag = (deg > 180)? 1: 0;
      var sweep_flag = 1;
      var rad = Math.PI * deg / 360.0; //角度を半分で計算
      var y = -(r * Math.cos(rad)); //座標系が SVG は特殊なので
      var x = (r * Math.sin(rad)); //座標系が SVG は特殊なので
      attrs["d"] = "M0,0 L" + (-x).toFixed(3) + "," + y.toFixed(3)
          + "A" + r + "," + r
          + " 0 " + large_arc_flag + "," + sweep_flag + " "
          + x.toFixed(3) + "," + y.toFixed(3) + " z";
      var pie = createSVGElement("path", attrs);
      var g = document.createElementNS("http://www.w3.org/2000/svg","g");
      g.appendChild(pie);
      g.setAttribute("transform", "rotate(" + (deg/2+start) + ")");
      return g;
    }

    function pie_mouseover(evt) {
      // 親要素の g を rotate してるから
      // y 座標を -20 だけ移動すれば、
      // 自動で移動して欲しい方向に移動する。
      var pie = evt.target;
      var fill = pie.setAttribute("transform", "translate(0,-20)");
    }
    function pie_mouseout(evt) {
      var pie = evt.target;
      pie.removeAttribute("transform");
    }

  ]]></script>

</svg>
    • good
    • 0
この回答へのお礼

どうもありがとうございます。
一度ちょっとじっくりコードをみさせて頂きます!!

お礼日時:2011/11/18 19:27

#7です。



やっぱりやってました。
動く方向がたまたま0radになると、hoverの動作が設定されませんね。

a == undefined などで判定するとかにしてください。
(多分、他にもあると思うけれど、とりあえず)
    • good
    • 0
この回答へのお礼

細かい例外処理についてはなんとか自分でやってみます!
ありがとうございます!!

お礼日時:2011/11/18 14:22

No5と3です。



たぶん canvas でもいけるとおもっているひとりです。

しかし、そのえんぐらふのぷれぜんほうほうが、いけてないとおもいます。
そもそもえんぐらふは、にかよったあたいをはんべつしにくい。
そのうえ、たかさ(はんけい)のちがいでも、2じてきなすうちをひょうげんしようとしています。
それなのに、まうすがかさなると、おおきくなるのでは、その2じてきすうちがいみをうしなってしまいます。
    • good
    • 0
この回答へのお礼

ご指摘ありがとうございます。
確かにご指摘の通り、この円グラフにこのアニメーションでは意味が薄れてしまいますね。。。
もう一度UIも考えながら作業を進めたいと思います。
babu_babooさんも最後までアドバイス頂きありがとうございました!

お礼日時:2011/11/18 14:24

#3です。



>知識をご教授頂けないでしょうか?
もともと知識がないので、canvasも自分のお勉強のために調べて書いてみた次第。

アニメーションはcanvasでも可能は可能ですが、全体を消して再度書き直すというのが基本みたいです。
それなので、画像そのものをオブジェクトっぽくは扱えない。
多少なりとも似せるなら、各画像を個別のcanvasに描いておいて重ねて表示をすれば、移動(もしかすると拡大・縮小も?←調べていません)程度ならば再描画しなくても可能になるかと思います。
いずれにしても、マウスの位置から画像を特定する部分は作成しないとならないでしょうから、そのあたりが面倒そうですね。


その点、#1様、#4様はさすがに読みが深く、SVGなら描画画像がオブジェクトになっているのでご希望のようなものには適しているかと。
私は、SVGも知らないのでハードルが高いけれど、またまた、にわか勉強で…
とは思ったものの、さすがにドキュメントが多くて、素から作成するには短時間ではとても無理そう。

てーことで、質問者様が御紹介のraphaelに走ってみました。
基本的には、#1様、#4様がご指摘のサイトにサンプルがあるので、半分コピペみたいなものですが…
それなので、詳しく知りたい時は御両者が提示なさっているサイトあたりを参照なさるのがよろしいかと。


<参考サイト>
http://www.w3.org/TR/2003/REC-SVG11-20030114/pat …
(pathのあたりを超斜め読みだけなので、↓は相当にいい加減。きちんと直してください。)


<!DOCTYPE html>
<html lang="ja">
<head>
<title>sample</title>
<script type="text/javascript" src="js/raphael/raphael.js"></script>
</head>
<body>

<div id="holder" style="width:400px; height:400px;"></div>

<script type="text/javascript">
(function(){
// 角度変換関数
var radian = function(a){ return ((a-90) % 360) * Math.PI / 180; }

// アニメーション定義用関数
var move = function(e, a){
 a = a?"t" + 15*Math.cos(a) + " " + 15*Math.sin(a) : "";
 return function(){ e.stop().animate({transform:a}, 100); }
}

// 扇形描画+アニメーション設定
var setFan = function(r, ang1, ang2, color1, color2){
 var x = center.x, y = center.y;
 var LAflag = (ang2 - ang1) > 180;
 var ang = radian((ang1 + ang2) / 2);
 ang1 = radian(ang1);
 ang2 = radian(ang2);

 var f = paper.path(["M", x, y, "l", r*Math.cos(ang1), r*Math.sin(ang1), "A", r, r, 0, +LAflag, 1, x+r*Math.cos(ang2), y+r*Math.sin(ang2), "Z"]);
 f.attr({fill:color1, stroke:color2}).hover(move(f, ang), move(f));
}


// 初期設定
var holder = document.getElementById("holder");
var center = {
 x: parseInt(holder.clientWidth)/2 | 0,
 y: parseInt(holder.clientHeight)/2 | 0
}
var paper = Raphael(holder, center.x*2, center.y*2);


paper.circle(center.x, center.y, 200).attr({fill:"#ddd", stroke:"#ddd"});
setFan(180, 0, 10, "#0c0", "#060");
setFan(140, 10, 240, "#c00", "#600");
setFan(100, 240, 360, "#00c", "#006");

})();
</script>
</body>
</html>
    • good
    • 0
この回答へのお礼

ご丁寧にありがとうございます。
現在は開発に費用をかけられない関係で1から勉強するのは正直厳しい状況です。
このコードをベースに改良を加えていきたいと思います。
本当にご丁寧にありがとうございました!

お礼日時:2011/11/18 14:21

Raphael.js を出してきたからあやしいとおもっけど、やっぱりアニメーションかぁ



「ひとつひとつの扇形をオフジェクトとして取り出して、クリックしたらajaxを使って該当データを引っ張ってきて、ツールチップに表示、こうしたこと」は canvas は得意じゃないから、やっぱり SVG だとおもうよ?

と推してみる。
    • good
    • 0
この回答へのお礼

ご返事ありがとうございます。
アニメーション難しいですね。。

初めてのコンタクトなのに大変恐縮なんですが、
http://elycharts.com/examples#example_p1
のようなアニメーション付きの、しかも今回のようなちょっと特殊な円グラフの、動くコードをなんとか頂けないでしょうか?もしくは作成の手順を、教えて頂けないでしょうか?
本当に簡素なもので大丈夫ですので、知識をご教授下さい。

お礼日時:2011/11/16 16:33

さらに、あにめーしょん!?



あとだしじゃんけんのようなものには・・・
きっと、Fujillin さんならやるっ!とふってみる。(きっとだいすきだろうから^^;)

ところで、えんぐらふの value でぐらふのかくどがへんかするのだけれど、 radius のきじゅんはなに?

さいしゅうてきなもくてきをたっせいするために、うごくこーどがほしいの?
てじゅんだとか、かんがえかた、あるごりずむだとかを、まなびたいの?
    • good
    • 0
この回答へのお礼

ご返事ありがとうございます。

説明が足らず申し訳ありませんでした。。
半径は、90%~100%の人,80%~89%の人,70%~79%の人,60%~69%の人,50%~59%の人,40%~49%の人,30%~39%の人,20%~29%の人,10%~19%の人,0%~9%の人という10個の半径を取ります。なので順に200px,180px,160px,140px,120px,100px,80px,60px,40px,20pxという値を半径にしようと思っています。

質問の量が多すぎるので、ある程度は手順だけでも仕方ないかともおもっていますが
できれば、先ほど載せたサイトの円グラフのようなアニメーションのついた動くコードを頂けたら幸いです。。

お礼日時:2011/11/16 16:23

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!