자바스크립트로 원형게이지에 캔틀스틱 차트를 입히고 싶습니다.
조회수 1181회
안녕하세요. 자바스크립트로 차트 UI를 만들어야 하는데 너무 막막해서 조언을 구하고 싶습니다.
위 그림과 같이 실시간으로 들어오는 데이터에 따라 원형 게이지 차트 위에 캔들스틱 차트를 그려야 하는데 계속 찾아도 비슷하게 구현된 라이브러리를 못찾겠습니다.
이러한 차트를 그려보셨거나, 비슷한 라이브러리를 사용했던 분 혹시 계신지 어쭈어보고 싶습니다.
-
(•́ ✖ •̀)
알 수 없는 사용자
2 답변
-
원형 캔들 차트 라이브러리는 딱히 본 적이 없는데... 도넛 차트를 응용해서 만들 수 있지 않을까요?
근데 단순히 이걸 구현하려고 라이브러리를 배우고 되는지 시도해 보고 하는 삽질 하느니 직접 구현하는게 나을 것 같기도 하고요.
직접 구현한다면 구현 난이도는 다 비슷하겠지만 표현을 뭘로 하느냐의 차이긴 해요.
canvas를 쓰시면 가능할거에요. https://www.w3schools.com/tags/canvas_arc.asp
완벽하게 맞아 떨어지는 라이브러리를 찾지 못한다면 저는 이게 가장 쉬워보입니다.
차선책으로 SVG기반으로 하는 라이브러리를 사용하셔도 됩니다. (SVG 엘리먼트 및 속성을 직접 다루는건... 음... 딱히 추천드리지 않습니다.)
CSS와 일반적인 엘리먼트로만 만드는건... 만들기도 번거로울 뿐더러 만들어놔도 컨트롤하기 힘들겁니다.
border-radius: 50%
속성 부여된 동심원들 잘 스까치면 가능은 할거에요. -
결국 canvas 를 통해 완성했습니다. 혹시나 필요하신 분을 위해 작성합니다.
완성된 그림과 코드를 첨부합니다.
아직 완벽히 다짠게 아닌것에 유의해 주시면 감사하겠습니다.
<html> <head> </head> <body> <canvas id="tempCanvas" width=700 height=500> </canvas> </body> </html>
var circular ={ width:700, //캔버스 너비 height:500, //캔버스 높이 radius:200, // 그리려는 원의 반지름 lineWidth:1, // 원의 두께 angle:0.35, // 원의 각도 MinVal:0, // 원의 최소값 MaxVal:100, //원의 최대값 toMaxVal:50, //처음 그릴때의 최대 초기값 toMinVal:50 // 처음 그릴때의 최소 초기값 }; $(document).ready(function(){ testDraw(49, 51); // 디버그용 그리기 setInterval(function(){ var Number1 = Number((Math.random()*100).toFixed(0)); var Number2 = Number((Math.random()*100).toFixed(0)); var openVal, closeVal; if(Number1 > Number2){ openVal = Number2; closeVal = Number1; }else{ openVal = Number1; closeVal = Number2; } testDraw(openVal, closeVal); },2000) }); var req; function testDraw(openVal, closeVal){ var canvas = document.getElementById("testCanvas"); var context = canvas.getContext("2d"); drawStarndard(context); drawCircle(circular.toMinVal, circular.toMaxVal, context); animate(openVal, closeVal, canvas, context); } function drawStarndard(context){ //기준선 context.beginPath(); context.arc(circular.width/2, circular.height/2, circular.radius, (1-circular.angle)*Math.PI, (2+circular.angle)*Math.PI, false) context.lineWidth=1; context.strokeStyle="#000000"; context.stroke(); context.beginPath(); // hit 최소값 context.moveTo((circular.width/2 - circular.radius),circular.height/2); context.lineTo((circular.width/2 - circular.radius)-30, circular.height/2); context.stroke(); context.font = "20px Arial"; context.fillText("25", (circular.width/2 - circular.radius)-65,(circular.height/2)+5); //중앙값 context.beginPath(); context.moveTo(circular.width/2, circular.height/2-circular.radius) context.lineTo(circular.width/2, circular.height/2-circular.radius-30); context.stroke(); context.fillText("50", (circular.width/2)-10,(circular.height/2 - circular.radius-40)); // hit 최대값 context.beginPath(); context.moveTo(circular.width/2+circular.radius, circular.height/2) context.lineTo(circular.width/2+circular.radius+30, circular.height/2); context.stroke(); context.fillText("75", (circular.width/2 + circular.radius)+40,(circular.height/2)+5); } function animate(openVal, closeVal, canvas, context) { if(openVal < circular.toMinVal){ circular.toMinVal -= 1; }else if(openVal > circular.toMinVal){ circular.toMinVal += 1; } if(closeVal > circular.toMaxVal){ circular.toMaxVal += 1; }else if(closeVal < circular.toMaxVal){ circular.toMaxVal -= 1; } context.clearRect(0, 0, canvas.width, canvas.height); drawStarndard(context); drawCircle(circular.toMinVal, circular.toMaxVal, context); if(openVal == circular.toMinVal && closeVal == circular.toMaxVal){ cancelAnimationFrame(req); circular.toMinVal = openVal; circular.toMaxVal = closeVal; }else{ req = requestAnimationFrame(function() { animate(openVal, closeVal, canvas, context); }); } } function drawCircle(openVal, closeVal, context){ var openAngle = getAngle(circular.angle, circular.MinVal, circular.MaxVal, openVal); var closeAngle = getAngle(circular.angle, circular.MinVal, circular.MaxVal, closeVal); context.beginPath(); context.arc(circular.width/2, circular.height/2, circular.radius+5, openAngle , closeAngle, false); context.lineWidth=5; context.strokeStyle="#3536f0"; context.stroke(); context.beginPath(); context.moveTo((Math.cos(openAngle)*circular.radius) + (circular.width/2) , (Math.sin(openAngle)*circular.radius) + (circular.height/2)); context.lineTo((Math.cos(openAngle)*circular.radius*1.2) + (circular.width/2) , (Math.sin(openAngle)*circular.radius*1.2) + (circular.height/2)); context.stroke(); }
-
(•́ ✖ •̀)
알 수 없는 사용자
-
댓글 입력