flex加载图片闪白屏

图片锯齿问题
图片闪白屏问题。主要是因为load加载字节数组图片时会产生闪白屏现象

基本思路:
        1. 从一个给定路径加载图片,图片大一点效果会好点。侦探加载过程,显示加载信息
        2. 加载完成删除侦听并显示图片,创建放大镜的实例
        3. 添加为图片添加鼠标事件,根据鼠标移动,点击等不同位置获取位图数据置于放大镜中。

具体代码如下:
1. 创建文本用来显示加载信息
    private function setUpLoadBox():void
    {
         var tf:TextFormat = new TextFormat();
         tf.color = 0xff0000;
         tf.size = 14;
         tf.font = "Arial";
         infoBox = new TextField();
         infoBox.x = 50;
         infoBox.y = 50;
         board.addChild(infoBox);
         infoBox.wordWrap = false;
         infoBox.autoSize = TextFieldAutoSize.LEFT;
         infoBox.type = TextFieldType.DYNAMIC;
         infoBox.border = true;
         infoBox.defaultTextFormat = tf;
         infoBox.mouseEnabled = false;
         infoBox.text = "Hello World!";
    }


2. 加载图片并创建侦听,侦探ProgressEvent和Event事件


        private function startApp():void
        {
               loader = new Loader();
               var url:String = "img/02.jpg";
               var urlRequest:URLRequest = new URLRequest(url);
               loader.load(urlRequest);
               loader.contentLoaderInfo.addEventListener(Event.COMPLETE,initPic);
               loader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS,updateInfo);
              //board.addChild(loader);
  }


3. 计算加载信息


        private function updateInfo(evt:ProgressEvent):void
        {
               infoBox.text = "Loading "+ Math.floor(evt.bytesLoaded/1024).toString()+" KB of " + Math.floor(evt.bytesTotal/1024).toString() + " KB.";
        }


4. 对加载后的图片进行处理


       private function initPic(evt:Event):void
       {
             //加载进来的数据保存在loader对象的content属性中
             //将加载的数据进行位图格式化
            image = Bitmap(loader.content);
            //将位图数据保存到imageData中
            imageData = image.bitmapData;
            //分别保存原始图像的高度和宽度
            dataWidth = image.width;
            dataHeight = image.height;
            //将原始图像按照shrinkFactor进行缩放,即为原来的1/4;
            image.scaleX = shrinkFactor;
            image.scaleY = shrinkFactor;
            //保存缩放为1/4后图片的宽度和高度,很显然picWidth是dataWidth的四分之一
            picWidth = image.width;
            picHeight = image.height;
   
             //image.x = stage.stageWidth/2-picWidth/2;
            //image.y = stage.stageHeight/2-picHeight/2;
   
            //显示图像,删除侦听器,删除loader的引用以释放内存
            board.addChild(image);
            loader.contentLoaderInfo.removeEventListener(Event.COMPLETE,initPic);
            loader.contentLoaderInfo.removeEventListener(ProgressEvent.PROGRESS,updateInfo);
            loader = null;
   
           //负责显示加载信息的文本框清空且不可见
           infoBox.text = "";
           infoBox.visible = false;
   
           //显示放大镜并加阴影滤镜效果
           board.addChild(glass);
           glass.filters = [new DropShadowFilter()];
   
           board.filters = [new DropShadowFilter()];
   
           //建立board的鼠标侦听事件
           setUpListeners();
       }


5. 建立位图的鼠标时间侦听


     private function setUpListeners():void
     {
               board.addEventListener(MouseEvent.ROLL_OUT,boardOut);
               board.addEventListener(MouseEvent.MOUSE_MOVE,boardMove);
               board.addEventListener(MouseEvent.MOUSE_DOWN,boardDown);
               board.addEventListener(MouseEvent.MOUSE_UP,boardUp);
     }


6. 处理当鼠标滑出图片时


      private function boardOut(evt:MouseEvent):void
      {
           //不可拖动
           isDrag = false;
           //清楚放大镜内容
           glassClean();
           //显示光标
           Mouse.show();
      }


7. 处理鼠标释放事件


     private function boardUp(evt:MouseEvent):void
     {
            isDrag = false;
            glassClean();
            Mouse.show();
     }


8. 处理鼠标按下事件


      private function boardDown(evt:MouseEvent):void
      {
             //鼠标相对于board的位置
            var locX:Number = board.mouseX;
            var locY:Number = board.mouseY;
   
            glass.x = locX-glassWidth/2;
            glass.y = locY-glassHeight/2;
            drawInGlass(magFactor*locX,magFactor*locY);
            isDrag = true;
            Mouse.hide();
  }


9. 处理鼠标移动事件,只有在图片上方移动才有效


      private function boardMove(evt:MouseEvent):void
      {
            //鼠标相对于board的位置
            var locX:Number = board.mouseX;
            var locY:Number = board.mouseY;
   
            var goodCoords:Point = getGoodCoords(locX,locY);
            if(isDrag)
            {
                   glass.x = goodCoords.x-glassWidth/2;
                   glass.y = goodCoords.y-glassHeight/2;
                   locX = goodCoords.x;
                   locY = goodCoords.y;
                   drawInGlass(magFactor*locX,magFactor*locY);
                   evt.updateAfterEvent();
            }
       }


10. 单击时根据单击位置创建放大镜,即从大图中提取像素


        //创建放大镜。a,b分别对应于鼠标单击大图时,鼠标在大图上的坐标
        private function drawInGlass(a:Number,b:Number):void
        {
               var curBd:BitmapData;
               var curBmp:Bitmap;
               //分别计算鼠标相对于大图的坐标与放大镜的宽度差值,利用这个差值,可以使单击位置位于放大镜正中。
               var xbeg:Number=a-glassWidth/2;
               var ybeg:Number=b-glassHeight/2;
     
               //鼠标移出左边界
               if(xbeg<0){
                   xbeg=0;
               }
               //上边界
               if(ybeg<0){
                  ybeg=0;
               }
               //右边界和下边界
               if(xbeg>dataWidth-glassWidth){
                      xbeg=dataWidth-glassWidth;
                }
                if(ybeg>dataHeight-glassHeight){
                      ybeg=dataHeight-glassHeight;
                 }
   
                 //根据放大镜大小创建默认位图
                 curBmp=new Bitmap(new BitmapData(glassWidth,glassHeight));
                 //将大图以鼠标单击位置为中心的一块像素复制到放大镜,作为放大镜位图数据
                 curBmp.bitmapData.copyPixels(imageData,new Rectangle(xbeg,ybeg,glassWidth,glassHeight),new Point(0,0));
                 //将放大镜位图数据重新保存到curBd
                 curBd=curBmp.bitmapData;
   
                 //绘制矩形,用curBd进行位图填充
                glass.graphics.clear();
                glass.graphics.lineStyle();
                glass.graphics.beginBitmapFill(curBd);
                glass.graphics.drawRect(0,0,glassWidth,glassHeight);
                glass.graphics.endFill();
       }
  
       //清除放大镜中的位图填充
       private function glassClean():void
       {
              glass.graphics.clear();
       }


11. 鼠标移动时创建放大镜范围限制


       //计算放大镜在大图上显示的范围确保不显示大图以外的数据,a,b分别为单击时相对于大图的坐标
       private function getGoodCoords(a:Number,b:Number):Point
       {
              var goodCoords:Point = new Point();
              goodCoords.x = a;
              goodCoords.y = b;
              if(a>picWidth-glassWidth/(2*magFactor))
              {
                    goodCoords.x = picWidth-glassWidth/(2*magFactor);
              }
              if (a < glassWidth/(2*magFactor))
              {
                   goodCoords.x = glassWidth/(2*magFactor);
              }
              if (b < glassHeight/(2*magFactor)){
                   goodCoords.y = glassHeight/(2*magFactor);
              }
              if (b > picHeight-glassHeight/(2*magFactor)){
                   goodCoords.y = picHeight-glassHeight/(2*magFactor);
              }
              return goodCoords;
       }


12. 程序初始化


       private function init():void
       {
               //实例化装载图片的容器
               board = new Sprite();
               //实例化放大镜
               glass = new Sprite();
               //显示图片容器
               addChild(board);
               //设置容器坐标
               board.x=75;
               board.y=70;
               //创建文本显示加载信息
               setUpLoadBox();
               //加载图片
               startApp();
      }


 


总结:


         1. 加载图片时需要用URLRequest类封装路径,将路径作为字符串传给URLRequest类的构造函数即可。
         2. 图片的加载由Loader类负责,Loader类的load方法需要传递一个URLRequest实例以便告诉Loader要加载图片的路径。
         3. 图片加载过程中需要侦听contentLoaderInfo的ProgressEvent和Event.COMPLETE事件。ProgressEvent的bytesLoaded和bytesTotal属性分别返回已加载的字节和总字节;Event.COMPLETE事件是在图片完全加载完成后触发。
         4. 加载完成的图片被保存在Loader实例的content属性中,要处理加载进来的图片只需返回content属性值,加载的是图片,则content类型为Bitmap,如果是SWF文件,则content类型为movieclip。
         5. 图片加载完成后要删除对ProgressEvent和Event.COMPLETE事件的侦听。
         6. 如果要修改放大镜的形状,可以更改glass.graphics.drawRect(0,0,glassWidth,glassHeight);一句,如:改为圆形glass.graphics.drawCircle(glassWidth/2,glassWidth/2,glassWidth/2);
在 Vue 项目中,首页加载时出现白屏是一个常见的用户体验问题,尤其在数据请求和资源加载较多时更为明显。为了解决这一问题并提升用户感知体验,可以通过添加一个 loading 框来填补页面渲染前的空白时间。 ### 添加 Loading 框的方式 1. **在 `index.html` 中直接插入静态 loading 元素** 在项目的入口 HTML 文件中,可以直接在挂载点内部添加一个 loading 提示元素。这样可以在 Vue 应用尚未完成初始化之前显示一个简单的加载状态[^1]。 ```html <body> <div id="app"> <!-- 静态 loading 提示 --> <div class="self-loading">页面正快马加鞭赶来,请耐心等待</div> </div> </body> ``` 当 Vue 应用初始化完成后,该 loading 元素会被自动替换为实际内容,从而实现一种轻量级的加载过渡效果。 2. **使用骨架屏(Skeleton Screen)替代传统 loading 动画** 对于更复杂的场景,可以考虑使用骨架屏技术。它能提供比简单 loading 更接近最终页面结构的占位效果,让用户感知到页面正在加载而不是完全空白[^1]。 3. **结合 `requestAnimationFrame` 控制 loading 显示与隐藏** 在 Vue3 项目中,可以利用 `requestAnimationFrame` 来优化 loading 的显示逻辑,确保其在合适的时机被移除,避免视觉上的闪烁或延迟[^2]。 ```javascript const app = createApp(App); const loadingEl = document.querySelector('.self-loading'); requestAnimationFrame(() => { // 模拟异步操作完成后隐藏 loading setTimeout(() => { if (loadingEl) { loadingEl.style.display = 'none'; } }, 1000); // 根据实际情况调整 }); app.mount('#app'); ``` 4. **使用懒加载插件优化首屏资源加载** 对于图片等大体积资源,建议使用 `vue-lazyload` 插件进行懒加载处理,减少首屏加载的数据量,从而缩短白屏时间[^3]。 ```javascript import VueLazyload from 'vue-lazyload'; import loading from '@/assets/images/load.jpg'; Vue.use(VueLazyload, { loading: loading, error: '@/assets/images/error.jpg' }); ``` 5. **检查构建配置与路由设置** 确保 `index.html` 正确设置了挂载点,并且构建后的 JS 文件被正确引入。同时,检查 Vue Router 的配置是否合理,避免因路由异步加载导致的长时间白屏现象[^4]。 --- ### 示例:完整的 loading 组件实现 以下是一个基于 Vue3 的组件化实现方式,结合了 `ref` 和生命周期钩子来控制 loading 的显示与隐藏: ```vue <template> <div v-if="isLoading" class="loading-overlay"> <div class="spinner"></div> <p>加载中,请稍候...</p> </div> </template> <script setup> import { ref, onMounted } from 'vue'; const isLoading = ref(true); onMounted(() => { // 模拟异步加载完成 setTimeout(() => { isLoading.value = false; }, 1500); }); </script> <style scoped> .loading-overlay { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: #fff; display: flex; flex-direction: column; justify-content: center; align-items: center; z-index: 9999; } .spinner { border: 4px solid rgba(0, 0, 0, 0.1); border-top: 4px solid #3498db; border-radius: 50%; width: 40px; height: 40px; animation: spin 1s linear infinite; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } </style> ``` 将上述组件作为全局或局部组件引入后,在主应用中即可通过控制 `isLoading` 的值来切换 loading 状态。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值