Как обращаться к статическим методам и свойствам класса до его объявления?

С переменными всё понятно. var - поднимаются, const и let - нет.

Функции тоже поднимаются. Но почему не поднимаются классы??

Вот, тут класс с некоторыми статическими свойствами и методами. Если я в первых строках скрипта пытаюсь писать SoltFly.fly_selectors='td' то получаю ошибку

Uncaught ReferenceError: Cannot access 'SoltFly' before initialization

А хочется вызвать до объявления. Как этого добиться, даже если классы не поднимаются?

//SoltFly.fly_selectors='td,div';

class SoltFly{
  url1='https://www.solt.ru/files/fly01.webm';
  url2='https://www.solt.ru/files/fly_wash01.webm';
  url3='https://www.solt.ru/files/flying01.webm';
    the_fly; video; box; line; next_line;
    id;
    fly_dx=20;
    fly_dy=10;
    fly_x=0;
    fly_y=0;
    fly_a=0;
    fly_discrete=200;
    init_speed=40;
    creep_speed=40;
    aria_size=1;
    timer=0;
    act='';
    x1;y1;x2;y2; new_x; new_y; new_a; fly_step;

    static sides={
        top:   {next:'right',  angle:0,  dx:1, dy:0},
        right: {next:'bottom', angle:90, dx:0, dy:1},
        bottom:{next:'left',   angle:180,dx:-1,dy:0},
        left:  {next:'top',    angle:270,dx:0, dy:-1}
    };
    static fly_blocks=[];
    static counter=0;

    static fly_selectors='';
    static win_pos={};
    static d_timer;
    static flies=[];    
    static start_delay=5;
    
    constructor(width=40){
        let height=width/2;
        this.aria_size=rnd(1,4);
        this.fly_discrete=rnd(150,750,0,3);//150+Math.random()**3*600;
        this.fly_x=rnd(-15,25)*document.documentElement.clientWidth;
        this.fly_y=rnd(-15,25)*document.documentElement.clientHeight;
        this.id=SoltFly.counter++;
        this.fly_dx=width/2;
        this.fly_dy=height/2;
        this.creep_speed=this.init_speed=rnd(4,40);

        this.the_fly=document.createElement('div');
        this.the_fly.style=`font-size:${width*.2}px; 
            width:${width}px; height:${height}px; position:fixed; left:${this.fly_x}px; top:${this.fly_y}px;
            //border: solid 0.5px; border-color: green red black green;
            z-index:1100`;
        this.the_fly.innerHTML=`<video preload disableremoteplayback playsinline autoplay muted loop 
            style="position:relative;
            width:${width}px; 
            top:${height/6}px;"
            src="${this.url1}" type="video/webm">
            </video>`;
    
        
        //this.the_fly.addEventListener('click',()=>{this.start()});
        this.the_fly.addEventListener('mouseover',this.touch);
        document.body.appendChild(this.the_fly);
        this.video=this.the_fly.querySelector('video');
        this.video_src=this.video.querySelector('source');
        //log('CONSTRUCTING',this.get_rnd_line);
    }

    touch=()=>{
        clearTimeout(this.timer);
        this.aria_size*=2;
        this.disabled=1;
        this.do_fly();
    }

    start=(e)=>{
        //log('START',this);
        if(this.disabled) return;
        if(this.act=='flying'){
            this.fly_again=1;
            return;
        }
        clearTimeout(this.timer);
        this.act=0;
        setTimeout(this.do_fly,1);
    }

    do_turn=()=>{
        let k=1, x=0, y=0,turn_discrete=100;
        if(!this.act){

            //log('START turn',3000/this.init_speed, this.fly_discrete);
            this.next_line=this.get_line(this.box.next_side);
            //log(this.next_line);
            if(!this.next_line){
                setTimeout(this.start, 1);
                return;
            }
            this.new_x=this.next_line[0][0];
            this.new_y=this.next_line[0][1];
            this.act='turning';
            this.fly_step=0;
            this.new_a=this.fly_a+90;
        }
        //turn_discrete=4000/this.init_speed;

        if(this.fly_step<=turn_discrete){
            k=this.fly_step/turn_discrete;

            x=this.fly_x+(this.new_x-this.fly_x)*k;
            y=this.fly_y+(this.new_y-this.fly_y)*k;
            this.the_fly.style.left=(x-this.fly_dx)+'px';
            this.the_fly.style.top=(y-this.fly_dy)+'px';
            this.the_fly.style.transform=`rotate(${this.fly_a+(this.new_a-this.fly_a)*k}deg)`;
            this.fly_step+=1;
            this.timer=setTimeout(this.do_turn, 1);
        }else{
            //ctx.lineTo(this.line[1][0],this.line[1][1]);
            this.fly_x=this.new_x;
            this.fly_y=this.new_y;
            this.fly_a=this.new_a%360;
            this.line=this.next_line;

            let side=this.box.side;
            this.box.side=this.box.next_side;
            this.box.next_side=this.box.f[SoltFly.sides[this.box.side].next] ? SoltFly.sides[this.box.side].next : '';
            //log(side,this.box.side,this.box.next_side);
            this.act=0;
            setTimeout(this.do_creep, 1);
        }
    }

    do_creep=()=>{
        //log(this.action);
        if(!this.act || this.act=='washing'){
            this.act='creeping';
            this.creep_speed=this.init_speed*rnd(.5, 1.5);
            this.video.src=this.url1;
            //this.the_fly.innerHTML='Ползёт';
            //log('START creep');
        }
        //log(this.fly_x,this.line[1][0] , this.fly_y,this.line[1][1]);
        let dx=SoltFly.sides[this.box.side].dx;
        let dy=SoltFly.sides[this.box.side].dy;
        if(this.fly_x*dx<=this.line[1][0]*dx && this.fly_y*dy<=this.line[1][1]*dy){

            this.fly_x+=dx;
            this.fly_y+=dy;
            this.the_fly.style.left=(this.fly_x-this.fly_dx)+'px';
            this.the_fly.style.top=(this.fly_y-this.fly_dy)+'px';

            if(rnd()<0.01){ //Иногда стоит
                //this.the_fly.innerHTML='Стоит';
                this.act='washing';
                this.video.src=this.url2;
                this.timer=setTimeout(this.do_creep, rnd(1000,7000,1));
                return;
            }
            if(rnd()<0.002){ //Редко улетает
                //this.the_fly.innerHTML='Муха';
                setTimeout(this.do_fly, 1);
                return;
            }
            this.video.playbackRate=580/(this.creep_speed*this.fly_dx);
            this.timer=setTimeout(this.do_creep, this.creep_speed);
        }else{
            this.act=0;
            //log('END creep');
            if(rnd()<0.33)
                this.timer=setTimeout(this.do_fly, 1);
            else
                this.timer=setTimeout(this.do_turn, 1);
        }
    }

    do_fly=(mode)=>{
        let k=2,t=1,t1=1,x=0,y=0;
        if(this.act!='flying'){ //init
            //log(this);
            clearTimeout(this.timer);
            this.get_rnd_line();
            //log('Fly',this.line)
            this.new_x=this.line[0][0];
            this.new_y=this.line[0][1];
            this.new_a=SoltFly.sides[this.box.side].angle;
            this.x1=(this.aria_size*rnd(-.5,.5)+.5)*document.documentElement.clientWidth;
            this.x2=(this.aria_size*rnd(-.5,.5)+.5)*document.documentElement.clientWidth;
            this.y1=(this.aria_size*rnd(-.5,.5)+.5)*document.documentElement.clientHeight;
            this.y2=(this.aria_size*rnd(-.5,.5)+.5)*document.documentElement.clientHeight;
            this.fly_step=0;
            this.act='flying';
            //log('START Fly');
            this.video.src=this.url3;
        }
        if(this.fly_step<=this.fly_discrete){
            k=this.fly_step/this.fly_discrete;
            t=k**0.7;

            let cos=Math.cos(k*Math.PI);
            if(cos>=0){ //Первая половина полёта
                cos= cos**0.8;
                k=1+k;
            }else{ // Вторая половина
                cos= - ((-cos)**0.8);
                k=2-k;
                if(this.disabled){ //Улетела
                    this.the_fly.style.display='none';
                    return;
                }
            }
            t=(1-cos)/2;
            t1=1-t;
            //log(t,t1,this.fly_x,this.new_x,this.x1,this.x2,this.y1,this.y2);
            x=(t1**3)*this.fly_x + 3*(t1**2)*t*this.x1 + 3*t1*(t**2)*this.x2 + (t**3)*this.new_x;
            y=(t1**3)*this.fly_y + 3*(t1**2)*t*this.y1 + 3*t1*(t**2)*this.y2 + (t**3)*this.new_y;


            //log(k);
            this.the_fly.style.left=(x-this.fly_dx)+'px';
            this.the_fly.style.top=(y-this.fly_dy)+'px';
            let s_k=(k**.7)*2;//**2+(k-1)*this.aria_size*2;
            //log(k,s_k)
            
            //this.the_fly.style.width=(this.fly_dx*s_k)+'px';
            this.video.style.width=(this.fly_dx*s_k)+'px';
            //this.the_fly.style.height=(this.fly_dy*s_k)+'px';
            
            this.the_fly.style.filter=`blur(${(k-1)*(this.aria_size*4)}px)`;
            this.the_fly.style.transform=`rotate(${this.fly_a+(this.new_a-this.fly_a)*t}deg)`;
            //ctx.lineTo(x,y);
            this.fly_step++;
            this.timer=setTimeout(this.do_fly, 1);

        }else{
            //ctx.lineTo(this.line[1][0],this.line[1][1]);
            this.the_fly.style.filter='';
            this.video.play();
            this.fly_x=this.line[0][0];
            this.fly_y=this.line[0][1];
            this.fly_a=this.new_a;
            //ctx.closePath();
            //ctx.stroke();
            this.act=0;
            //log('END fly');
            if(this.fly_again){
                this.fly_again=0;
                this.timer=setTimeout(this.do_fly, 1);
            }else{
                this.video.src='/bpms/files/fly01.webm';
                this.timer=setTimeout(this.do_creep, 1);
            }
        }

    }

    get_rnd_line(){
        let rnd_block=SoltFly.is_visible(SoltFly.fly_blocks[rnd(0,SoltFly.fly_blocks.length,1)]);

        if(!rnd_block){
            //log([rnd_block,this.box]);
            SoltFly.get_win_pos();
            return;
            rnd_block=SoltFly.is_visible(SoltFly.fly_blocks[rnd(0,SoltFly.fly_blocks.length,1)]);
            if(!rnd_block) return;
        }
        this.box=rnd_block;     
        let vis_keys=Object.keys(this.box.f);
        let vis_key_i=rnd(0,vis_keys.length,1);
        this.box.side=vis_keys[vis_key_i];

        this.box.next_side=this.box.f[SoltFly.sides[this.box.side].next] ? SoltFly.sides[this.box.side].next : '';

        //log(this.box, vis_keys, vis_key_i);
        this.line=this.get_line(this.box.side);
    }

    get_line(side='top'){
        let line=null;
        let dx=this.fly_dx/2;
        //let dy=this.fly_dy/2;
        if(side=='top'){
            line=[ [this.box.coords[0][0]+dx,this.box.coords[0][1]-this.fly_dy],[this.box.coords[1][0]-dx,this.box.coords[0][1]-this.fly_dy] ];
        }else if(side=='right'){
            line=[ [this.box.coords[1][0]+this.fly_dy,this.box.coords[0][1]+dx],[this.box.coords[1][0]+this.fly_dy,this.box.coords[1][1]-dx] ];
        }else if(side=='bottom'){
            line=[ [this.box.coords[1][0]-dx,this.box.coords[1][1]+this.fly_dy],[this.box.coords[0][0]+dx,this.box.coords[1][1]+this.fly_dy] ];
        }else if(side=='left'){
            line=[ [this.box.coords[0][0]-this.fly_dy,this.box.coords[1][1]-dx],[this.box.coords[0][0]-this.fly_dy,this.box.coords[0][1]+dx] ];
        }
        return line;
    }

    static init(fly_num=1, min_size=20, delay=5){
        if(delay>0){
            SoltFly.start_delay=delay;
            setTimeout(SoltFly.init, delay*1000, fly_num, min_size, 0);
            return;
        }
        SoltFly.get_win_pos('init');
        if(!SoltFly.fly_blocks.length) return;
        for(let i=0; i<fly_num;i++){
            SoltFly.flies[i]=new SoltFly(min_size*rnd(1,1.5));
        }
        window.addEventListener('scroll', SoltFly.get_win_pos.bind(this,'scroll'));
        window.addEventListener('resize', SoltFly.get_win_pos.bind(this,'resize'));
        SoltFly.fly_start(SoltFly.start_delay*1000);
    }

    static fly_start(delay=1){
        //log(SoltFly.counter);
        for(let i=0; i<SoltFly.counter;i++){
            setTimeout(SoltFly.flies[i].start, rnd(1,delay,1));
        }

    }
    
    static get_win_pos(act='end',e){
        //log(e,act);
        if(act=='end' || act=='init'){
            SoltFly.win_pos={
                top: window.pageYOffset,
                left: window.pageXOffset,
                right: window.pageXOffset + document.documentElement.clientWidth,
                bottom: window.pageYOffset + document.documentElement.clientHeight
            };
            //log('win_pos',SoltFly.win_pos)
            SoltFly.fly_blocks=[];
            let elements=document.querySelectorAll(SoltFly.fly_selectors);
            //log(elements);
            for(let el of elements){
                if(SoltFly.is_visible(el))
                    SoltFly.fly_blocks.push(el);
            }
        }
        if(act=='scroll' || act=='resize'){
            clearTimeout(SoltFly.d_timer);
            SoltFly.d_timer=setTimeout(()=>{SoltFly.get_win_pos('end')}, 200);
        }
        if(act!='init')
            SoltFly.fly_start();
    }

    static is_visible(el){
        var vis={f:{}}, v=0;
        var add_border=10; //+ с запасом, - лояльно
        var bounds=el.getBoundingClientRect();
        var el_pos={
            top:window.pageYOffset + bounds.top,
            left:window.pageXOffset + bounds.left,
            right:window.pageXOffset + bounds.right,
            bottom:window.pageYOffset + bounds.bottom
        };
        //log('el bounds',el_pos);
        
        vis.coords=[[el_pos.left-SoltFly.win_pos.left,el_pos.top-SoltFly.win_pos.top],[el_pos.right-SoltFly.win_pos.left,el_pos.bottom-SoltFly.win_pos.top]];

        el_pos.top-=add_border;
        el_pos.left-=add_border;
        el_pos.right+=add_border;
        el_pos.bottom+=add_border;
        if(el_pos.top>SoltFly.win_pos.top    && el_pos.top<SoltFly.win_pos.bottom)    vis.top=1;
        if(el_pos.left>SoltFly.win_pos.left  && el_pos.left<SoltFly.win_pos.right)    vis.left=1;
        if(el_pos.bottom>SoltFly.win_pos.top && el_pos.bottom<SoltFly.win_pos.bottom) vis.bottom=1;
        if(el_pos.right>SoltFly.win_pos.left && el_pos.right<SoltFly.win_pos.right)   vis.right=1;

        if(vis.top    && vis.left && vis.right) vis.f.top=1;
        if(vis.left   && vis.top && vis.bottom) vis.f.left=1;
        if(vis.bottom && vis.left && vis.right) vis.f.bottom=1;
        if(vis.right  && vis.top && vis.bottom) vis.f.right=1;

        if( vis.f.top || vis.f.bottom || vis.f.left || vis.f.right ){ // Хоть одна сторона полная
            //log('Вы видите элемент',vis);
            return vis;
        }
        return false;
    }
    
}

function rnd(a=null,b=null,retint=null,disp=1){
    let r=Math.random();
    if(disp!=1)
        r=r**disp;
    if(a===null && b===null) //0.0-1.0
        return r;
    if(b===null) //0-a
        return r*a;
    if(retint)
        return r=(a+(b-a)*r)>>0;
    return r=a+(b-a)*r;
}

function log(...a){console.log(...a)}

function fly_init(selectors=null, size=30, delay=1, num=10){
    if(selectors===null) selectors='div, td, th';
    SoltFly.fly_selectors=selectors;
    SoltFly.init(num,size,delay);
        
}

fly_init();
#header{
  margin:4px;
  border: 1px solid #20204040;
}
#footer{
  margin:40px;
  border: 1px solid #20204040;
}
table {
  width: 100%;
}
td {
  height: 3em;
  border: 1px solid #40404040;
}
<html>
<body>
<div id="container">
<div id=header>Header</div>
<table cellspacing=15>
  <tr><td></td><td></td><td></td><td></td></tr>
  <tr><td></td><td colspan=2></td><td></td></tr>
  <tr><td></td><td></td><td></td><td></td></tr>
    <tr><td></td><td></td><td></td><td></td></tr>
  <tr><td></td><td></td><td></td><td></td></tr>
  <tr><td></td><td colspan=2></td><td></td></tr>

</table>
<div id=footer>Footer</div>
</div>
</body>
</html>


Ответы (0 шт):