Asp.Net MVC2 控件开发实例(3)

Asp.Net MVC2 控件开发实例(1)

Asp.Net MVC2 控件开发实例(2)

 

    这次是一个图片控件,实现轮播、上传、删除、修改以及点击时放大等功能。 先来看最终效果:

   Asp.Net MVC2 控件开发实例(3)

 

 

 

 

 

 

 

 

 

 

说明:轮播的CSS参考了网上一篇文章,具体链接忘记了,其余为原创。

    书归正传。这个控件有几个功能点,1是无刷新上传和修改,这里使用了一个上传插件,详见:

ajaxupload。官方有使用说明,这里我就不讨论了;2是新增修改和删除图标的定位问题,CSS设置定位和层叠即可,也不细说了;3是点击小图显示大图的问题,这里面还有缩略图问题;4是控件单独刷新。以下将依次说明。

    首先构建基本的HTML和CSS:

Asp.Net MVC2 控件开发实例(3) HTML+CSS
< div  class ="banner_f" >
    
< div  class ="banner" >
        
< div  class ="banner_bg" >
        
</ div >
        
<!-- 标题 -->
        
< div  class ="banner_info" >
    
</ div >
        
<!-- 标题背景 -->
        
< div  class ="banner_list" >
        
</ div >

        
< div  class ="div_imgHD" >
        
</ div >
    
</ div >
    
< ul  class ="banner_ul" >
        
</ ul >
</ div >
<% = Html.Hidden( " ZPDTID " , Model.ZPDTID  as   string ) %>
<% = Html.Hidden( " PhotoYWdtid " , Model.PhotoYWdtid  as   string ) %>
<% = Html.Hidden( " HD_Width " , Model.HD_Width  as   string ) %>
<% = Html.Hidden( " HD_Height " , Model.HD_Height  as   string ) %>
< style  type ="text/css" >
    .banner_f
    
{
        height
:  140px ;
        width
:  91px ;
        position
:  relative ;  
        border
:  1px solid #666 ;
    
}
    .banner
    
{
        position
:  relative ;
        width
:  90px ;
        height
:  120px ;
        border
:  1px solid #666 ;
        overflow
:  hidden ;
    
}
    .banner_list img
    
{
        border
:  0px ;
        height
:  120px ;
        width
:  90px ;
    
}
    .banner_list
    
{
        float
:  left ;
    
}
    .div_imgHD
    
{
        display
: none ;
    
}
    .banner_bg
    
{
        position
:  absolute ;
        bottom
:  0 ;
        background-color
:  #ffffff ;
        height
:  20px ;
        filter
:  Alpha(Opacity=30) ;
        opacity
:  0.3 ;
        z-index
:  1000 ;
        cursor
:  pointer ;
        width
:  90px ;
    
}
    .banner_info
    
{
        position
:  absolute ;
        bottom
:  0 ;
        left
:  15px ;
        height
:  15px ;
        color
:  #fff ;
        z-index
:  1001 ;
        cursor
:  pointer ;
        left
: 30% ;
    
}
    .banner_text
    
{
        position
:  absolute ;
        width
:  90px ;
        z-index
:  1002 ;
        right
:  3px ;
        bottom
:  3px ;
    
}
    .banner_ul
    
{
        position
:  absolute ;
        list-style-type
:  none ;
        filter
:  Alpha(Opacity=80) ;
        opacity
:  0.8 ;
        border
:  1px solid #fff ;
        z-index
:  1002 ;
        margin
:  0 ;
        padding
:  0 ;
        bottom
:  0 ;
        right
:  5px ;
        height
:  17px ;
    
}
    .banner_ul li
    
{
        padding
:   0px 4px ;
        float
:  left ;
        display
:  block ;
        color
:  #FFF ;
        border
:  #e5eaff 1px solid ;
        background-color
:  #6f4f67 ;
        cursor
:  pointer ;
        width
:  3px ;
    
}
    .banner_list a
    
{
        position
:  absolute ;
    
}

</style> 

 简单说明一下:banner_f是整个控件的外层div,高度为图片高度120+导航高度20=140,宽度为图片宽度90+border1=91,相对定位;banner为图片div;banner_list为图片div;div_imgHD为显示大图的div(初始为隐藏);banner_ul为导航。

使用的时候这样即可:

$('#tdPhoto').load('/FM/Modify/BannerPhoto', { YWDTID: dtid, timeStamp: time,width:'450',height:'600' }, function () {
         fillRYPhoto($('#ZPDTID').val() == null ? '' : $('#ZPDTID').val(), false, 0);

     }); 其中tdPhoto是需要填充此图片控件的控件ID,'/FM/Modify/BannerPhoto'为请求的action(此action作用为返回此图片控件的PartialViewResult),YWDTID是这些图片的数据源ID,timeStamp为时间戳以避免缓存问题,width为显示大图时的外围层宽度,height为大图外围层高度(或者说是想显示大图的最大宽度和高度以便自适应尺寸来保证图片不变形),回调方法fillRYPhoto填充图片。

    首先是action,作用就是绑定一些页面数据并返回PartialViewResult:

Asp.Net MVC2 控件开发实例(3) View Code
[HttpPost()]
        
public  PartialViewResult BannerPhoto( string  YWDTID,  string  timeStamp, string  width, string  height)
        {
            
string  ZPDTIDList  =   string .Empty;
            DataTable zpDt 
=  GetZpDt(YWDTID,  out  ZPDTIDList);
            dynamic m 
=   new  System.Dynamic.ExpandoObject();
            m.ZPDTID 
=  ZPDTIDList;
            m.PhotoYWdtid 
=  YWDTID;
            m.HD_Width 
=  width;
            m.HD_Height 
=  height;
            
return  PartialView( " ~/Views/Shared/BannerPhoto.ascx " , m);}

然后是回调方法 fillRYPhoto,由于初始的html里面只包含了外层控件,所以这里面做的事情比较多,包括所有内层控件的回填:

 

< script type = " text/javascript " >
    
// #region fillRYPhoto
     function  fillRYPhoto(IDList, hidButton, index) {
        
if  (index  ==  null  ||  index  ==  ' undefined ' ) {
            index 
=  0 ;
        }
        $.unblockUI;
        
var  list  =  IDList.toString().split( ' , ' );
        $(
' .banner_ul ' ).eq(index).empty();
        $(
' .banner_list ' ).eq(index).empty();
        
for  ( var  i  =  0 ; i  <  list.length; i ++ ) {
            $(
' .banner_ul ' ).eq(index).append( " <li> "  +  (i  +  1 ).toString()  +  " </li> " );
            $(
' .banner_list ' ).eq(index).append( " <a href='javascript:///'><img title='点击放大' id=' " +  list[i]  +  " ' onclick=\"showHDimg(this.id, " + index + " );\" src=\"/FM/Modify/GetRyPhotoByID?ZPDTID=' "  +  list[i]  +  " '&timestamp= "  +  new  Date()  +  " \"  /></a> " );
        }
        
if  ($( ' .banner_ul ' ).eq(index).children( ' li ' ).length  <  2 ) {
            $(
' .banner_ul ' ).eq(index).remove();
            $(
' .banner_f ' ).eq(index).css( ' height ' ' 120px ' );
        }
        
else  {
            $(
' .banner_ul ' ).eq(index).children( ' li ' ).show();
        }
        bindZPClick(hidButton,index);
    }
    
// #endregion


    
// #region showHDimg:显示大图
     function  showHDimg(imgID,index) {
        
var  selector  =  ' .banner_list:eq( '  +  index  +  ' ) '  +  '  img ' ;
        
if  ($(selector).attr( ' id ' ).length  ==  0 ) {  return  };
        
var  hd_width  =  $( ' #HD_Width ' ).val();
        
var  hd_height  =  $( ' #HD_Height ' ).val();
        $(
' .div_imgHD ' ).eq(index).empty().append( " <img id=' "  +  imgID  +  " _HD' "  +  "  src=\"/FM/Modify/GetRyPhotoHDByID?ZPDTID=' "  +  imgID  +  " '&hd_width= "  +  hd_width  +  " &hd_height= "  +  hd_height  +  " &timestamp= "  +  new  Date()  +  " \"> " );
        $.blockUI({
            message: $(
' # '  +  imgID  +  ' _HD ' ).click($.unblockUI),
            css: {
                centerY: 
true ,
                top: ($(window).height() 
-  hd_height)  /  2  +  ' px ' ,
                left: ($(window).width() 
-  hd_width)  /  2  +  ' px ' ,
                width: hd_width 
+  ' px ' ,
                height: hd_height 
+  ' px '
            },
            fadeIn: 
700 ,
            fadeOut: 
700
        });
        $(
' .blockOverlay ' ).attr( ' title ' ' 点击收起 ' ).click($.unblockUI);
        
var  i  =  setInterval( function  () {
            
var  h  =  $( ' # '  +  imgID  +  ' _HD ' ).height();
            $(
' # '  +  imgID  +  ' _HD ' ).css( ' margin-top ' , (hd_height  -  h)  /  2  +  ' px ' );
            
if  (h  >  0 ) {
                clearInterval(i);
            }
        }, 
1000 );
    }
    
// #endregion


    
// #region 绑定事件
     function  bindZPClick(hidButton,index) {
        
var  count  =  $( " .banner_list " ).eq(index).children( ' a ' ).length;
        $(
" .banner_list " ).eq(index).children( ' a:not(:first-child) ' ).hide();
        editBannerinfo(hidButton,index);
        $(
" .banner_ul " ).eq(index).children( ' li ' ).click( function  () {
            
var  i  =  $( this ).text()  -  1 // 获取Li元素内的值,即1,2,3,4
             if  (i  >=  count)  return ;
            $(
" .banner_list " ).eq(index).children( ' a ' ).filter( " :visible " ).fadeOut( 500 ).parent().children().eq(i).fadeIn( 1000 );
            $(
this ).css({  " background " " #be2424 " ' color ' ' #000 '  }).siblings().css({  " background " " #6f4f67 " ' color ' ' #fff '  });
        });
    }
    
function  editBannerinfo(hidButton, index) {
        
if  (hidButton  ==  ' undefined '  ||  hidButton) {
            hidButton 
=  false ;
            $(
' .banner_bg ' ).eq(index).remove();
        }
        
else  {
            $(
" .banner_info " ).eq(index).empty();
            
if  ($( ' .banner_ul ' ).eq(index).children( ' li ' ).length  >  4 ) {
                $(
" .banner_info " ).eq(index).append( " <image alt='新增' id=' "  +  index  +  " _imgRyAdd' src='/FM/Content/Images/plus.jpg' onclick='$.growlUI(\"最多只能上传5张照片\",null,1000);$(\"div.growlUI\").attr(\"class\",\"growlUI_Error\");' /> " );
            }
            
else  {
                $(
" .banner_info " ).eq(index).append( " <image alt='新增' id=' "  +  index  +  " _imgRyAdd' src='/FM/Content/Images/plus.jpg' /> " );
            }
            $(
" .banner_info " ).eq(index).append( " <image alt='删除' id=' "  +  index  +  " _imgRyDel' src='/FM/Content/Images/minus.jpg' onclick='delZP( "  +  index  +  " );' /> " )
            .append(
" <image alt='修改' id=' "  +  index  +  " _imgRyModify' src='/FM/Content/Images/edit2.png'  /> " );
            setTimeout(
function  () {
                setRyUpload(
' add ' , index);
                setRyUpload(
' modify ' , index);
            }, 
3000 );
        }
    }
    
// #endregion


    
// #region 初始化人员上传控件
     function  setRyUpload(operation, index) {
        
var  url;
        
var  mess;
        
var  selector;
        
var  setdata;
        
var  zpid  =  $( " .banner_list " ).eq(index).children( ' a ' ).filter( " :visible " ).children().attr( " id " );
        
var  content  =  '' ;
        
if  (operation  ===  ' add ' ) {
            url 
=  ' /FM/Modify/AddRyImg ' ;
            mess 
=  ' 新增图片成功! ' ;
            content 
=  ' 相片ID: ' ;
            selector 
=  ' # ' + index + ' _imgRyAdd ' ;
            setdata 
=  {  ' YWDTID ' : $( ' #PhotoYWdtid ' ).val() };
        }
        
else  {
            url 
=  ' /FM/Modify/ModifyRyImg ' ;
            mess 
=  ' 修改图片成功! ' ;
            content 
=  ' 相片ID: '  +  zpid;
            selector 
=  ' # '  +  index  +  ' _imgRyModify ' ;
            setdata 
=  {  ' photoID ' : zpid };
        }

        
var  upload  =  new  AjaxUpload(
            $(selector),
            {
                action: url,
                onSubmit: 
function  () {  this .disable(); },
                responseType: 
" json " ,
                onComplete: 
function  (file, response) {
                    refreshTB(index);
                    
if  (response  ==  ' 1 ' ) {
                        $.growlUI(mess, 
null 2000 );
                    }
                    
else  {
                        $.growlUI(
' 上传失败 ' null 2000 );
                    }
                }
            });
        upload.setData(setdata);
    }
    
// #endregion


    
// #region 删除照片
     function  delZP(index) {
        
if  (window.confirm( " 确认删除当前照片吗? " )) {
            
var  zpid  =  $( " .banner_list " ).eq(index).children( ' a ' ).filter( " :visible " ).children().attr( " id " );
            
var  mess;
            $.post(
            
' /FM/Modify/DltRyImg ' , { photoID: zpid },
            
function  (result) {
                mess 
=  result  ==  1  ?  ' 删除成功 '  :  ' 删除失败 ' ;
                $.growlUI(mess, 
' 相片ID: '  +  zpid,  2000 );
                refreshTB(index);
            }
            );
        }
    }
    
// #endregion


    
// #region 刷新照片
     function  refreshTB(index) {
        
var  ywdtid  =  $( ' #PhotoYWdtid ' ).val();
        
var  time  =  ( new  Date()).toString();
        
var  hd_width  =  $( ' #HD_Width ' ).val();
        
var  hd_height  =  $( ' #HD_Height ' ).val();
        $(
' .banner_f ' ).eq(index).parent().empty().load( ' /FM/Modify/BannerPhoto ' ,
        { YWDTID: ywdtid, timeStamp: time, width: hd_width, height: hd_height },
        
function  () {
            fillRYPhoto($(
' #ZPDTID ' ).val(),  false , index);
        });
    }
    
// #endregion

< / script>

    这里详细说一下显示大图的问题,由于图片在数据库里是以blob的形式存储,又担心图片的文件存储问题,所以自始自终图片都不以文件的形式存储,而用户又要求显示大图的时候要自适应宽度和高度,也就是不能变形又不能溢出自定义的外框,这样就要进行图片处理。下面是byte[]和 Image互转的两个方法:

 Asp.Net MVC2 控件开发实例(3)View Code

public  static  Image ConvertToImg(Byte[] byte_img)
        {
            
using  (MemoryStream stream  =  new  MemoryStream(byte_img))
            {
                Image img 
=  Image.FromStream(stream);
                
return  img;
            }
        }

        
public  static  Byte[] ConvertToByte(Image img)
        {
            
using  (MemoryStream stream = new  MemoryStream())
            {
                img.Save(stream, ImageFormat.Jpeg);
                
return  stream.ToArray();
            }
        }

 显示大图时我用了blockUI,用法见blockUI。小图点击时直接请求数据库原图并将需显示大小尺寸做入参在后台计算并处理生成缩略图(这里的缩略图生成比较简单,没有做插值算法处理,有兴趣可以自行生成高质量缩略图):

Asp.Net MVC2 控件开发实例(3)View Code
public  FileResult GetRyPhotoHDByID( string  ZPDTID,  int  hd_width,  int  hd_height,  string  timestamp)
        {
            DataTable dt 
=  Session[ " zp " as  DataTable;
            
if  (dt  ==  null )
            {
                
return  File(Server.MapPath( " ~/Content/Images/nophoto.jpg " ),  " application/octet-stream " );
            }

            DataRow[] dr 
=  dt.Select( " DTID= "  +  ZPDTID);
            
if  (dr.Count()  <  1 )
            {
                
return  File(Server.MapPath( " ~/Content/Images/nophoto.jpg " ),  " application/octet-stream " );
            }
            Byte[] zpnr 
=  (Byte[])dr[ 0 ][ " ZPNR " ];
            Image img 
=  ImageCommon.ConvertToImg(zpnr);
            
double  a  =  Convert.ToDouble(img.Width)  /  Convert.ToDouble(img.Height); // 原图宽高比
             double  b  =  Convert.ToDouble(hd_width)  /  Convert.ToDouble(hd_height); // 浮动层宽高比
             double  w  =  img.Width; // 显示的大图的宽度
             double  h  =  img.Height; // 显示的大图的高度
             if  (img.Width  >  hd_width  ||  img.Height  >  hd_height) //原图的宽度或高度大于外层宽高则做缩略图,否则显示原图
            {
                
if  (a  >  b)
                {
                    w 
=  hd_width;
                    h 
=  Convert.ToDouble(w  *  img.Height)  /  Convert.ToDouble(img.Width);
                }
                
else
                {
                    h 
=  hd_height;
                    w 
=  Convert.ToDouble(h  *  img.Width)  /  Convert.ToDouble(img.Height);
                }
                Image.GetThumbnailImageAbort myCallback 
=  new  Image.GetThumbnailImageAbort(CallBack);
                Image i 
=  img.GetThumbnailImage(Convert.ToInt32(w), Convert.ToInt32(h), myCallback, IntPtr.Zero);

                Byte[] byte_img 
=  ImageCommon.ConvertToByte(i);
                
return  File(byte_img,  " application/octet-stream " );
            }
            
else
            {
                
return  File((Byte[])dr[ 0 ][ " ZPNR " ],  " application/octet-stream " );
            }
        }

        
private  static  bool  CallBack()   // 委托方法
        {
            
return  false ;

        } 

    生成之后有一个定位问题,因为返回之后要做居中处理(大图要显示在自定义的层中央,这个自定义层的大小是根据业务自定义的,主要是显示大图的时候用户可能还想看前面的信息),但是图片此时虽然已经生成,但是前台缺未必可以获取到尺寸,这里用了一个小技巧,用一个计时器反复检查图片尺寸直到尺寸大于0时清除计时器:

 

Asp.Net MVC2 控件开发实例(3)View Code
  var  i  =  setInterval( function  () {
            
var  h  =  $( ' # '  +  imgID  +  ' _HD ' ).height();
            $(
' # '  +  imgID  +  ' _HD ' ).css( ' margin-top ' , (hd_height  -  h)  /  2  +  ' px ' );
            
if  (h  >  0 ) {
                clearInterval(i);
            }
        }, 
1000 );
 

 

 其余的新增,删除修改图片的后台方法比较简单我就不贴了。各位看官有何意见,尽管拍砖~

 

你可能感兴趣的:(asp.net)