高斯模糊加图片展示(仿ipad qq图片点击展示)

1.前言

       项目中有需要点击展示大图的,然而发现手机端的图片展示更多的是黑色背景+图片展示,最多加上个缩放动画。更让强迫症纠结的是:因为android的本身的原因(从nexus到小米魅族),使用activity进行图片展示会有几率看到statusbar下滑消失动画(对的,没看错,有几率),单单是几率两字就让人纠结不已......随萌生出了些本博客代码——dialog+高斯模糊+图片展示的想法。

效果:

录制看着卡,真机上流畅。

2.高斯模糊

       高斯模糊在苹果系统中很常见,然而在android系统中却鲜有闻,很多app对于高斯模糊的态度是能避免就避免的,究其原因很简单——费时,这里大致讲下高斯模糊的原理:假设一张100*100的图片,上边有10000个像素点,每个像素点作为中心点,按照高斯分布的概率算均值,也就是说,每多一个点,计算时间就会增加很多。闲话不叙,上例子:

这是截的原图。然后,以30个像素点为半径进行高斯模糊:

打印了下log,可以看出耗时是:I/need time: 671 .....(高斯模糊采用的是fastblur方法,如果嫌效率一般,可以考虑用jni,据说速度能降低一半,但是,放在这里的,还是不够)

然而图片并不能让我们满意,虽然有点模糊的意思了,但是感觉还是略微有点棱角......

好吧,那就将半径设为60,看看结果如何:

只能说感觉还好吧,但是用了868ms,上一张我个人比较满意的150的高斯模糊:

然而耗时1156ms.

如果以这种速度去处理图片那就很尴尬了,总不能在做相应操作的时候去等个1s多吧,虽然可以把图片处理放在子线程中,不影响主线程对其他任务的处理,然而这并不是一个靠谱的解决方案,所以决定去尝试下图片压缩:处理速度慢的根本原因是因为想像素数量多,如果我进行压缩呢?

嗯 先上个对比图:

看着差别大么?

一个是长宽压缩过,并进行8像素半径高斯模糊的,一个是原图基础上150高斯模糊的,更喜欢哪个?

左边是原图的,右边是压缩的,压缩后的长宽是原来的十六分之一,更让人高兴的是,压缩+高斯模糊全过程持续了3ms......对没错,一个1156 一个3ms。然而唯一比较遗憾的是,android貌似没有局部截图的工具,如果自己获取整个页面再生成bitmap处理,整个生成bitmap在nexus5上就需要接近40ms,所以暂时来说,没想到有什么好的实时高斯模糊的办法。所以,高斯从淡到完全显示用的是原图上边铺上高斯模糊图,然后alpha动画走起

ok,进入今天的正题,高斯模糊+图片显示

3.高斯模糊背景的图片展示

之前难点都讲的差不多了,直接上代码吧:

import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Rect;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;

import com.example.angusfine.mywidget.R;

/**
 * Created by AngusFine on 2016/3/22.
 */
public class ImagePreviewDialog extends Dialog implements View.OnClickListener{
    private final int animationTime = 250; //动画时间
    private Context context;
    private ImageView targetView; //目标ImageView
    private View mParentView; //DisplayFrame氛围内的RootView
    private int[]location = new int[2]; //targetView 屏幕坐标
    private Bitmap gaussBg; //mParentView高斯的结果
    private ImageView ivGauss;
    private ImageView ivShadow;
    private ImageView ivShow; //targetView展示
    private View currentView; //dialog对应的View
    private int currentW;
    private int currentH;
    private int displayH;
    private Rect rect; //displayframe对应的存储信息
    private boolean vertical = false;
    private boolean backable = true;
    float fY; //动画终点Y坐标
    float dY;
    float fX;
    float dX;

    /**
     *
     * @param context
     * 类中方法调用对应View的绘制顺序,不可修改
     */
    public ImagePreviewDialog(Context context){
        super(context, R.style.GaussDialog);
        this.context = context;
        Log.i("DecordhashCode",String.valueOf(((Activity)context).getWindow().getDecorView().hashCode()));
        ViewGroup decor = (ViewGroup) ((Activity)context).getWindow().getDecorView();
        Log.i("DecordhashCoded",String.valueOf(decor.hashCode()));
        for(int i = 0;i<decor.getChildCount();i++){
            if(decor.getChildAt(i)instanceof LinearLayout){
                ViewGroup ll = (ViewGroup)decor.getChildAt(i);
                for(int j = 0;j<ll.getChildCount();j++){
                    if (ll.getChildAt(j)instanceof FrameLayout){
                        this.mParentView = ll.getChildAt(j);
                        break;
                    }
                }
            }
        }
        initBg();
        getStatusBarInfo();
    }

    public ImagePreviewDialog setTargetView(ImageView view){
        ((Activity)context).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
        targetView = view;
        getImageViewInfo();
        initTargetView();
        initGaussBitmap();
        initAnimation();
        return this;
    }

    /**
     * bg初始化
     */
    private void initBg(){
        currentView = LayoutInflater.from(getContext()).inflate(R.layout.dialog_gauss_bg_pic,null);
        setContentView(currentView);
        ivGauss = (ImageView) currentView.findViewById(R.id.iv_gauss);
        ivShadow = (ImageView) currentView.findViewById(R.id.iv_shadow);
        currentView.setOnClickListener(this);
    }

    /**
     * 获取展示View的对应信息
     */
    private void getImageViewInfo(){
        targetView.getLocationOnScreen(location);
        currentW = targetView.getMeasuredWidth();
        currentH = targetView.getMeasuredHeight();
    }

    /**
     * 状态栏信息
     */
    private void getStatusBarInfo(){
        rect = new Rect();
        ((Activity)context).getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
        displayH = ((Activity)context).getWindow().getDecorView().getMeasuredHeight();
    }

    /**
     * 高斯模糊
     */
    private void initGaussBitmap(){
        gaussBg = convertViewToBitmap(mParentView,mParentView.getWidth(),mParentView.getHeight());
        gaussBg = zoomImage(gaussBg,mParentView.getMeasuredWidth()/16,mParentView.getMeasuredHeight()/16);
        gaussBg = gaussBlur(gaussBg,5,true);
        ivGauss.setImageBitmap(gaussBg);
    }

    /**
     * 加载展示View
     */
    private void initTargetView(){
        FrameLayout.LayoutParams layoutParams= new FrameLayout.LayoutParams(currentW,currentH);
        ivShow = new ImageView(context);
        ivShow.setImageDrawable(targetView.getDrawable());
        ivShow.setX(location[0]);
        ivShow.setY(location[1]-rect.top);
        ivShow.setScaleType(targetView.getScaleType());
        ivShow.setLayoutParams(layoutParams);
        ((ViewGroup)currentView).addView(ivShow);
    }

    private void initAnimation(){
        float w = targetView.getMeasuredWidth();
        float h = targetView.getMeasuredHeight();
        float dw = rect.right - rect.left;
        final float dh = rect.bottom - rect.top;
        float ratio = h/w;
        float dRatio = dh/dw;
        final float maxRatio;
        backable = true;
        ivShadow.setAlpha(0f);
        if(ratio>dRatio){
            vertical = true;
            maxRatio = dh/h;
            fY = ((maxRatio-1)*h)/2;
            dY = location[1]-fY;
            fX = location[0]-dw/2+w/2;
        }else{
            maxRatio = dw/w;
            dY = location[1] - dh/2 +h/2;
            fX = ((maxRatio-1)*w)/2;
            dX = location[0]-fX;
        }
        final AlphaAnimation alphaAnimation = new AlphaAnimation(0.0f,1.0f);
        alphaAnimation.setDuration(animationTime);
        alphaAnimation.setFillAfter(true);
        ObjectAnimator animator = ObjectAnimator.ofFloat(ivShow,"an",1.0f,maxRatio).setDuration(200);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (Float) animation.getAnimatedValue();
                float YDRatio = (cVal-1)/(maxRatio-1);
                float dRatio = 1-YDRatio;
                if(vertical) {
                    ivShow.setScaleX(cVal);
                    ivShow.setScaleY(cVal);
                    ivShow.setX(location[0] - fX * (YDRatio));
                    ivShow.setY(dY * dRatio + fY-rect.top*dRatio);
                }else{
                    ivShow.setY(location[1]-rect.top*dRatio-dY*YDRatio);
                    ivShow.setX(dX*dRatio+fX);
                    ivShow.setScaleX(cVal);
                    ivShow.setScaleY(cVal);
                }
                ivShadow.setAlpha(YDRatio);
            }
        });
        ivGauss.startAnimation(alphaAnimation);
        animator.start();

    }

    private void backAnimation(){
        if(!backable)
            return;
        backable = false;
        float w = targetView.getMeasuredWidth();
        float h = targetView.getMeasuredHeight();
        float dw = rect.right - rect.left;
        final float dh = rect.bottom - rect.top;
        float ratio = h/w;
        float dRatio = dh/dw;
        final float maxRatio;
        if(ratio>dRatio){
            vertical = true;
            maxRatio = dh/h;
        }else{
            maxRatio = dw/w;
            fX = ((maxRatio-1)*w)/2;
            dX = location[0] - fX;
        }
        AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f,0f);
        alphaAnimation.setDuration(animationTime);
        alphaAnimation.setFillAfter(true);
        alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                ivShow.setVisibility(View.GONE);
                ImagePreviewDialog.super.dismiss();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        ObjectAnimator animator = ObjectAnimator.ofFloat(ivShow,"an",maxRatio,1f).setDuration(animationTime);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float cVal = (Float) animation.getAnimatedValue();
                float YDRatio = (cVal-1)/(maxRatio-1);
                float dRatio = 1-YDRatio;
                if(vertical) {
                    ivShow.setScaleX(cVal);
                    ivShow.setScaleY(cVal);
                    ivShow.setX(location[0] - fX * (YDRatio));
                    ivShow.setY(dY * dRatio + fY-rect.top*dRatio);
                }else{
                    ivShow.setY(location[1]-rect.top*dRatio-dY*YDRatio);
                    ivShow.setX(fX+dRatio*dX);
                    ivShow.setScaleX(cVal);
                    ivShow.setScaleY(cVal);
                }
                ivShow.setAlpha(YDRatio);
            }
        });
        animator.start();

        ivGauss.startAnimation(alphaAnimation);
        ivShadow.startAnimation(alphaAnimation);

    }

    @Override
    public void onBackPressed() {
        backAnimation();
    }

    /**
     * 图片缩放
     * @param targetBitmap 目标bitmap
     * @param newWidth  目标宽度
     * @param newHeight  目标高度
     * @return
     */
    private Bitmap zoomImage(Bitmap targetBitmap, double newWidth, double newHeight) {
        float width = targetBitmap.getWidth();
        float height = targetBitmap.getHeight();
        Matrix matrix = new Matrix();
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        matrix.postScale(scaleWidth, scaleHeight);
        Bitmap bitmap = Bitmap.createBitmap(targetBitmap, 0, 0, (int) width, (int) height, matrix, true);
        return bitmap;
    }

    /**
     * View转Bitmap
     * @param view 目标View
     * @param bitmapWidth 宽度
     * @param bitmapHeight 高度
     * @return
     */
    private Bitmap convertViewToBitmap(View view, int bitmapWidth, int bitmapHeight){
        Bitmap bitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888);
        view.draw(new Canvas(bitmap));
        return bitmap;
    }

    /**
     * 高斯模糊
     * @param sentBitmap 目标bitmap
     * @param radius 高斯半径
     * @param canReuseInBitmap  是否原图修改
     * @return
     */
    private Bitmap gaussBlur(Bitmap sentBitmap, int radius, boolean canReuseInBitmap) {
        Bitmap bitmap;
        if (canReuseInBitmap) {
            bitmap = sentBitmap;
        } else {
            bitmap = sentBitmap.copy(sentBitmap.getConfig(), true);
        }

        if (radius < 1) {
            return (null);
        }

        int w = bitmap.getWidth();
        int h = bitmap.getHeight();

        int[] pix = new int[w * h];
        bitmap.getPixels(pix, 0, w, 0, 0, w, h);

        int wm = w - 1;
        int hm = h - 1;
        int wh = w * h;
        int div = radius + radius + 1;

        int r[] = new int[wh];
        int g[] = new int[wh];
        int b[] = new int[wh];
        int rsum, gsum, bsum, x, y, i, p, yp, yi, yw;
        int vmin[] = new int[Math.max(w, h)];

        int divsum = (div + 1) >> 1;
        divsum *= divsum;
        int dv[] = new int[256 * divsum];
        for (i = 0; i < 256 * divsum; i++) {
            dv[i] = (i / divsum);
        }

        yw = yi = 0;

        int[][] stack = new int[div][3];
        int stackpointer;
        int stackstart;
        int[] sir;
        int rbs;
        int r1 = radius + 1;
        int routsum, goutsum, boutsum;
        int rinsum, ginsum, binsum;

        for (y = 0; y < h; y++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            for (i = -radius; i <= radius; i++) {
                p = pix[yi + Math.min(wm, Math.max(i, 0))];
                sir = stack[i + radius];
                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);
                rbs = r1 - Math.abs(i);
                rsum += sir[0] * rbs;
                gsum += sir[1] * rbs;
                bsum += sir[2] * rbs;
                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }
            }
            stackpointer = radius;

            for (x = 0; x < w; x++) {

                r[yi] = dv[rsum];
                g[yi] = dv[gsum];
                b[yi] = dv[bsum];

                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;

                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];

                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (y == 0) {
                    vmin[x] = Math.min(x + radius + 1, wm);
                }
                p = pix[yw + vmin[x]];

                sir[0] = (p & 0xff0000) >> 16;
                sir[1] = (p & 0x00ff00) >> 8;
                sir[2] = (p & 0x0000ff);

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[(stackpointer) % div];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi++;
            }
            yw += w;
        }
        for (x = 0; x < w; x++) {
            rinsum = ginsum = binsum = routsum = goutsum = boutsum = rsum = gsum = bsum = 0;
            yp = -radius * w;
            for (i = -radius; i <= radius; i++) {
                yi = Math.max(0, yp) + x;

                sir = stack[i + radius];

                sir[0] = r[yi];
                sir[1] = g[yi];
                sir[2] = b[yi];

                rbs = r1 - Math.abs(i);

                rsum += r[yi] * rbs;
                gsum += g[yi] * rbs;
                bsum += b[yi] * rbs;

                if (i > 0) {
                    rinsum += sir[0];
                    ginsum += sir[1];
                    binsum += sir[2];
                } else {
                    routsum += sir[0];
                    goutsum += sir[1];
                    boutsum += sir[2];
                }

                if (i < hm) {
                    yp += w;
                }
            }
            yi = x;
            stackpointer = radius;
            for (y = 0; y < h; y++) {
                pix[yi] = (0xff000000 & pix[yi]) | (dv[rsum] << 16) | (dv[gsum] << 8) | dv[bsum];
                rsum -= routsum;
                gsum -= goutsum;
                bsum -= boutsum;
                stackstart = stackpointer - radius + div;
                sir = stack[stackstart % div];
                routsum -= sir[0];
                goutsum -= sir[1];
                boutsum -= sir[2];

                if (x == 0) {
                    vmin[y] = Math.min(y + r1, hm) * w;
                }
                p = x + vmin[y];

                sir[0] = r[p];
                sir[1] = g[p];
                sir[2] = b[p];

                rinsum += sir[0];
                ginsum += sir[1];
                binsum += sir[2];

                rsum += rinsum;
                gsum += ginsum;
                bsum += binsum;

                stackpointer = (stackpointer + 1) % div;
                sir = stack[stackpointer];

                routsum += sir[0];
                goutsum += sir[1];
                boutsum += sir[2];

                rinsum -= sir[0];
                ginsum -= sir[1];
                binsum -= sir[2];

                yi += w;
            }
        }
        bitmap.setPixels(pix, 0, w, 0, 0, w, h);
        return (bitmap);
    }

    @Override
    public void onClick(View v) {
        backAnimation();
    }
}

然后布局代码:

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <ImageView
        android:id="@+id/iv_gauss"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
    <ImageView
        android:id="@+id/iv_shadow"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/transparent_gray"/>

</FrameLayout>

以及style设置:

<style name="GaussDialog">
        <item name="android:windowBackground">@color/transparent</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowFullscreen">false</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:backgroundDimEnabled">false</item>
        <item name="android:background">#00000000</item>
    </style>

色值设置:

<color name="transparent_gray">#88000000</color>

嗯,使用方法很简单,只要两行代码:

imagePreviewDialog = new ImagePreviewDialog(this);
imagePreviewDialog.setTargetView(iv).show();

(第二行代码,需要在目标View显示后进行调用,否则获得的getmeasuredwidth以及高度会为0)

ok,这就完事了

其实这个版本很不完善,当时代码写的很急,后来也因为各种原因没在进行完善,功能上可以做不少的优化及扩展,以后有空再说吧

转帖请标明

时间: 2024-08-01 02:19:31

高斯模糊加图片展示(仿ipad qq图片点击展示)的相关文章

腾讯大牛动态教学:Android 仿微信 QQ 图片裁剪,赶紧收藏起来!

前言 在平时开发中,经常需要实现这样的功能,拍照 - 裁剪,相册 - 裁剪.当然,系统也有裁剪的功能,但是由于机型,系统兼容性等问题,在实际开发当中,我们通常会自己进行实现.今天,就让我们一起来看看怎样实现. 这篇博客实现的功能主要有仿微信,QQ 上传图像裁剪功能,包括拍照,从相册选取.裁剪框的样式有圆形,正方形,九宫格. 主要讲解的功能点 使用说明 整体的实现思路 裁剪框的实现 图片缩放的实现,包括放大,缩小,移动,裁剪等 我们先来看看我们实现的效果图 使用说明 有两种调用方式 第一种 第一种

WPF下的仿QQ图片查看器

本例中的大图模式使用图片控件展示,监听控件的鼠标滚轮事件和移动事件,缩略图和鹰眼模式采用装饰器对象IndicatorObject和Canvas布局.百分比使用一个定时器,根据图片的放大倍数计算具体的数值显示. 首先看看效果图: 以下开始绘制图片 定义缩略图上白色的矩形,这其实是一个Indicator,它的外围是一个Canvas,然后缩略图是一个Image控件 internal class IndicatorObject : ContentControl { private MaskCanvas

CSS3实战开发:仿天猫首页图片展示动画特效实战开发

各位网友大家好,我是陌上花会开,人称陌陌.今天我带领大家开发一个仿天猫首页图片展示动画特效的案例.一如往常,我既不提供源码给大家,也不提供Demo给大家,只是希望大家能跟着我的讲解,然后将代码一步步复制到本地,本人可以保证,页面上的代码复制到本地,绝对百分百运行,且得到与陌陌一样的运行效果.我这么做只为激起大伙的动手能力,望大家能明白我的用心. 好了,不废话了,直接本篇的实战开发吧. 我们看一下我们今天要做的实战案例效果图: 1. 鼠标划过前: 2. 鼠标划过右侧的图片时: 可能大伙看这个静态截

Android 使用ContentProvider扫描手机中的图片,仿微信显示本地图片效果

首先我们先看第一个界面吧,使用将手机中的图片扫描出来,然后根据图片的所在的文件夹将其分类出来,并显示所在文件夹里面的一张图片和文件夹中图片个数,我们根据界面元素(文件夹名, 文件夹图片个数,文件夹中的一张图片)使用一个实体对象ImageBean来封装这三个属性 package com.example.imagescan; /** * GridView的每个item的数据对象 * * @author len * */ public class ImageBean{ /** * 文件夹的第一张图片路

代码: 两列图片瀑布流(一次后台取数据,图片懒加载。下拉后分批显示图片。图片高度未知,当图片onload后才显示容器)

代码: 两列图片瀑布流(一次后台取数据,无ajax,图片懒加载.下拉后分批显示图片.图片高度未知,当图片onload后才显示容器) [思路]: 图片瀑布流,网上代码有多种实现方式,也有各类插件.没找到合意的,所以根据网上找的一段代码,进行了较大改动. 需引用 zepto 或 jquery. 我这个是应用于手机上的,两列瀑布流,图片高度未知——等图片的onloaded事件触发后,才对容器进行计算和定位. 大容器是 $("#imgList"),容器格子是$(".pin"

jquery文档加载几种写法,图片加载写法

jquery文档加载写法: $(function(){ }) ; //个人最常使用方式 $(document).ready(function(){ }); //调用文档对象下的ready方法传入一个函数. $(window).load(function() { });//调用window对象下的load方法传入一个函数. (function() { })(jQuery)//()()表示立即执行 并且传入jquery = $ 所以之前$也可以替换为jQuery 注意: jquery的ready只是

手动屏蔽 QQ 图片广告 教程 适用于任何版本

现在很多软件的免费版都是有广告的,这让原本清清爽爽的界面变得乱七八糟,QQ 虽然没有收费版,但是也要开了会员才能去广告.那不开会员如何屏蔽 QQ 广告呢?早在 QQ2009 Beta 版的时候,可以通过删除一些文件让非会员也能实现去广告的目的,可惜从 QQ2009 正式版起增加了文件完整性检查,删除文件会导致 QQ 无法启动,并且要求重新安装. 这里要介绍的方法,其实只要你对 Windows 操作系统稍有了解就可以轻松搞定!当然也不代表以后所有版本都适用.这个方法仅供大家交流讨论,没有别的想法,

PHP加水印代码 支持文字和图片水印

PHP加图片水印.文字水印类代码,PHP加水印类,支持文字图片水印的透明度设置.水印图片背景透明.自己写的一个类,因为自己开发的一套CMS中要用到,网上的总感觉用着不顺手,希望大家也喜欢这个类,后附有类使用方法. <?php class WaterMask{ public $waterType = 1; //水印类型:0为文字水印.1为图片水印 public $pos = 0; //水印位置 public $transparent = 45; //水印透明度 public $waterStr =

【JavaScript】加载失败的红叉图片处理与&lt;img&gt;图片标签的onerror事件

大家上网的时候肯定见到过加载失败的红叉图片,具体如下图.当然现在Google Chrome与Firefox对其处理会好看一些. 其实可以利用<img>图片标签的onerror事件对其处理的,要求其加载失败之后,马上加载一张默认图片,而不是显示为红叉叉. 其代码如下: <img src="s.png" onerror="javascript:this.src='xx.png';this.width=80;this.height=80;" />