Как обращаться к статическим методам и свойствам класса до его объявления?
С переменными всё понятно. 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>