예측 데이터 그래프 (Dygraph)
말은 예측 데이터 그래프지만 실제로는 이차 방정식 그래프에 마커 표시를 한것이다.
시설물의 균열은 시간이 지나면서 점점 벌어지는데 오랜 시간 측정한 데이터로 다음 균열의 진행 시기를 예측 할 수 있다고 한다.
Source Code
- bigdata.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <link rel="stylesheet" href="http://dygraphs.com/dist/dygraph.css"> <script src="./jquery-3.3.1.js"></script> <script src="http://dygraphs.com/dist/dygraph.js"></script> <script src="./moment.js"></script> <script src="./numbro.min.js"></script> <script src="./bridgeGraph.js"></script> </head> <body> <p>시작일 <input type="date" id="startDate" value="2019-01-01"></p> <p>끝일 <input type="date" id="endDate" value="2035-01-01"></p> <p>색상 <input type="color" id="color" rgba></p> <p>이벤트 포인트</p> <p> <input type="checkbox" name="dots" value="0.2" id="dottwo" checked> <label for="dottwo">0.2</label> <input type="checkbox" name="dots" value="0.3" id="dotthree" checked> <label for="dotthree">0.3</label> <input type="checkbox" name="dots" value="0.5" id="dotfive" checked> <label for="dotfive">0.5</label> <input type="checkbox" name="dots" value="0.7" id="dotseven"> <label for="dotseven">0.7</label> <input type="checkbox" name="dots" value="0.9" id="dotnine"> <label for="dotnine">0.9</label> </p> <button id="generateBtn" onclick="graphOptionGenerate()">조회</button> <div id="graph_div" style="width:1024px; height:400px;"></div> <div id="record"></div> </body> </html>
- bigdata.js
var data = { "returnCode": "200", "data": { "paramA": 3.647711896363213e-18, "paramB": -1.1277236853945568e-8, "paramC": 8.762329392601957, "currentPoint": { "evetId": "", "x": 1.546835815E9, "y": 0.0461795755014478 }, "stdPoint": null, "eventPoints": [{ "evetId": "D20181127204455070000004", "x": 1.751149584e+9, "y": 0.2 }, { "evetId": "D20181127204610688000005", "x": 1.809584815e+9, "y": 0.3 }, { "evetId": "D20181127204842488000007", "x": 1.898518878e+9, "y": 0.5 }] } } var bigDataGraph; const hexToRgb = function(hex) { var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); return result ? [parseInt(result[1], 16), parseInt(result[2], 16),parseInt(result[3], 16)] : null; } const axisTickFormatter = function (type, format) { if (type == "timeseries") { return function (d) { return moment(d).format(format) }; } else if (type == "indexed") { return function (d) { return numbro(d).format(format) }; } } const timeFormatter = function (time, format) { return moment(time * 1000).format(format); } const quadraticEquationequation = function (x, a, b, c) { let y = (a * Math.pow(x, 2)) + (b * x) + c; return parseFloat(y); } const quadraticFormula = function (y, a, b, c_param) { let c = c_param - y; let x = (-1 * b + Math.sqrt(b * b - 4 * a * c)) / (2 * a); return x; } const bigdataGenerate = function (el, option, suboption) { console.log(suboption) if (option.returnCode == 204) { document.getElementById("el").innerHTML("빅데이터 값이 존재하지 않습니다."); return; } else { var a = parseFloat(option.data.paramA); var b = parseFloat(option.data.paramB); var c = parseFloat(option.data.paramC); var graph = document.getElementById(el); var width = parseInt(graph.style.width); var x1 = suboption.startDate; var x2 = suboption.endDate; var xs = 1.0 * (x2 - x1) / width; var data = []; for (var i = 0; i < width; i++) { var x = parseFloat(x1 + i * xs); var y = quadraticEquationequation(x / 1000, a, b, c); var row = [x]; if (y.length > 0) { for (var j = 0; j < y.length; j++) { row.push(y[j]); } } else { row.push(y); } data.push(row); } } var labels = ['Time']; if (data[0].length == 2) { labels.push('Y'); } else { for (var i = 1; i < data[0].length; i++) { labels.push('Y' + (1 + i)); } } return new Dygraph(graph, data, { labels: labels, axisLabelFontSize: 11, displayAnnotations: true, axes: { x: { valueFormatter: axisTickFormatter("timeseries", "YYYY/MM/DD"), axisLabelFormatter: axisTickFormatter("timeseries", "YYYY/MM/DD"), }, y: { valueFormatter: axisTickFormatter("indexed", { "mantissa": 4, "thousandSeparated": true }), axisLabelFormatter: axisTickFormatter("indexed", { "mantissa": 4, "thousandSeparated": true }), } }, underlayCallback: function (canvas, area, g) { var size = suboption.dotsVal.length; let recordData = []; suboption.dotsVal.forEach(function (el, index) { var bottom_left = g.toDomCoords(quadraticFormula(el, a, b, c) * 1000 - 15768000000, 0); var top_right = g.toDomCoords(quadraticFormula(el, a, b, c) * 1000 + 15768000000, 0); var left = bottom_left[0]; var right = top_right[0]; var opacify = 1 / size * (index + 1) canvas.fillStyle = "rgba(" + suboption.color[0] + "," + suboption.color[1] + "," + suboption.color[2] + ", " + opacify + ")"; canvas.fillRect(left, area.y, right - left, area.h); recordData[index] = {point : el, time : timeFormatter(quadraticFormula(el, a, b, c), "YYYY/MM/DD")} }) recordGenerate(recordData) }, colors: ["#000000"], }); } const recordGenerate = function(r_data){ let html = "" r_data.forEach(function(el, idx){ html += "<p>"+el.point+": "+el.time+"</p>" }) $("#record").html(html) } window.onload = function () { graphOptionGenerate(data) } const graphOptionGenerate = function (param) { let startDate = ""; let endDate = ""; let color = ""; let dotsVal = [] if (param == undefined) { startDate = new Date(document.getElementById("startDate").value).getTime() endDate = new Date(document.getElementById("endDate").value).getTime() color = hexToRgb(document.getElementById("color").value) let dotsList = Array.from($("input[name=dots]:checked")) dotsList.forEach(function (el, index) { dotsVal[index] = $(el).val() * 1.0; }) } else { startDate = param.data.currentPoint.x * 1000 endDate = 2208988800000 color = hexToRgb("#2dbcb3") dotsVal = [0.2, 0.3, 0.5] } let suboption = { startDate, endDate, color, dotsVal, }; bigDataGraph = bigdataGenerate("graph_div", data, suboption) }
Usage
1. Setup
<link rel="stylesheet" href="http://dygraphs.com/dist/dygraph.css"> <script src="./jquery-3.3.1.js"></script> <script src="http://dygraphs.com/dist/dygraph.js"></script> <script src="./moment.js"></script> <script src="./numbro.min.js"></script>
data
가 서버로부터 받은 값이고 사용자의 옵션에 따라 여러가지 항목을 정할 수 있게 하였다.
처음에는 디폴트 옵션이 적용되고 옵션 설정시 해당 옵션 적용
- 서버로 부터 받는 값
- 시작일 (현재 값)
- 계수 (ParamA, ParamB, ParamC)
- 이벤트 포인트
- 사용자 옵션 값
- 시작일, 종료일
- 그래프 bar 색상 (bar)
- 이벤트 포인트
주요 함수
bigdataGenerate(el, option, suboption)
suboption
: 사용자 옵션- 실제 그래프를 그려
Dygraph
객체를 반환하는 함수 el
: 그래프를 그릴element
의id
option
: 서버로 부터 받은data
quadraticEquationequation(x, a, b, c)
넘겨 받은 값으로y
를 반환함x
,a
,b
,c
: 이차 방정식 계수 및x
quadraticFormula(y, a, b, c)
근의 공식을 이용하여 방정식의 해를 반환(x
)y
,a
,b
,c
: 이차 방정식 계수 및y
graphOptionGenerate(param)
사용자 선택한 옵션 생성해 그래프 그리는 함수 호출param
:require false
CodePen
See the Pen dygraph Equation graph by PAPICO (@joseongryun) on CodePen.
'Study > ETC' 카테고리의 다른 글
Clojure로 LISP 톺아보기 (2) - Symbol 과 함수 (0) | 2019.05.21 |
---|---|
Clojure로 LISP 톺아보기 (1) - 데이터 구조 (0) | 2019.05.20 |
[개발이슈]bxSlider height 0 이슈 (0) | 2019.01.08 |
[개념잡기] jQuery-UI (0) | 2018.10.08 |
[개념잡기] D3JS 기본 개념 및 API (1) | 2018.09.18 |