这 2 个承诺是: 1-加载下一张图像
Load_Img_p
。
2- 移动到下一张图像之前的等待动画Timing_Anim_p
。
它还有一个视觉动画,鼓励您在等待下一张图像完全加载时等待
Hourglass_f
。
想法是这样的: 并行执行
Timing_Anim_p
和 Load_Img_p
。
在解决
Timing_Anim_p
之前,如果出现Load_Img_p
,则显示Wait_Img_Load
这是通过一个名为 imgOnLoad
的简单标志来完成的
代码
Load_Img_p
var imgOnLoad = false;
const Load_Img_p = (imgScr ) => new Promise( (resolve ) =>
{
imgOnLoad = true;
const img = new Image();
img.onload =()=>{ imgOnLoad = false; resolve( img ) };
img.onerror =()=>{ imgOnLoad = false; resolve( null ) };
img.src = imgScr;
})
Hourglass_f
和Timing_Anim_p
的原位代码测试
var imgOnLoad = true; // need also this one to reject other user commands on interface.
const
hourglass_elm = document.querySelector('#hourglass')
, Hourglass_f = (run=false) =>
{
hourglass_elm.classList.toggle('showHourglass', run);
}
, Timing_Anim_e = document.querySelector('#Timing-Anim-bar')
, Timing_Anim_p =()=> new Promise( (resolve ) =>
{
Timing_Anim_e.addEventListener('transitionend', ()=>
{
Timing_Anim_e.classList.remove('showTiming');
Hourglass_f(imgOnLoad);
resolve('Timing_Anim_p ended ok');
}
, { once: true }
);
Timing_Anim_e.classList.add('showTiming');
})
;
btn_test_A.onclick =_=> Hourglass_f(true);
btn_test_B.onclick =_=> Hourglass_f(false);
btn_test_C.onclick =_=> Timing_Anim_p();
body {
background-color: #03063a;
}
#hourglass {
visibility : hidden;
width : 100px;
height : 100px;
stroke : #ff146e;
stroke-dasharray : 80;
stroke-dashoffset : 200;
}
#hourglass.showHourglass {
visibility : visible;
animation : hourglassAnim 1400ms linear infinite alternate;
}
@keyframes hourglassAnim { to { stroke-dashoffset: 0; } }
#Timing-Anim-bar {
width : 500px;
height : 10px;
border : 1px #9acd32 solid;
position : relative;
}
#Timing-Anim-bar::before {
position : absolute;
display : block;
top : 0;
left : 0;
height : 100%;
width : 0%;
content : '';
background : #0cfa2c;
}
#Timing-Anim-bar.showTiming::before {
transition : width 3s linear;
width : 100%;
}
<svg id="hourglass" viewbox="0 0 200 200" class="" >
<circle id="c5" cx="100" cy="100" r="50" stroke-width="5" fill="transparent" />
</svg>
<div id="Timing-Anim-bar"></div>
<br><br>
<button id="btn_test_A">hourglass true</button>
<button id="btn_test_B">hourglass false</button>
<button id="btn_test_C">test Timing_Anim_p</button>
完成图像更改循环代码,但是不使用promise.ALL:
const
img_box = document.querySelector('#img-box')
, imgs_src_list =
[ 'https://picsum.photos/id/124/400/300.webp'
, 'https://picsum.photos/id/146/400/300.webp'
, 'https://picsum.photos/id/155/400/300.webp'
, 'https://picsum.photos/id/219/400/300.webp'
];
var
imgOnLoad = false
, img_index = 0;
;
const
hourglass_elm = document.querySelector('#hourglass')
, Hourglass_f = (run=false) =>
{
hourglass_elm.classList.toggle('showHourglass', run);
}
, Timing_Anim_e = document.querySelector('#Timing-Anim-bar')
, Timing_Anim_p =()=> new Promise( (resolve ) =>
{
Timing_Anim_e.addEventListener('transitionend', ()=>
{
Timing_Anim_e.classList.remove('showTiming');
Hourglass_f(imgOnLoad);
resolve('Timing_Anim_p ended ok');
}
, { once: true }
);
Timing_Anim_e.classList.add('showTiming');
})
, Load_Img_p = (imgScr ) => new Promise( (resolve ) =>
{
imgOnLoad = true;
const img = new Image();
img.onload =()=>{ imgOnLoad = false; resolve( img ) };
img.onerror =()=>{ imgOnLoad = false; resolve( null ) };
img.src = imgScr;
})
, chkBxPlayer = document.querySelector('#chkBx-player')
;
chkBxPlayer.addEventListener('change',()=>
{
if (chkBxPlayer.checked)
{
carousel_Loop();
}
else
{
Hourglass_f(false);
Timing_Anim_e.classList.remove('showTiming');
}
})
async function carousel_Loop()
{
let nxt_src, nxt_imgIdx = img_index
;
while (chkBxPlayer.checked)
{
nxt_imgIdx = ++nxt_imgIdx % imgs_src_list.length;
nxt_src = imgs_src_list[nxt_imgIdx];
await Timing_Anim_p();
if (!chkBxPlayer.checked) break;
Hourglass_f(true);
let newImg = await Load_Img_p( nxt_src );
Hourglass_f(false);
if (!chkBxPlayer.checked) break;
if (newImg===null)
{
chkBxPlayer.checked = false;
console.log('Image loading error', nxt_src );
break;
}
img_index = nxt_imgIdx;
img_box.replaceChildren( newImg );
}
Hourglass_f(false); // some security...
}
body {
background-color: #03063a;
}
#img-box, label {
margin : 20px;
border : 1px whitesmoke solid;
padding : 10px;
width : fit-content;
height : fit-content;
background : lightgrey;
border-radius : 5px;
position : relative
}
#hourglass {
position : absolute;
top : 50px;
left : 50px;
visibility : hidden;
width : 100px;
height : 100px;
stroke : #ff146e;
stroke-dasharray : 80;
stroke-dashoffset : 200;
}
#hourglass.showHourglass {
visibility : visible;
animation : hourglassAnim 1400ms linear infinite alternate;
}
@keyframes hourglassAnim { to { stroke-dashoffset: 0; } }
#Timing-Anim-bar {
width : 500px;
height : 10px;
border : 1px #9acd32 solid;
position : relative;
}
#Timing-Anim-bar::before {
position : absolute;
display : block;
top : 0;
left : 0;
height : 100%;
width : 0%;
content : '';
background : #0cfa2c;
}
#Timing-Anim-bar.showTiming::before {
transition : width 3s linear;
width : 100%;
}
<div id="img-box">
<img src="https://picsum.photos/id/124/400/300.webp" alt="">
<svg id="hourglass" viewbox="0 0 220 220" class="">
<circle cx="110" cy="110" r="50" stroke-width="10" fill="transparent" />
</svg>
</div>
<div id="Timing-Anim-bar"></div>
<br>
<label> <input type="checkbox" id="chkBx-player" > play diaporama </label>
我尝试过,但循环在第一次更改时停止...:/ 怎么了?
const
img_box = document.querySelector('#img-box')
, imgs_src_list =
[ 'https://picsum.photos/id/124/400/300.webp'
, 'https://picsum.photos/id/146/400/300.webp'
, 'https://picsum.photos/id/155/400/300.webp'
, 'https://picsum.photos/id/219/400/300.webp'
];
var
imgOnLoad = false
, img_index = 0;
;
const
hourglass_elm = document.querySelector('#hourglass')
, Hourglass_f = (run=false) =>
{
hourglass_elm.classList.toggle('showHourglass', run);
}
, Timing_Anim_e = document.querySelector('#Timing-Anim-bar')
, Timing_Anim_p =()=> new Promise( (resolve ) =>
{
Timing_Anim_e.addEventListener('transitionend', ()=>
{
Timing_Anim_e.classList.remove('showTiming');
Hourglass_f(imgOnLoad);
resolve('Timing_Anim_p ended ok');
}
, { once: true }
);
Timing_Anim_e.classList.add('showTiming');
})
, Load_Img_p = (imgScr ) => new Promise( (resolve ) =>
{
imgOnLoad = true;
const img = new Image();
img.onload =()=>{ imgOnLoad = false; resolve( img ) };
img.onerror =()=>{ imgOnLoad = false; resolve( null ) };
img.src = imgScr;
})
, chkBxPlayer = document.querySelector('#chkBx-player')
;
chkBxPlayer.addEventListener('change',()=>
{
if (chkBxPlayer.checked)
{
carousel_Loop();
}
else
{
Hourglass_f(false);
Timing_Anim_e.classList.remove('showTiming');
}
})
async function carousel_Loop()
{
let nxt_src, nxt_imgIdx = img_index
;
while (chkBxPlayer.checked)
{
nxt_imgIdx = ++nxt_imgIdx % imgs_src_list.length;
nxt_src = imgs_src_list[nxt_imgIdx];
let resp = await Promise.all([ Timing_Anim_p() , Load_Img_p( nxt_src ) ]);
Hourglass_f(false);
let newImg = resp[1];
if (!chkBxPlayer.checked) break;
if (newImg===null)
{
chkBxPlayer.checked = false;
console.log('Image loading error', nxt_src );
break;
}
img_index = nxt_imgIdx;
img_box.replaceChildren( newImg );
}
Hourglass_f(false); // some security...
}
body {
background-color: #03063a;
}
#img-box, label {
margin : 20px;
border : 1px whitesmoke solid;
padding : 10px;
width : fit-content;
height : fit-content;
background : lightgrey;
border-radius : 5px;
position : relative
}
#hourglass {
position : absolute;
top : 50px;
left : 50px;
visibility : hidden;
width : 100px;
height : 100px;
stroke : #ff146e;
stroke-dasharray : 80;
stroke-dashoffset : 200;
}
#hourglass.showHourglass {
visibility : visible;
animation : hourglassAnim 1400ms linear infinite alternate;
}
@keyframes hourglassAnim { to { stroke-dashoffset: 0; } }
#Timing-Anim-bar {
width : 500px;
height : 10px;
border : 1px #9acd32 solid;
position : relative;
}
#Timing-Anim-bar::before {
position : absolute;
display : block;
top : 0;
left : 0;
height : 100%;
width : 0%;
content : '';
background : #0cfa2c;
}
#Timing-Anim-bar.showTiming::before {
transition : width 3s linear;
width : 100%;
}
<div id="img-box">
<img src="https://picsum.photos/id/124/400/300.webp" alt="">
<svg id="hourglass" viewbox="0 0 220 220" class="" >
<circle cx="110" cy="110" r="50" stroke-width="10" fill="transparent" />
</svg>
</div>
<div id="Timing-Anim-bar"></div>
<br>
<label> <input type="checkbox" id="chkBx-player" > play diaporama </label>
尝试用下面的代码替换,当执行承诺时,“showTiming”在转换结束后立即执行,这样动画就不会重新开始,这只会导致加载一张图像。
setTimeout(() => {
Timing_Anim_e.classList.add('showTiming')
}, 0);