2013-09-04 3 views
1

HTML5 캔버스 드로잉을 연습하려고합니다. 그래서이 문제를 생각해 냈습니다. 나는 노란색 별이 과 겹친의 흉상의 녹색 실루엣 (사람의 머리와 어깨)을 가져야합니다.Html 5 캔버스 문제

그러나 drawStar() 행이 주석 처리되지 않은 경우 녹색 실루엣은 그려지지 않습니다. 이 작업 코드는 현재 상황에 대한 설명만큼 중요하지 않습니다.

http://jsfiddle.net/xiondark2008/LYfHJ/2/

HTML :

<!DOCTYPE html> 
<html> 
<head> 
    <style> 
    h6{ 
     -webkit-margin-before: .5em; 
     -webkit-margin-after: 0; 
    } 
    label{ 
     margin-left: 1em; 
    } 
    </style> 

</head> 
<body> 

    <canvas id="myCanvas" width="19" height="19" 
     style="border:1px solid d3d3d3;"> 
     Your browser does not support the HTML5 canvas tag.</canvas> 
</body> 
</html> 

자바 스크립트 :

function drawProfile(ctx,x,y,width,height) { 
    this.flp = false; 
    this.x = function(r){ return Math.floor(width*(this.flp?1-r:r)); } 
    this.y = function(r){ return Math.floor(height*r); } 

    ctx.save(); 

    ctx.translate(x, y); 
    ctx.fillStyle="#40FF00"; 

    ctx.beginPath(); 
    ctx.moveTo(this.x(0), this.y(1)); 
    ctx.bezierCurveTo(
     this.x(0),  this.y(125/190), 
     this.x(70/190), this.y(170/190), 
     this.x(75/190), this.y(120/190) 
    ); 
    ctx.lineTo(this.x(95/190), this.y(130/190)); 
    ctx.bezierCurveTo(
     this.x(40/190), this.y(130/190), 
     this.x(30/190), this.y(0), 
     this.x(95/190), this.y(0) 
    ); 

    this.flp = true; 

    ctx.bezierCurveTo(
     this.x(30/190), this.y(0), 
     this.x(40/190), this.y(130/190), 
     this.x(95/190), this.y(130/190) 
    ); 
    ctx.lineTo(this.x(75/190), this.y(120/190)); 
    ctx.bezierCurveTo(
     this.x(70/190), this.y(170/190), 
     this.x(0), this.y(125/190), 
     this.x(0), this.y(1) 
    ); 
    ctx.fill(); 

    this.flp = false; 

    ctx.restore(); 
} 

function drawStar(ctx,x,y,height) { 

    var pnts = 5, 
     rad = height/(1-Math.cos(0.8*Math.PI)); 

    this.x = function(p,dst){ 
     return dst * Math.sin((p/pnts)*2*Math.PI); 
    } 
    this.y = function(p,dst){ 
     return dst * Math.cos((p/pnts)*2*Math.PI) * -1; 
    } 
    this.movePct = function(a,b,pct){ 
     var f = (function(x){ 
       var m = (b.y-a.y)/(b.x-a.x); 
       return m*x+(a.y-(a.x*m)); 
      }).bind(), 
      r = b.x - a.x, 
      point = {}; 

     point.x = a.x+(r*pct); 
     point.y = f(point.x); 

     return point; 
    } 
    this.transPoints = function(s,p,e,pct){ 
     var sp = this.movePct(s,p,pct), 
      ep = this.movePct(e,p,pct); 

     return [sp,ep]; 
    } 

    ctx.save(); 

    ctx.translate(x+rad, y+rad); 
    ctx.fillStyle = "#ffff00"; 

    ctx.beginPath(); 

    for(var i=0;i<pnts;i++){ 
     var dst = rad/2, 
      s = { x: this.x(i+0.5, dst), 
        y: this.y(i+0.5, dst) }, 
      p = { x: this.x(i+1, rad), 
        y: this.y(i+1, rad) }, 
      e = { x: this.x(i+1.5, dst), 
        y: this.y(i+1.5, dst) }, 
      t = this.transPoints(s,p,e,.75); 

     if(i==0){ ctx.moveTo(s.x, s.y); } 

     ctx.lineTo(t[0].x, t[0].y); 
     ctx.quadraticCurveTo(p.x, p.y, t[1].x, t[1].y); 
     ctx.lineTo(e.x, e.y); 
    } 
    ctx.fill(); 

    ctx.restore(); 

} 

function draw(c) { 

    var ctx = c.getContext("2d"); 

    this.x = function(r){ return c.width*r; } 
    this.y = function(r){ return c.height*r; } 

    ctx.shadowBlur=this.y(1/19); 
    ctx.shadowColor="black"; 

    //drawStar(ctx, this.x(-3/19), this.y(-1/19), this.y(20/19)); 
    drawProfile(ctx, this.x(6/19), this.y(1/19), this.x(18/19), this.y(18/19)); 


    if(0){ 
     ctx.clearRect(this.x(1), this.y(0), this.x(1), this.y(1)); 
     ctx.clearRect(this.x(0), this.y(1), this.x(1), this.y(1)); 
    } 

} 

draw(document.getElementById("myCanvas")); 
+3

당신 스크립트가 무엇을하는지에 비해 지나치게 복잡하게 보이는 : 나는 기능 drawProfile 및 drawStar의 끝에서 자신의 이전 값에 this.x와 this.y 기능을 재설정하여 해결 방법을 만들어 첫 번째보기에서는 객체 메서드로 호출되지 않는 함수에서이를 참조하는 것은 혼란 스럽습니다. 먼저 아키텍처를 다시 생각해야하며 문제가 훨씬 쉽게 발견 될 것입니다. 쓸데없는 복잡성보다 더 나쁜 것은 없습니다. – Virus721

+0

저는이 바이러스에 @ Virus721을 사용하고 있습니다. 코드가 복잡해 보입니다. – Funkyguy

+0

당신이 더 신선한 사람이라면 [link] http://www.w3schools.com/html/html5_canvas.asp[/link]를 시도해보십시오. [link] https://developer.mozilla.org/en- US/docs/Web/Guide/HTML/Canvas_tutorial? redirectlocale = ko-US & redirectslug = Canvas_tutorial [/ link] 완전한 수비수를위한 모두 –

답변

2

당신은 당신의 기능에 this을 사용하고 있습니다. 여기에서 문맥에서 thiswindow에 바인딩되어 있습니다 (this을 사용하는 방법에 대한 많은 리소스가 있으며 잘못하고 있습니다).

this을 사용하는 각 함수에서 서로 동일한 변수 (window)에 바인딩되어 서로의 변수를 덮어 씁니다. (이것은 당신이 기능을 사용하는 방식 때문입니다. 당신이 new 그들을 편집하면 다른 이야기가 될 것입니다.)

그래서

  1. 하여 draw() 방법
  2. 는 다음 아규먼트 drawStar() 함수 방법 (window.x이다) this.x의 값을 변경
  3. drawStar()에 전달 실제로 window.xthis.x 설정 draw()
  4. 다음으로 draw()drawProfile()this.x (즉, window.x)으로 바꾸지 만,이 값은 원하는 float 값이 아닌 함수입니다.
  5. drawProfile는 플로트로 인수를 기대하지만, 지금은 모든 폐쇄와 변수와 함께이 작업을 수행 할 수 있습니다 (xxy을 읽기) 기능

입니다. this을 제거하면 프로그램이 작동합니다. 아마.

+0

도움을 주셔서 감사합니다. 나는 많은 "작은"변화의 결과로 복잡한 코드에 희생되었습니다. –

+0

모든 사람에게 발생합니다. 그것을 보면서 무엇이 잘못되었는지 알 수 없다면 할 수있을 때까지 자주 구조를 바꾸는 것이 좋습니다. – Joe

0

조이 맞습니다. this.x 및 this.y 함수를 겹쳐 쓰는 중입니다. 왜 당신이 이것을하고 있는지 나는 모른다.

function drawProfile(ctx,x,y,width,height) { 
    var oldX = this.x, //storing the old values for this.x ... 
     oldY = this.y; // ... and this.y 
    this.flp = false; 
    this.x = function(r){ return Math.floor(width*(this.flp?1-r:r)); } 
    this.y = function(r){ return Math.floor(height*r); } 

    ctx.save(); 

    ctx.translate(x, y); 
    ctx.fillStyle="#40FF00"; 

    ctx.beginPath(); 
    ctx.moveTo(this.x(0), this.y(1)); 
    ctx.bezierCurveTo(this.x(0), this.y(125/190), 
         this.x(70/190), this.y(170/190), 
         this.x(75/190), this.y(120/190) 
        ); 
    ctx.lineTo(this.x(95/190), this.y(130/190)); 
    ctx.bezierCurveTo(this.x(40/190), this.y(130/190), 
         this.x(30/190), this.y(0), 
         this.x(95/190), this.y(0) 
        ); 

    this.flp = true; 

    ctx.bezierCurveTo(this.x(30/190), this.y(0), 
         this.x(40/190), this.y(130/190), 
         this.x(95/190), this.y(130/190) 
        ); 
    ctx.lineTo(this.x(75/190), this.y(120/190)); 
    ctx.bezierCurveTo(this.x(70/190), this.y(170/190), 
         this.x(0), this.y(125/190), 
         this.x(0), this.y(1) 
        ); 
    ctx.fill(); 

    this.flp = false; 

    ctx.restore(); 

    this.x = oldX; //Restoring old values 
    this.y = oldY; 
} 

function drawStar(ctx,x,y,height) 
{ 
    var pnts = 5, 
     rad = height/(1-Math.cos(0.8*Math.PI)), 
     oldX = this.x, //storing the old values for this.x ... 
     oldY = this.y; // ... and this.y 

    this.x = function(p,dst){ 
     return dst * Math.sin((p/pnts)*2*Math.PI); 
    } 
    this.y = function(p,dst){ 
     return dst * Math.cos((p/pnts)*2*Math.PI) * -1; 
    } 
    this.movePct = function(a,b,pct){ 
     var f = (function(x){ 
      var m = (b.y-a.y)/(b.x-a.x); 
      return m*x+(a.y-(a.x*m)); 
     }).bind(), 
      r = b.x - a.x, 
      point = {}; 

     point.x = a.x+(r*pct); 
     point.y = f(point.x); 

     return point; 
    } 
    this.transPoints = function(s,p,e,pct){ 
     var sp = this.movePct(s,p,pct), 
      ep = this.movePct(e,p,pct); 

     return [sp,ep]; 
    } 

    ctx.save(); 

    ctx.translate(x+rad, y+rad); 
    ctx.fillStyle = "#ffff00"; 

    ctx.beginPath(); 

    for(var i=0;i<pnts;i++){ 
     var dst = rad/2, 
      s = { x: this.x(i+0.5, dst), 
       y: this.y(i+0.5, dst) }, 
      p = { x: this.x(i+1, rad), 
       y: this.y(i+1, rad) }, 
      e = { x: this.x(i+1.5, dst), 
       y: this.y(i+1.5, dst) }, 
      t = this.transPoints(s,p,e,.75); 

     if(i==0){ ctx.moveTo(s.x, s.y); } 

     ctx.lineTo(t[0].x, t[0].y); 
     ctx.quadraticCurveTo(p.x, p.y, t[1].x, t[1].y); 
     ctx.lineTo(e.x, e.y); 
    } 
    ctx.fill(); 

    ctx.restore(); 

    this.x = oldX; //Resetting the old values 
    this.y = oldY; 
} 

function draw(c) 
{ 

    var ctx = c.getContext("2d"); 

    this.x = function(r){ return c.width*r; } 
    this.y = function(r){ return c.height*r; } 

    ctx.shadowBlur=this.y(1/19); 
    ctx.shadowColor="black"; 

    drawStar(ctx, this.x(-3/19), this.y(-1/19), this.y(20/19)); 
    drawProfile(ctx, this.x(6/19), this.y(1/19), this.x(18/19), this.y(18/19)); 



    if(0){ 
     ctx.clearRect(this.x(1), this.y(0), this.x(1), this.y(1)); 
     ctx.clearRect(this.x(0), this.y(1), this.x(1), this.y(1)); 
    } 

} 

draw(document.getElementById("myCanvas")); 

http://jsfiddle.net/hhaXM/