쓸만한 주저리

꺽은선 그래프 그리기

봄돌73 2008. 10. 16. 11:06

아래 산점도 글에서 언급한 방식으로 만든 꺽은선 그래프이다.

두 점 간의 직선 함수(1차 함수)를 못 찾아서 만들었다.

직선 함수를 만든 건 아니고, 1차 함수의 a, b 값을 찾는 함수를 만들어서 좌표를 찍을 때 사용했다.


마찬가지로 〈는 특수문자이다.


ie에서는 엄청 느리고, 불여우는 조금 빠르다.

vml이라는 게 있어서 써 볼까 했는데 ie 전용인지 불여우에서는 작동하지 않았다.


〈body onload=viewgraph()>
〈table width=301 height=301 align=center bgcolor=silver style="border-left:1px solid black;border-bottom:1px solid black">
  〈tr>
    〈td width=100% height=100% valign=top>
      〈!-- td에 position:relative를 주면 불여우에서는 인식하지 않는다. -->
      〈span id=pointspan style=position:relative>〈/span>
    〈/td>
  〈/tr>
〈/table>

〈script>
  var a=0,b=0
  function seekab(x1,y1,x2,y2){
    /*
    y1=ax1+b
    y2=ax2+b
    b=y1-ax1
    b=y2-ax2
    y1-ax1=y2-ax2
    ax2-ax1=y2-y1
    a=(y2-y1)/(x2-x1)
    */
    a=(y2-y1)/(x2-x1)
    b=y1-a*x1
  }

  function viewgraph(){
    var xpoints=new Array(8,34,62,79,150)
    var ypoints=new Array(8,33,95,71,55)
    var topx=300,topy=300

    var obj=document.getElementById('pointspan')
    obj.innerHTML=''

    for(var i=0;i〈xpoints.length-1;i++){
      seekab(xpoints[i],ypoints[i],xpoints[i+1],ypoints[i+1])
      for(var j=0;j〈(xpoints[i+1]-xpoints[i]);j++){
        obj.innerHTML=obj.innerHTML+'〈img src=http://phpschool.com/images/background.gif width=1 height=1 style=position:absolute;left:'+(xpoints[i]+j)+'px;top:'+(300-(a*(xpoints[i]+j)+b))+'px>'
      }
    }

    obj.innerHTML=obj.innerHTML+'〈span style=position:absolute;left:-'+(topy.toString().length*10)+'px;top:0px>'+topy+'〈/span>〈span style=position:absolute;left:'+(topx-20)+'px;top:'+(topy+5)+'px>'+topx+'〈/span>〈span style=position:absolute;left:-15px;top:'+topy+'px>0〈/span>'
  }
〈/script>




크롬에서 실행한 결과 (2초)



불여우3에서 실행한 결과 (5초)



ie8에서 실행한 결과 (이건 뭐...)


위 소스가 너무 느려서(특히 ie) 빠르게 할 방법이 없을까 여기저기 기웃거리다가 발견한 cloneNode를 사용하여 만든 소스다.

불여우에서는 실시간이고, ie에서는 점 그리는 게 느려서 2초 가량 걸린다.


마찬가지로 〈는 특수문자다.


〈body onload=viewgraph()>
〈table width=301 height=301 align=center bgcolor=silver style="border-left:1px solid black;border-bottom:1px solid black">
  〈tr>
    〈td width=100% height=100% valign=top>
      〈!-- td에 position:relative를 주면 불여우에서는 인식하지 않는다. -->
      〈span id=pointspan style=position:relative;font-size:9pt>〈/span>
    〈/td>
  〈/tr>
〈/table>

〈!-- 복사해서 사용할 원본 이미지 개체를 만들어 둔다. -->
〈img id=imgobj src=http://phpschool.com/images/background.gif width=1 height=1 style=position:absolute;left:0px;top:0px;display:none>

〈script>
  var a=0,b=0
  function seekab(x1,y1,x2,y2){
    /*
    y1=ax1+b
    y2=ax2+b
    b=y1-ax1
    b=y2-ax2
    y1-ax1=y2-ax2
    ax2-ax1=y2-y1
    a=(y2-y1)/(x2-x1)
    */
    a=(y2-y1)/(x2-x1)
    b=y1-a*x1
  }

  function viewgraph(){
    var xpoints=new Array(8,34,62,79,150,300)
    var ypoints=new Array(8,33,95,71,55,100)
    var topx=300,topy=300

    var obj=document.getElementById('pointspan')
    obj.innerHTML=''
    var imgobj=null

    for(var i=0;i〈xpoints.length-1;i++){
      obj.innerHTML=obj.innerHTML+'('+xpoints[i]+','+ypoints[i]+')'
      seekab(xpoints[i],ypoints[i],xpoints[i+1],ypoints[i+1])
      for(var j=xpoints[i];j〈xpoints[i+1];j++){
        //각 좌표에 해당하는 점을 원본에서 복사해 온다.
        imgobj=document.getElementById('imgobj').cloneNode(true)
        //해당 좌표에 맞도록 속성을 지정한다.
        imgobj.style.left=j
        imgobj.style.top=300-(a*j+b)
        imgobj.style.display=''
        //그래프 영역 개체에 추가한다.
        obj.appendChild(imgobj)
        //초기에는 아래와 같이 html 태그를 만들어서 추가했다. 굉장히 느렸다. 특히 ie에서...
        //obj.innerHTML=obj.innerHTML+'〈img src=http://phpschool.com/images/background.gif width=1 height=1 style=position:absolute;left:'+j+'px;top:'+(300-(a*j+b))+'px>'
      }
    }
    obj.innerHTML=obj.innerHTML+'('+xpoints[i]+','+ypoints[i]+')'

    obj.innerHTML=obj.innerHTML+'〈span style=position:absolute;left:-'+(topy.toString().length*10)+'px;top:0px>'+topy+'〈/span>〈span style=position:absolute;left:'+(topx-20)+'px;top:'+(topy+5)+'px>'+topx+'〈/span>〈span style=position:absolute;left:-15px;top:'+topy+'px>0〈/span>'
  }
〈/script>


여기저기 자랑했더니 무지개 색깔 그래프를 만들어 보래서 만들었다.


〈table width=301 height=301 align=center bgcolor=silver style="border-left:1px solid black;border-bottom:1px solid black">
  〈tr>
    〈td width=100% height=100% valign=top>
      〈!-- td에 position:relative를 주면 불여우에서는 인식하지 않는다. -->
      〈span id=pointspan style=position:relative;font-size:9pt>〈/span>
    〈/td>
  〈/tr>
〈/table>

〈!-- 복사해서 사용할 원본 개체를 만들어 둔다. -->
〈span id=imgobj style=width:1px;height:1px;font-size:0pt;border:0px;position:absolute;display:none>〈/span>

〈script>
  var a=0,b=0
  function seekab(x1,y1,x2,y2){
    /*
    y1=ax1+b
    y2=ax2+b
    b=y1-ax1
    b=y2-ax2
    y1-ax1=y2-ax2
    ax2-ax1=y2-y1
    a=(y2-y1)/(x2-x1)
    */
    a=(y2-y1)/(x2-x1)
    b=y1-a*x1
  }

  function viewgraph(xpointarray,ypointarray,topxpoint,topypoint,graphcolor){
    var obj=document.getElementById('pointspan')
    var imgobj=null

    for(var i=0;i〈xpointarray.length-1;i++){
      seekab(xpointarray[i],ypointarray[i],xpointarray[i+1],ypointarray[i+1])
      for(var j=xpointarray[i];j〈xpointarray[i+1];j++){
        //각 좌표에 해당하는 점을 원본에서 복사해 온다.
        imgobj=document.getElementById('imgobj').cloneNode(true)
        //해당 좌표에 맞도록 속성을 지정한다.
        imgobj.style.left=j-3
        imgobj.style.top=296-(a*j+b)
        imgobj.style.background=graphcolor
        imgobj.style.display=''
        //그래프 영역 개체에 추가한다.
        obj.appendChild(imgobj)
      }
    }
    obj.innerHTML=obj.innerHTML+'〈span style=position:absolute;left:-'+(topypoint.toString().length*10)+'px;top:0px>'+topypoint+'〈/span>〈span style=position:absolute;left:'+(topxpoint-20)+'px;top:'+(topypoint+5)+'px>'+topxpoint+'〈/span>〈span style=position:absolute;left:-15px;top:'+topypoint+'px>0〈/span>'
  }

  var xpoints=new Array(8,34,62,79,150,300)
  var ypoints=new Array(8,33,95,71,55,200)
  var topx=300,topy=300
  viewgraph(xpoints,ypoints,topx,topy,'red')

  xpoints=new Array(1,300)
  ypoints=new Array(8,100)
  topx=300,topy=300
  viewgraph(xpoints,ypoints,topx,topy,'orange')

  xpoints=new Array(1,300)
  ypoints=new Array(1,150)
  topx=300,topy=300
  viewgraph(xpoints,ypoints,topx,topy,'yellow')

  xpoints=new Array(1,300)
  ypoints=new Array(100,100)
  topx=300,topy=300
  viewgraph(xpoints,ypoints,topx,topy,'green')

  xpoints=new Array(1,300)
  ypoints=new Array(200,100)
  topx=300,topy=300
  viewgraph(xpoints,ypoints,topx,topy,'blue')

  xpoints=new Array(1,300)
  ypoints=new Array(300,100)
  topx=300,topy=300
  viewgraph(xpoints,ypoints,topx,topy,'navy')

  xpoints=new Array(1,300)
  ypoints=new Array(100,10)
  topx=300,topy=300
  viewgraph(xpoints,ypoints,topx,topy,'purple')
〈/script>