设置了width:100%,移动设备上宽度还是现实不正确

本文介绍了一种在网页中设置视口元标签的方法,确保页面能在不同设备上正确显示。具体涉及的代码为<metaname=viewportcontent=width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scalable=no>,同时提到设计图尺寸需减半处理。

需要加如下代码

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">

和设计图的尺寸要减半

<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>-</title> <style> body { margin: 0; padding: 0; overflow: hidden; } .container { position: relative; display: flex; width: 1920px; height: 900px; overflow: hidden; cursor: pointer; top:220px; } .box { position: absolute; width: 500px; white-space: nowrap; /* left: 0; */ text-align: center; /* 让内容居中 */ } .image-container { /* border: 1px solid #ddd; */ border-radius: 4px; padding: 5px; text-align: center; transition: transform 0.3s; } .image-container img { max-width: 100%; height: auto; max-height: 150px; } .loading { text-align: center; font-size: 18px; color: #666; margin: 20px 0; } .bg { width: 1920px; height: 1080px; background-image: url(img/bg.jpg); } </style> </head> <body> <div class="bg"> <div id="loading" class="loading">正在加载图片...</div> <div class="container" id="container"></div> <div style="float: right; margin-right: 100px;margin-top: 20px; position: relative;z-index: 999;"> <a href="index.html"><img style="" src="img/btn1.png" alt="" /></a> <a href="qianzi.html"><img style="" src="img/btn2.png" alt="" /></a> </div> </div> <script> document.addEventListener('DOMContentLoaded', function () { const container = document.getElementById('container'); const loadingElement = document.getElementById('loading'); fetch('images/') .then(response => { if (!response.ok) { throw new Error(`目录请求失败,状态码:${response.status}`); } return response.text(); }) .then(html => { const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const links = doc.querySelectorAll('a[href]'); const imageFiles = Array.from(links) .map(link => link.getAttribute('href')) .filter(file => /\.(jpg|jpeg|png|gif|webp)$/i.test(file)); if (imageFiles.length === 0) { loadingElement.textContent = '未找到图片文件'; return; } loadingElement.style.display = 'none'; // 动态创建box,每个box一个图片 const boxWidth = 400; const boxHeight = 200; // 估算高度,图片150 + padding + border + margin,实际可根据需要调整 const gapX = 0; // 列间距 const gapY = 50; // 行间距 const boxesPerColumn = 3; imageFiles.forEach((file, index) => { const box = document.createElement('div'); box.className = 'box'; // 计算列号和行号 const col = Math.floor(index / boxesPerColumn); const row = index % boxesPerColumn; // 设置left和top box.style.left = `${col * (boxWidth + gapX)}px`; box.style.top = `${row * (boxHeight + gapY)}px`; const imageContainer = document.createElement('div'); imageContainer.className = 'image-container'; const img = document.createElement('img'); img.src =file; imageContainer.appendChild(img); box.appendChild(imageContainer); container.appendChild(box); }); // 动画逻辑 const boxes = document.getElementsByClassName('box'); function moveBox(element, delay, distance) { setTimeout(() => { // 开始平滑移动 element.style.transition = 'transform 30s linear'; element.style.transform = `translateX(-${distance}px)`; // 20秒后,取消动画,瞬间回到起点 setTimeout(() => { element.style.transition = 'none'; element.style.transform = 'translateX(0)'; // 强制浏览器渲染,触发重绘 element.offsetHeight; // 读取offsetHeight强制重绘 // 重新开始动画 moveBox(element, 0, distance); }, 20000); }, delay); } // 给每行box设置同的延迟,避免同时移动 // 计算移动距离 const totalColumns = Math.ceil(imageFiles.length / boxesPerColumn); const containerWidth = 1920; const totalWidth = totalColumns * (boxWidth + gapX); const distance = containerWidth + totalWidth; Array.from(boxes).forEach((box, idx) => { if(idx%3==0){ moveBox(box, 1900, distance);//控制第一行延迟 }else if((idx+1)%3==0){ moveBox(box, 1400, distance);//控制第三行延迟 }else{ moveBox(box, 1100, distance);//控制第二行延迟 } }); }) .catch(error => { console.error('获取图片失败:', error); loadingElement.textContent = '加载图片失败,请确保通过本地服务器运行此页面'; }); }); </script> </body> </html> 这个是我的图片动效代码,我现在需要改变代码获取图片方式的前提下,让代码的循环更加流畅丝滑
最新发布
06-08
<think>我们目前有一个问题:动画循环在每次20秒后重置时会有明显的跳跃感,因为采用了瞬间回到起点的方式。这会导致动画够流畅丝滑。解决方案:我们可以使用两个相同的副本(duplicateset)来无缝循环,而是在移动后跳回起点。这样,当一组元素移出视图时,另一组元素正好进入视图,从而实现连续滚动。然而,现有的代码结构是每个图片都是一个单独的.box元素,并且按行列排列。我们想要实现的效果是让每一列的盒子(每个列有三个图片)作为一个整体从左向右移动(实际上是向左移动,因为translateX为负)。但是,请注意我们的布局:图片是按列布局的,每列有3个图片(即每列3行)。目前,每个box是绝对定位,按照列和行定位。为了让动画更流畅,我们可以将每一列(包含三个图片)包裹在一个组(.column)中,然后让这些列连续向左移动。当第一列完全移出容器时,我们将其移动到队列的末尾,并重置位置,而是使用一个跳回起点的动画。但是,由于代码中获取图片后动态创建box,并且每个box是独立的,所以我们需要重新组织DOM结构:将每一列(每列3个图片)放入一个容器(.column)中。然后,我们创建两个相同的列组(这样可以无缝循环)。然而,考虑到改动较大,且要求改变获取图片的方式,我们可以尝试另一种方法:方法:使用CSS动画实现无限滚动,并且利用重复的DOM元素(即复制一份整个图片列表)来达到无缝衔接。具体步骤如下:1.将所有的列(每列3个图片)放在一个大的水平排列的容器(.slider)中,这个容器宽度足够容纳所有列(包括复制的列)。2.复制一份整个列,放在后面(这样当第一份的列滚动出容器时,复制的列正好进入,这时我们再将整个容器重置位置,由于是连续的,所以视觉上是无缝的)。3.使用CSS动画让这个容器向左移动(相当于容器向右滚动)。但是,由于我们目前的DOM结构是绝对定位,每个box独立,要改成这样的结构需要较大调整。另一种思路:使用纯CSS的animation动画,利用关键帧实现无限滚动,但是每一列作为一个整体移动。我们可以将每一列的三个box用一个div包裹起来,作为列容器,然后让这些列容器水平排列。修改步骤:1.修改动态创建DOM的部分:将图片文件按照每3个一组分组(因为每列3个),每组创建一个.column元素,然后把每组的3个图片放入该.column中。2.将所有的列容器复制一份,这样我们就有两份相同的列(这样当第一份的列全部移出后,第二份的列刚好进入)。3.然后让一个包含这两份列的大容器(.slider)做动画,动画效果是向左移动整个大容器宽度的50%(即一份列的总宽度),然后重置(但是用动画循环,我们可以用CSS关键帧实现无限滚动)。4.但是为了避免在移动完第一份列后跳转到开头,我们可以使用两个相同的副本进行无限循环,当第一份列完全移出时,第二份列正好进入视野,而此时我们重置位置(在动画中设置关键帧:从0%移动到最后,然后跳回0%,但因为有第二份的存在,跳回时第二份刚好接上第一份的开头,视觉无缝)。然而,考虑到性能,我们也可以使用JavaScript动态调整位置来实现无限循环,但为了流畅性,我们采用复制内容并使用CSS动画的方法。但是,由于要求改变图片获取方式,我们可以在获取图片后对数据进行分组,并创建两倍的分组(复制一份),然后使用CSS关键帧动画。具体实现计划:第一步:将图片列表按每3个一组分组(因为每列3个)。最后一组可能足3个,但我们复制时保持原样,因为两份合起来后最后会回到开头。第二步:创建两个相同的分组数组,合并为一个数组(即两份连续的图片)。第三步:在DOM中,将合并后的数组(即两份分组)创建为列(.column)元素,每个列包含3个图片(box)。第四步:计算整个容器的总宽度(所有列宽度之和)。每个列的宽度为boxWidth+gapX,列的总数为分组数*2(因为我们复制了一份)。第五步:设置一个水平方向足够宽的大容器(.slider)来包含这些列,并设置这个.slider的宽度为总宽度。第六步:使用CSS关键帧动画,让.slider从初始位置移动到总宽度的一半(因为有两份,移动一份的宽度就能让第二份的第一列正好在可视区域的开头)。然后我们设置动画循环。第七步:在动画结束时,我们可以让动画重置到0,但是由于我们有两份,当第一份移出时,第二份刚好进入,所以在动画结束重置时是瞬间跳回0,但是因为第二份和第一份一样,所以跳回0的时候第二份的开头正好在视图区域,所以是连续的。但是,这样我们就需要JavaScript来控制动画了,而是使用CSS动画无限循环。调整代码:1.在container里面创建一个大容器(.slider),这个容器将包含所有的列(每列三个图片),并且复制一份同样的列。2.设置.slider的动画为从左到右移动(实际上我们需要向左移动,所以是translateX为负值)。3.动画关键帧设置:0%{transform:translateX(0);}100%{transform:translateX(-50%);}//因为有两份,移动第一份的宽度(也就是总宽度的50%)4.设置animation:infiniteSlider20slinearinfinite;//20秒一次循环5.为了无缝,当动画到达100%时(此时刚好第一份移出,第二份完全在可视区域),然后立即重置回0%(但是重置是瞬间的,因为CSS动画默认循环就是这样),因为第二份内容和第一份一样,所以看起来就是连续的。6.但是注意:我们在创建列的时候,每一列的图片顺序要和第一份一样。但是,这样做的一个问题是:我们需要确保列的数量乘以列宽小于或等于整个.slider的宽度,并且列的排列是连续的。由于我们原有的布局是绝对定位,现在要改成浮动或行内块排列。另外,我们现有的代码中,每个box是绝对定位,现在要改为相对定位,并且每个列(.column)应该是行内块元素或者浮动元素。修改步骤:1.隐藏loading后,创建一个新的div作为slider,并将其append到container中。2.将图片文件按照每3个分组(最后一组可能足3个)。3.创建两个相同组的数组,然后遍历这个长数组,创建列,每个列内创建3个box(如果最后一组足三个,就创建实际的个数)。4.设置列(.column)的样式为display:inline-block;vertical-align:top;这样列会水平排列。5.设置每个列中的box的样式,现在我们再需要绝对定位,而是按照正常流排列,每个box就是一个块元素,这样自然排列在列中。6.设置slider的宽度为(列数*(boxWidth+gapX)),然后设置动画。7.设置container的宽度为1920px,overflow:hidden,这样只显示一屏,其他部分隐藏。另外,考虑到原有代码的动画延迟,我们再需要为每个box设置同的延迟,因为整个列是一起移动的。但是,我们也可以为每一列设置同的移动速度,过按照我们的需求,希望整体丝滑,所以整个slider一起移动。代码修改:由于改动较大,我将逐步修改代码:首先,我们修改动态创建DOM的部分:(1)将图片分组,每3个一组:letgroups=[];for(leti=0;i< imageFiles.length;i+=3){groups.push(imageFiles.slice(i,i+3));}(2)复制这个分组数组:letdoubleGroups=groups.concat(groups);//两份连续的分组(3)创建.slider容器:constslider=document.createElement('div');slider.className='slider';(4)计算每一列的宽度:boxWidth+gapX(原代码中gapX是0,所以列宽就是boxWidth=500px)但是注意,我们的boxWidth是500px,但是在原有代码中,每个box是400px?不对,原有代码boxWidth=400px(在创建box时用了一个boxWidth=400,然后列间距gapX=0)?但是,我们原有代码中每个.box是绝对定位,left按列设置:col*(boxWidth+gapX)->400px一列。现在也要按400px宽来设置列?是的。(5)设置每个列(.column)的宽度为400px(和原来的box宽度一致),并设置为行内块元素。(6)遍历doubleGroups,创建列,每列中遍历该列的图片(最多3个)创建box(.box)元素,并加入列中。(7)然后设置slider的宽度:doubleGroups.length*400px(因为gapX=0),然后设置slider的动画。(8)将slider加入到container中。(9)设置container的高度(为了能显示3行,每行高度为boxHeight+gapY)?因为每一列是竖直排列3个box,所以列的高度应该是自然高度(3个box的高度加上各自的间距)。但是我们希望container高度固定,这样溢出隐藏。另外,原有每个box的高度设置:boxHeight=200px(估算值),但我们原有每个图片容器(.image-container)的高度包括图片(150px)和padding等,所以列的高度可能会超出。为了保持布局,我们设置列内每个box的样式,去掉绝对定位,设置正常流,并设置垂直间距(gapY)。由于改动较大,我将在代码中详细注释。但是,需要注意的是,我们要求改变获取图片的方式,所以获取图片的代码保留。下面我们重新编写代码(只修改script部分)。由于原有代码中使用了绝对定位布局,现在要改为浮动布局,为了保持图片垂直方向上的间距,我们需要调整样式。考虑到时间,我们改变原有box的样式,而是重新调整。修改后的样式:.container{...其他样式保持变overflow:hidden;/*隐藏超出部分*/display:block;/*默认flex改成block,因为我们内部需要水平滚动的行内块*/}.slider{position:absolute;top:0;left:0;height:100%;/*和container一样高*/white-space:nowrap;/*使列水平排列*//*宽度由JavaScript计算,动态设置*/}.column{display:inline-block;vertical-align:top;width:400px;/*和原有boxWidth一样*/padding:0;margin:0;/*注意:这里我们设置高度,高度由内容撑开*/}.box{position:relative;/*改为相对定位,这样会按照正常流排列*/display:block;width:100%;/*让每个box占满列宽*//*注意:原有的white-space和text-align保留*/text-align:center;margin-bottom:50px;/*使用gapY=50px作为底部间距,最后一列可以用,但为了简单,都加*/}.box:last-child{margin-bottom:0;/*最后一列要底部间距*/}.image-container{...变}然后修改JavaScript部分:在获取图片文件后://分组constimagesPerColumn=3;letgroups=[];for(leti=0;i<imageFiles.length;i+=imagesPerColumn){groups.push(imageFiles.slice(i,i+imagesPerColumn));}letdoubleGroups=[...groups,...groups];//两份//创建sliderconstslider=document.createElement('div');slider.className='slider';//设置slider宽度:列数*每列宽度constcolumnWidth=400;constgapX=0;constsliderWidth=doubleGroups.length*columnWidth;slider.style.width=`${sliderWidth}px`;//创建列和boxdoubleGroups.forEach((group,colIndex)=>{constcolumn=document.createElement('div');column.className='column';group.forEach((file,rowIndex)=>{constbox=document.createElement('div');box.className='box';constimageContainer=document.createElement('div');imageContainer.className='image-container';constimg=document.createElement('img');img.src=file;imageContainer.appendChild(img);box.appendChild(imageContainer);column.appendChild(box);});slider.appendChild(column);});//将slider添加到container中container.appendChild(slider);//隐藏loadingloadingElement.style.display='none';//然后设置动画:使用CSS动画//定义动画关键帧conststyle=document.createElement('style');style.innerHTML=`@keyframesinfiniteSlider{0%{transform:translateX(0);}100%{transform:translateX(-${groups.length*columnWidth}px);}}.slider{animation:infiniteSlider20slinearinfinite;}`;document.head.appendChild(style);注意:这样创建的动画是20秒移动一份图片(第一份),然后第二份紧跟着就接上了,因为动画结束时会瞬间跳回0(默认CSS动画循环的特性),但我们希望从第一份开始移动,当第一份移出时第二份已经在可视区域了,所以当动画结束时跳回0(也就是第二份出现在第一份原来的位置)因为第二份和第一份内容一样,所以用户会察觉。但是,这样写动画会立即开始,所以是连续滚动。但是,这种方式可能会有个小问题:在动画结束瞬间跳回原点,但因为有两份内容,所以跳回原点时显示的是第一份内容,但第一份内容已经移出视窗,而第二份内容正好在视窗内,所以跳回原点后动画重新开始,显示的是第一份内容(其实此时第二份内容位于原点,而第一份内容已经移出了)。所以我们需要设置动画的起点和终点,确保动画结束跳回0时,显示的内容是第二份(这样才会无缝)。实际原理:在动画开始时,我们能看到第一份内容,然后移动距离为groups.length*columnWidth(即第一份的总宽度)后,第一份完全移出,第二份完全进入视窗。然后动画结束,回到0(即第一份的位置),这时我们看到的第二份内容瞬间变成了第一份内容的位置(但因为内容相同,所以看起来是连续的)。但是,跳回0的过程是瞬间的,因此我们希望在跳回0的时候,用户看到的是第二份内容正好覆盖第一份内容的位置(这样就会有跳跃感)。实际上,当动画开始移动时,第二份内容是在第一份内容右侧并排排列。当移动了第一份的宽度后,视窗中显示的是第二份内容。然后动画结束时回到0,这时第二份内容被瞬间拉回到视窗的起始位置(也就是原本第一份内容的位置),而第二份内容正好和第一份内容相同,所以是连续的。因此,这个方案可行。但是,注意:列数较多时,复制一份可能会导致DOM元素过多,性能问题。过列数多的话(比如100列,复制一份200列)应该问题大。另外,由于CSS动画是使用transform:translateX,所以性能较好(GPU加速)。我们需要修改.container的样式,将display:flex去掉,因为我们现在使用绝对定位的.slider(在container里面)并且需要水平排列,所以container的样式调整为:.container{position:relative;width:1920px;height:900px;overflow:hidden;/*隐藏超出的部分*/cursor:pointer;top:220px;/*去掉flex*/display:block;}现在,我们修改代码。但是,由于原有代码中为每个box设置的动画逻辑(moveBox函数)需要删除,所以我们只保留分组、创建列和CSS动画的部分。另外,为了确保样式正确,我们需要调整.box的样式,去掉原有的绝对定位,并设置正常的块级元素。修改后的完整script部分:(由于原有代码较多,我只修改从fetch成功后处理的部分)注意:我们仍然要确保图片加载错误处理,以及没有图片的情况。下面是修改后的代码(从fetch成功后开始):fetch('images/').then(response=>{//...同上}).then(html=>{//解析html,获取图片文件数组imageFiles(同上)//分组constimagesPerColumn=3;constgroups=[];for(leti=0;i<imageFiles.length;i+=imagesPerColumn){groups.push(imageFiles.slice(i,i+imagesPerColumn));}//如果groups为空,则没有图片if(groups.length===0){loadingElement.textContent='未找到图片文件';return;}loadingElement.style.display='none';//创建slider容器constslider=document.createElement('div');slider.className='slider';//双份组constdoubleGroups=[...groups,...groups];constcolumnWidth=400;//和原来每个box的宽度一致consttotalWidth=doubleGroups.length*columnWidth;slider.style.width=`${totalWidth}px`;//创建列doubleGroups.forEach((group,colIndex)=>{constcolumn=document.createElement('div');column.className='column';group.forEach((file,rowIndex)=>{constbox=document.createElement('div');box.className='box';constimageContainer=document.createElement('div');imageContainer.className='image-container';constimg=document.createElement('img');img.src=file;imageContainer.appendChild(img);box.appendChild(imageContainer);column.appendChild(box);});slider.appendChild(column);});container.innerHTML='';//清空container(原本有loading,但已经隐藏)container.appendChild(slider);//添加CSS动画conststyle=document.createElement('style');constanimationDuration=20;//20秒完成一次移动consttranslateDistance=groups.length*columnWidth;//移动距离等于第一份的宽度style.textContent=`@keyframesinfiniteSlider{0%{transform:translateX(0);}100%{transform:translateX(-${translateDistance}px);}}.slider{animation:infiniteSlider${animationDuration}slinearinfinite;}`;document.head.appendChild(style);}).catch(error=>{//...同上});最后,我们还需要调整CSS样式:.bg的宽高可能需要调整,以及.container的样式调整。另外,为了垂直方向上的排列,我们调整.box的样式,去掉原有的left/top,改为正常流,并设置margin-bottom作为垂直间隔。我们修改一下样式:<style>/*原有的变,修改或添加以下内容*/.container{/*...*/display:block;/*覆盖flex*/position:relative;/*为了slider绝对定位*/}.slider{position:absolute;top:0;left:0;height:100%;/*和container高度一致*/white-space:nowrap;/*水平排列*/}.column{display:inline-block;vertical-align:top;width:400px;/*列宽*/padding:0;margin:0;}.box{/*去掉绝对定位*/position:relative;width:100%;display:block;white-space:nowrap;text-align:center;margin-bottom:50px;/*相当于gapY*/}.box:last-child{margin-bottom:0;}.image-container{/*保持原有*/}.image-containerimg{/*保持原有*/}</style>但是,注意这样设置后,每一列中的图片是垂直排列的,而原先的设计是每列三个图片,所以这样符合。由于每一列中可能有3个(或更少)box,每个box之间有50px的间隔(即gapY),因此整个列的高度为:(boxHeight+50px)*3-50px(因为最后一个没有底部margin),boxHeight包括图片高度(150px)和padding等,所以每个box的实际高度可能超过150px。我们需要确保.container的高度足够容纳3个box和2个间隙(50px的间隙有两个,所以总高度大概是3*boxHeight+2*50px)。目前.container的高度为900px,应该足够。最后,原有代码中的两个按钮(index.html和qianzi.html)的位置,我们需要修改。这个方案可能会增加一些DOM元素,但通常浏览器可以处理。由于改动较大,如果出现布局问题,可能需要微调。另外,我们删除了原有的动画逻辑(moveBox函数),所以会出现原来20秒后重置动画的跳跃感。现在,我们使用CSS动画实现无限循环滚动,更加平滑。注意:如果图片数量是3的倍数,最后一列可能只有1或2个图片,这会影响布局,因为每个box还是占满列宽。但是,复制两份后,第二份中的最后一列同样可能会少。这也影响动画效果。请尝试这个方案,如果有问题再调试。由于我们是在.stackoverflow上,所以提供完整代码修改是现实的,但以上是思路和关键代码修改部分。为了便于理解,下面提供修改后的完整HTML和JS代码(仅script部分和style部分)的修改。</think> 为了使图片滚动效果更流畅丝滑,我建议使用以下优化方案: ### 优化方案: 1. **使用CSS动画替代JavaScript动画**:CSS动画性能更好,可利用GPU加速 2. **无缝循环技术**:复制一份相同的元素放在原元素后面,实现无缝滚动 3. **避免重排和重绘**:使用transform和opacity等会引起重排的属性 4. **优化初始加载**:添加加载过渡效果 ### 修改后的代码: ```html <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>图片滚动优化</title> <style> body { margin: 0; padding: 0; overflow: hidden; } .container { position: relative; display: flex; width: 1920px; height: 900px; overflow: hidden; cursor: pointer; top: 220px; } .box { position: absolute; width: 500px; white-space: nowrap; text-align: center; /* 添加GPU加速 */ will-change: transform; backface-visibility: hidden; } .image-container { border-radius: 4px; padding: 5px; text-align: center; transition: transform 0.3s; } .image-container img { max-width: 100%; height: auto; max-height: 150px; } .loading { text-align: center; font-size: 18px; color: #666; margin: 20px 0; transition: opacity 0.5s; } .bg { width: 1920px; height: 1080px; background-image: url(img/bg.jpg); } /* 新添加的动画样式 */ .animate-slide { animation: slide 20s linear infinite; transform: translate3d(0, 0, 0); /* GPU加速 */ } @keyframes slide { 0% { transform: translateX(0); } 100% { transform: translateX(-1920px); } } .slide-container { display: flex; min-width: 200%; height: 100%; } .slide-group { display: flex; width: 100%; } </style> </head> <body> <div class="bg"> <div id="loading" class="loading">正在加载图片...</div> <div class="container" id="container"> <!-- 新的滑动结构 --> <div class="slide-container" id="slideContainer"> <div class="slide-group" id="slideGroup1"></div> <div class="slide-group" id="slideGroup2"></div> </div> </div> <div style="float: right; margin-right: 100px; margin-top: 20px; position: relative; z-index: 999;"> <a href="index.html"><img style="" src="img/btn1.png" alt="" /></a> <a href="qianzi.html"><img style="" src="img/btn2.png" alt="" /></a> </div> </div> <script> document.addEventListener('DOMContentLoaded', function() { const container = document.getElementById('container'); const loadingElement = document.getElementById('loading'); const slideContainer = document.getElementById('slideContainer'); const slideGroup1 = document.getElementById('slideGroup1'); const slideGroup2 = document.getElementById('slideGroup2'); fetch('images/') .then(response => { if (!response.ok) { throw new Error(`目录请求失败,状态码:${response.status}`); } return response.text(); }) .then(html => { const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const links = doc.querySelectorAll('a[href]'); const imageFiles = Array.from(links) .map(link => link.getAttribute('href')) .filter(file => /\.(jpg|jpeg|png|gif|webp)$/i.test(file)); if (imageFiles.length === 0) { loadingElement.textContent = '未找到图片文件'; return; } // 创建图片元素 const createImageElement = (file) => { const imageContainer = document.createElement('div'); imageContainer.className = 'image-container'; const img = document.createElement('img'); img.src = file; img.onload = () => img.style.opacity = 1; // 加载后淡入 img.style.opacity = 0; // 初始透明 img.style.transition = 'opacity 0.5s'; imageContainer.appendChild(img); return imageContainer; }; // 填充滑动组 const createSlideGroup = (groupElement) => { imageFiles.forEach(file => { const imageElement = createImageElement(file); groupElement.appendChild(imageElement); }); }; // 为两个滑动组添加相同的内容 createSlideGroup(slideGroup1); createSlideGroup(slideGroup2); // 渐隐加载提示 loadingElement.style.opacity = 0; setTimeout(() => { loadingElement.style.display = 'none'; }, 500); // 添加滑动动画 slideContainer.classList.add('animate-slide'); // 重置动画位置 slideContainer.addEventListener('animationiteration', () => { slideContainer.style.transform = 'translateX(0)'; }); }) .catch(error => { console.error('获取图片失败:', error); loadingElement.textContent = '加载图片失败,请确保通过本地服务器运行此页面'; }); }); </script> </body> </html> ``` ### 优化解释: 1. **CSS动画替代JS动画**: - 使用`@keyframes`定义了平滑的滑动动画 - `transform: translateX()`代替直接操作left/top属性,利用GPU加速 - 添加`will-change: transform`和`backface-visibility: hidden`优化渲染 2. **无缝循环技术**: - 创建两个相同的图片组(.slide-group) - 设置容器宽度为200%(包含两个完整副本) - 动画移动到100%时重置位置实现无缝循环 3. **加载优化**: - 图片加载后使用opacity淡入效果 - 加载提示使用透明度过渡消失 - 避免使用绝对定位布局 4. **避免强制重排**: - 使用transform进行动画而是修改left属性 - 避免在循环中读取offsetHeight等会触发重排的属性 5. **内存管理**: - 移除了原有的定时器逻辑 - 使用animationiteration事件处理重置,无内存累积 ### 关键优化点: 1. 使用纯CSS动画(GPU加速)替代JS操作DOM 2. 双容器复制技术实现无缝滚动 3. transform代替position布局(避免重排) 4. 图片加载淡入效果提升用户体验 5. 精简的事件处理机制
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值