2011-01-22 4 views
0

크기 조정 이벤트를 처리하는 코드를 작성 중입니다.크기 조정 핸들러는 한 번 작동하지만 두 번 작동하지 않습니다.

/* 
    Timeline.js 

    (Requires jquery, developed with jquery-1.4.4.min.js in mind) 
*/ 

/* 
    Timeline's two major functions are setup and draw. After instantiating a 
    timeline object, the developer calls setup() to initialize the object. Later, 
    the developer repeatedly calls on draw() to animate the canvas. 
    In between, resizing the window may trigger the resize() function which 
    adjusts the timeline's dimensions and other settings. 
*/ 
function Timeline(){ 
    // constants 
    Timeline._BORDER_SIDES = 20; // The border on each side of the timeline, 
    // We'll need this value later when calculating back's top offset 
    Timeline._OFFSET_LEFT = '8px'; 
    Timeline._OFFSET_TOP = '8px'; // top border, 8px seems to be chrome default 
    Timeline._BUTTON_WIDTH = 17; // The length of the back and forward buttons 
    Timeline._WIDTH_FACTOR = 2/3; // How much height timeline should take up 
    // variables 
    Timeline._id = 0; // An id wich is unique for each instance of Timeline 

    /* This function is called when the user clicks the back div*/ 
    this._backHandler = function(){ 
    alert('back clicked'); 
    }; 

    this._testResize = function(){ 
    alert('resized'); 
    }; 


    /* 
     timeline.setup() 
     Create canvas, back and forward button, as well as slider for scale. 
     timeline_wrapper_id is the id of an element which is to contain this 
     specific timeline. 
    */  
    this.setup = function(timeline_wrapper_id){ 
    // add canvas 
    this._id = Timeline._id++; // get id, create next id for next instance 
    this._timeline_wrapper_id = timeline_wrapper_id; 
    this._canvas = document.createElement('canvas'); 
    this._canvas.setAttribute('id', 'canvas' + this._id); 
    $('#' + timeline_wrapper_id).append(this._canvas); 

    // add back button 
    this._back = document.createElement('div'); 
    this._back.setAttribute('id', 'back' + this._id); 
    // id's help us jquery stuff, ensuring their unique across instances 
    // lets us potentially put several instance on the same page. 

    this._back.onclick = this._backHandler; // set event handler: onclick 
    $('#' + timeline_wrapper_id).append(this._back); 


    this._resizeHandler = function(){ 
     // First, we clear all style so as to prevent duplicates 
     $('#canvas' + this._id).removeAttr('style'); 
     $('#back' + this._id).removeAttr('style'); 
     // later we'll insert an empty style before modifying the style. 


     // set canvas attributes 

     // Width of canvas is window width, with space for borders either 
     // side. 
     var canvas_width = $(window).width() - Timeline._BORDER_SIDES*2; 
     var canvas_height = $(window).height() * Timeline._HEIGHT_FACTOR; 


     /* The core feature of this block is the z-index. Everything else 
      is there because otherwise I can't determine the z-index. At 
      least that's what I read somewhere. 

      The z-index determines how overlapping elements are drawn. 
      The higher the z-index, the "closer to the user" the element is. 

      In this case, we want to draw everything on top of the canvas, 
      hence the lowest z-index in our application: 0. 
     */ 
     $('#canvas'+this._id).attr('style', ''); 
     // this undoes our removeAttr('style') from earlier 

     $('#canvas' + this._id).css({ 
     width: canvas_width, 
     height: canvas_height, 
     border: '1px solid', // to see what's going on 
     position: 'relative', // "take canvas out of flow"-rough quote 
     top: Timeline._BORDER_TOP, // seems to be the chrome default 
     left: Timeline._BORDER_LEFT, // ditto 
     'z-index': 0 
     }); 

     /* Here we define the back button's visual properties. 
      Where possible, we calculate them in terms of canvas attributes, 
      to achieve a consistent layout as the browser is resized. 
     */ 
     var back_left = $('#canvas' + this._id).css('left') + 'px'; 
     // same distance from left timeline_wrapper as canvas 

     // This one is a little more difficult: An explanation will follow 
     // as soon as I've figured it out myself. 
     var back_top = ((-1)*$('#canvas' + this._id).height() - 6) + 'px'; 

     $('#back' + this._id).attr('style', ''); 
     $('#back' + this._id).css({ 
     'background-color': '#336699', 
     width: Timeline._BUTTON_WIDTH, 
     height: $('#canvas' + this._id).height(), // fill canvas height 
     position: 'relative', // same reason as for canvas 
     left: back_left, 
     top: back_top, 
     'z-index': 1 
     }); 
    }; 


    this._resizeHandler(); 
    $(window).resize(this._resizeHandler); 
    }; 

    /* 
     timeline.draw() 
     Update (or set for the first time) the styles of back and forward button, 
     as well as the canvas. 
     Assumes setup has been called. 
    */ 
    this.draw = function(){ 
    console.log('dummy'); 
    }; 
} 

Timeline.js를 호출하는 코드는 매우 간단하다 : 여기 코드입니다

<!doctype html> 
<html> 
    <head> 
    <title>timeline-js</title> 
    <script type="text/javascript" src="jquery-1.4.4.min.js"></script> 
    <script type="text/javascript" src="Timeline.js"></script> 
    </head> 
    <body> 
    <div id="timeline_wrapper"></div> 
    <script type="text/javascript"> 

var timeline = new Timeline(); 
timeline.setup('timeline_wrapper'); 
// timeline.draw(); 
//setInterval('timeline.draw()', 60); 

    </script> 
    </body> 
</html> 

크기 조정 기능은 크롬에서 오류가 발생하지 않으며,과 같이 호출 할 때 작동합니다

this._resizeHandler(); 

오류 처리기가 호출됩니다. 나는 window.onresize = this._testReszie 설정이 정상적으로 작동하므로이 사실을 알고 있습니다.

그러나 둘을 결합하면 캔버스가 창의 크기가 조정되지 않습니다. 누군가 나를 올바른 방향으로 안내 할 수 있습니까?

+0

코드는 http://code.google.com/p/timeline-js/source/browse/Timeline에서 찾을 수 있습니다. 약간 더 나은 형식으로 js. – lowerkey

답변

1

_resizeHandler 함수에서 this은 타임 라인 인스턴스를 참조하지 않는 것이 문제입니다. 대신 핸들러가 첨부 된 이후로 window을 참조합니다.

고정 방법은 _resizeHandler을 다시 정의하여 Timeline 인스턴스에 대한 참조를 얻는 것입니다.

this._resizeHandler = function(self){ 
    ...same code but with 'this' replaced by 'self'... 
} 

그리고 호출 사이트를 수정 :

this._resizeHandler(this); 
var thisTimeline = this; 
$(window).resize(function() { thisTimeline._resizeHandler(thisTimeline); }); 
}; 
+0

고맙습니다. 그것은 아름답게 일했습니다! 각 이벤트 처리기에 대해이 문제가 발생합니까? (Pun은 완전히 인정되었지만 의도하지는 않습니다) – lowerkey

+0

사실. 이벤트 핸들러가 호출 될 때이 객체는 이벤트 핸들러가 첨부 된 객체가 될 것이라는 것을 기억해야합니다. 따라서 핸들러 내부에 관심이있는 항목을 명시 적으로 참조하도록하려면 이러한 종류의 해결 방법을 수행해야합니다. – jmbucknall

관련 문제