使用JQuery插件Jcrop进行图片截取

Jcrop插件本身并不含有图片截取功能,它仅仅是在前端层面构建一套截取动画效果并产生4个坐标点,插件使用者将这4个坐标点传回至服务器接口上进行截取操作。其优点是具有较高的通用性、浏览器兼容性(IE6+)及稳定性高,缺点是无法适用于手机H5开发(无图片缩放、拖拽效果)。

最新版的Jcrop已更新到v3.0+了,本文基于 v0.9.12,由于这版本之间API及使用方式差异非常大,故本文不具备 Jcrop v3.0+ 的使用参考价值,请读者悉知。

Jcrop V0.9+ 下载地址:http://deepliquid.com/content/Jcrop.html

Jcrop V0.9+ API中文说明:https://blog.csdn.net/xht555/article/details/43407141?utm_source=blogxgwz6

Jcrop V3.0+ 下载地址: https://github.com/tapmodo/Jcrop

html代码,这里没放出Jcrop.js、jcrop.css的引用,请读者不要漏了这关键的两步。

    <div class="item">
        <h3>
            5、上传头像实例(预览\截取)
        </h3>
        <!--图片上传表单,读者也可以选择其他的上传方式-->
        <form id="form_upload" enctype="multipart/form-data" action="./UploadPhoto" method="post">
            <input id="File5" name="UserPhoto" type="file" value="" />
            <input id="btnUpload5" type="submit" value="提交上传"  />
        </form>

        <!--截取主要内容区-->
        <div id="photoWrap">

            <!--截取区-->
            <div id="crop_area">
                <img id="crop_img" alt="头像" style="display: none"/>
            </div>

            <!--预览区,我这里做了两个规格的预览 48*48 180*180 -->
            <div id="preview_area">
                <div id="preview_title">当前头像</div>
                <div id="preview_small_txt">48px × 48px</div>
                <div id="preview_small_wrap">
                    <img id="preview_small_img" alt="小预览图" src="~/Content/default_48.png"/>
                </div>
                <div id="preview_large_txt">180px × 180px</div>
                <div id="preview_large_wrap">
                    <img id="preview_large_img" alt="大预览图" src="~/Content/default_180.png"/>
                </div>
            </div>
        </div>

        <!--截取框坐标点数据保存区,同时也是请求后台截取接口的表单-->
        <div id="crop_operation">
            <form id="form_crop" action="./CropPhoto" method="post">
                <input id="url" type="hidden" name="url" />
                <input id="x" type="hidden" name="x" />
                <input id="y" type="hidden" name="y" />
                <input id="w" type="hidden" name="w" />
                <input id="h" type="hidden" name="h" />
                <input id="btn_crop" type="submit" value="裁剪并保存" />
            </form>
        </div>
    </div>

JS代码,所需参数

//jcrop 所需参数
var jcrop_api;
var boundx;
var boundy;

//上方是必选参数
//下方是用于截取预览图的参数,可选的
//我这里设置了48*48 180*180 两种规格的预览效果
var $pimg_small;
var $pimg_large; 

var xsize_small = 48;
var ysize_small = 48;
var xsize_large = 180;
var ysize_large = 180;

$(function() {
    $pimg_small = $(‘#preview_small_img‘);
    $pimg_large = $(‘#preview_large_img‘);
});

JS代码,主体逻辑

    //上传图片
    $(‘#form_upload‘).ajaxForm({
        dataType: "json",
        data:$(‘#form_upload‘).serialize(),
        success: function (data, textStatus, jqXHR) {
            if (data.Status == ‘success‘) {
                //上传成功后,为主截取区、截取预览区的img赋值
                $("#crop_img,#preview_small_img,#preview_large_img").attr(‘src‘, data.ImgUrl);
                //用input hidden保存返回值,以便截取时使用
                $("#url").val(data.ImgUrl);

                //if (jcrop_api != null) {
                //    jcrop_api.setImage(data.ImgUrl, function () {
                //        var bounds = jcrop_api.getBounds();
                //        boundx = bounds[0];
                //        boundy = bounds[1];
                //        var size = Math.min(boundx, boundy);
                //        jcrop_api.setSelect([0,0,size,size]);
                //    });
                //}
                return;
            }
            if (data.Status == ‘error‘) {
                showMessage(data.Msg);
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            showMessage(‘上传失败‘);
            console.error(textStatus);
        }
    });

    //当图片加载完毕时,调用Jcrop初始化函数
    //因为存在多次上传图片的情况,所以此处用<img/>标签的load事件,每加载完毕一次就初始化一次
    $("#crop_img").load(function () {
        $("#crop_img").Jcrop({
            onChange: updatePreview,//截取框变化事件,主要用于实时更新预览图
            onSelect: updateCropData,//截取框选定事件,主要用于获得截取框的4个坐标点
            aspectRatio: 1 //截取框的比例,1则是正方形
        }, function () {
            //$().Jcrop()初始化后的回调函数;
            //这里为提高用户体验而设置了一个可选范围内最大的截取框,以告诉用户“你可以进行截取了”。
            jcrop_api = this;
            var bounds = this.getBounds();//获取图片实际尺寸,格式为:[w,h]
            boundx = bounds[0];
            boundy = bounds[1];

            var size = Math.min(boundx, boundy);
            jcrop_api.setSelect([0, 0, size, size]);//4个坐标点设定一个截取框
        });
    });

//更新预览图,这函数是官方demo给出的代码,各位可以直接copy不必深究
function updatePreview(c) {
    if (parseInt(c.w) > 0) {
        var rx_large = xsize_large / c.w;
        var ry_large = ysize_large / c.h;

        $pimg_large.css({
            width: Math.round(rx_large * boundx) + ‘px‘,
            height: Math.round(ry_large * boundy) + ‘px‘,
            marginLeft: ‘-‘ + Math.round(rx_large * c.x) + ‘px‘,
            marginTop: ‘-‘ + Math.round(ry_large * c.y) + ‘px‘
        });

        var rx_small = xsize_small / c.w;
        var ry_small = ysize_small / c.h;

        $pimg_small.css({
            width: Math.round(rx_small * boundx) + ‘px‘,
            height: Math.round(ry_small * boundy) + ‘px‘,
            marginLeft: ‘-‘ + Math.round(rx_small * c.x) + ‘px‘,
            marginTop: ‘-‘ + Math.round(ry_small * c.y) + ‘px‘
        });
    }
};

//截取框选定事件的处理函数,用于实时更新4个坐标点
function updateCropData(c) {
    jQuery("#x").val(c.x);
    jQuery("#y").val(c.y);
    jQuery("#w").val(c.w);
    jQuery("#h").val(c.h)

    console.group(‘updateCropData‘);
    console.info(c.x)
    console.info(c.y)
    console.info(c.w)
    console.info(c.h)
    console.groupEnd(‘updateCropData‘);
}

    //请求后台接口,进行真正的图片截取
    //因为4个坐标点是由updateCropData()函数实时更新至<form id="form_crop"/>的隐藏域里的,
    //所以这里只要提交表单即可,这里是使用了jquery.form.js插件,我上一篇文章中有提到jquery.form.js的使用
    $(‘#form_crop‘).ajaxForm({
        dataType: "json",
        success: function (data, textStatus, jqXHR) {
            if (data.Status == ‘success‘) {
                showMessage(‘保存成功‘);
                jcrop_api.destroy();//上传成功后释放jcrop
                return;
            }
            if (data.Status == ‘error‘) {
                showMessage(data.Msg);
            }
        },
        error: function (jqXHR, textStatus, errorThrown) {
            showMessage(‘请求错误‘);
            console.error(textStatus);
        }
    });

后台代码。在这里代码较长可能会造成阅读效果不佳,不过在文章末有源码下载可供阅读。

        [HttpPost]
        public ActionResult UploadPhoto()
        {
            HttpPostedFileBase file = Request.Files["UserPhoto"];
            string contentType = file.ContentType;
            string extension = Path.GetExtension(file.FileName);

            //检查图片格式
            if (!IsAllowImg(contentType, extension))
            {
                return Json(new { Status = "error", Msg = "上传文件格式不符合要求。" });
            }

            //保存形成保存路径
            TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0);
            string newFileName = Convert.ToInt64(ts.TotalMilliseconds).ToString(CultureInfo.InvariantCulture) + new Random().Next(100, 999);
            string path = Server.MapPath("~/Upload/") + newFileName + ".jpeg";

            //压缩图片、转换格式(jpeg)
            Image ResourceImage = Image.FromStream(file.InputStream);
            if(ResourceImage.Width>300)
            {
                int dWidth = 300;
                int dHeight = 300 * ResourceImage.Height / ResourceImage.Width;
                CompressPicture(file.InputStream, path, dWidth, dHeight,100);
            }
            else
            {
                CompressPicture(file.InputStream, path, ResourceImage.Width, ResourceImage.Height, 100);
            }
            file.InputStream.Close();

            string url = Request.ApplicationPath + "Upload/" + newFileName + ".jpeg";
            return Json(new { Status = "success", Msg = "上传成功",ImgUrl= url });
        }

        #region 压缩图像
        /// <summary>
        /// 无损压缩图片
        /// </summary>
        /// <param name="inputStream">原图片</param>
        /// <param name="dFile">压缩后保存位置</param>
        /// <param name="dWidth">宽度</param>
        /// <param name="dHeight">高度</param>
        /// <param name="flag">压缩质量 1-100</param>
        /// <returns></returns>
        public bool CompressPicture(Stream inputStream, string dFile,  int dWidth, int dHeight, int flag)
        {
            System.Drawing.Image iSource = System.Drawing.Image.FromStream(inputStream);
            ImageFormat tFormat = iSource.RawFormat;
            int sW = 0, sH = 0;
            //按比例缩放
            Size tem_size = new Size(iSource.Width, iSource.Height);
            if (tem_size.Width > dWidth || tem_size.Height > dHeight)
            {
                if ((tem_size.Width * dHeight) > (tem_size.Height * dWidth))
                {
                    sW = dWidth;
                    sH = (dWidth * tem_size.Height) / tem_size.Width;
                }
                else
                {
                    sH = dHeight;
                    sW = (tem_size.Width * dHeight) / tem_size.Height;
                }
            }
            else
            {
                sW = tem_size.Width;
                sH = tem_size.Height;
            }

            Bitmap ob = new Bitmap(dWidth, dHeight);
            Graphics g = Graphics.FromImage(ob);
            g.Clear(Color.WhiteSmoke);
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);
            g.Dispose();
            //以下代码为保存图片时,设置压缩质量
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;
            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();

                ImageCodecInfo jpegICIinfo = null;

                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                if (jpegICIinfo != null)
                {
                    ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径
                }
                else
                {
                    ob.Save(dFile, tFormat);
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                iSource.Dispose();
                ob.Dispose();
            }
        }

        /// <summary>
        /// 无损压缩图片
        /// </summary>
        /// <param name="sFile">原图片</param>
        /// <param name="dFile">压缩后保存位置</param>
        /// <param name="dWidth">宽度</param>
        /// <param name="dHeight">高度</param>
        /// <param name="flag">压缩质量 1-100</param>
        /// <returns></returns>
        public bool CompressPicture(string sFile, string dFile, int dWidth, int dHeight, int flag)
        {
            System.Drawing.Image iSource = System.Drawing.Image.FromFile(sFile);
            ImageFormat tFormat = iSource.RawFormat;
            int sW = 0, sH = 0;
            //按比例缩放
            Size tem_size = new Size(iSource.Width, iSource.Height);
            if (tem_size.Width > dWidth || tem_size.Height > dHeight)
            {
                if ((tem_size.Width * dHeight) > (tem_size.Height * dWidth))
                {
                    sW = dWidth;
                    sH = (dWidth * tem_size.Height) / tem_size.Width;
                }
                else
                {
                    sH = dHeight;
                    sW = (tem_size.Width * dHeight) / tem_size.Height;
                }
            }
            else
            {
                sW = tem_size.Width;
                sH = tem_size.Height;
            }

            Bitmap ob = new Bitmap(dWidth, dHeight);
            Graphics g = Graphics.FromImage(ob);
            g.Clear(Color.WhiteSmoke);
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(iSource, new Rectangle((dWidth - sW) / 2, (dHeight - sH) / 2, sW, sH), 0, 0, iSource.Width, iSource.Height, GraphicsUnit.Pixel);
            g.Dispose();
            //以下代码为保存图片时,设置压缩质量
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;
            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();

                ImageCodecInfo jpegICIinfo = null;

                for (int x = 0; x < arrayICI.Length; x++)
                {
                    if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[x];
                        break;
                    }
                }
                if (jpegICIinfo != null)
                {
                    ob.Save(dFile, jpegICIinfo, ep);//dFile是压缩后的新路径
                }
                else
                {
                    ob.Save(dFile, tFormat);
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                iSource.Dispose();
                ob.Dispose();
            }
        }

        /// <summary>
        /// 按指定规格裁剪图片
        /// </summary>
        /// <param name="sFile">源文件路径</param>
        /// <param name="dFile">输出文件路径</param>
        /// <param name="originPoint">裁剪区域的起点</param>
        /// <param name="sSize">裁剪区域的大小</param>
        /// <param name="dSize">生成的规格</param>
        /// <param name="flag">压缩质量 1-100</param>
        /// <returns></returns>
        public bool CropPicture(string sFile, string dFile, Point originPoint , Size sSize, Size dSize, int flag)
        {
            System.Drawing.Image iSource = System.Drawing.Image.FromFile(sFile);
            ImageFormat tFormat = iSource.RawFormat;
            Bitmap ob = new Bitmap(dSize.Width, dSize.Height);
            Graphics g = Graphics.FromImage(ob);
            g.Clear(Color.WhiteSmoke);
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.DrawImage(iSource, new Rectangle(0, 0, dSize.Width, dSize.Height), originPoint.X, originPoint.Y, sSize.Width, sSize.Height, GraphicsUnit.Pixel);
            g.Dispose();
            //以下代码为保存图片时,设置压缩质量
            EncoderParameters ep = new EncoderParameters();
            long[] qy = new long[1];
            qy[0] = flag;//设置压缩的比例1-100
            EncoderParameter eParam = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, qy);
            ep.Param[0] = eParam;
            try
            {
                ImageCodecInfo[] arrayICI = ImageCodecInfo.GetImageEncoders();

                ImageCodecInfo jpegICIinfo = null;

                for (int i = 0; i < arrayICI.Length; i++)
                {
                    if (arrayICI[i].FormatDescription.Equals("JPEG"))
                    {
                        jpegICIinfo = arrayICI[i];
                        break;
                    }
                }
                if(string.IsNullOrEmpty(dFile))
                {
                    string[] temp = sFile.Split(new char[] { ‘\\‘ }, StringSplitOptions.RemoveEmptyEntries);
                    string fileName = temp[temp.Length - 1];
                    fileName = fileName.Insert(fileName.IndexOf(‘.‘), ‘_‘+ dSize.Width.ToString() + ‘_‘ + dSize.Height.ToString());
                    temp[temp.Length - 1] = fileName;
                    dFile = string.Empty;
                    foreach(string item in temp)
                    {
                        dFile += item + "\\";
                    }
                    dFile=dFile.TrimEnd(‘\\‘);
                }
                if (jpegICIinfo != null)
                {
                    ob.Save(dFile, jpegICIinfo, ep);
                }
                else
                {
                    ob.Save(dFile, tFormat);
                }
                return true;
            }
            catch
            {
                return false;
            }
            finally
            {
                iSource.Dispose();
                ob.Dispose();
            }

        }
        #endregion

        #region 判断图片格式
        public bool IsAllowImg(string contentType, string fileExtension)
        {
            contentType = contentType.ToLower();
            if(!contentType.Contains("image"))
            {
                return false;
            }

            fileExtension = fileExtension.ToLower();
            string[] allowExtension = { ".bmp", ".gif", ".jpeg", ".jpg", ".png" };
            foreach (string item in allowExtension)
            {
                if (fileExtension == item)
                {
                    return true;
                }
            }
            return false;
        }

        public static bool IsAllowedExtension(HttpPostedFileBase file)
        {
            System.IO.Stream stream = file.InputStream;
            System.IO.BinaryReader reader = new System.IO.BinaryReader(stream);
            string fileclass = "";
            //这里的位长要具体判断.
            byte buffer;
            try
            {
                //buffer = r.ReadByte();
                //fileclass = buffer.ToString();
                //buffer = r.ReadByte();
                //fileclass += buffer.ToString();

                for (int i = 0; i < 2; i++)
                {
                    fileclass += reader.ReadByte().ToString();
                }

            }
            catch
            {

            }
            reader.Close();
            stream.Close();
            if (fileclass == "255216" || fileclass == "7173")//说明255216是jpg;7173是gif;6677是BMP,13780是PNG;7790是exe,8297是rar
            {
                return true;
            }
            else
            {
                return false;
            }

        }
        #endregion

        [HttpPost]
        public JsonResult CropPhoto(string url,int x,int y,int w,int h)
        {
            if (string.IsNullOrEmpty(url) || w == 0 || h == 0)
            {
                return Json(new { Status = "error", Msg = "参数错误" });
            }

            Point origin = new Point(x, y);
            Size source = new Size(w, h);
            Size destSmall = new Size(48, 48);
            Size destLarge = new Size(180, 180);

            bool result1 =CropPicture(Server.MapPath(url), null, origin, source, destSmall, 100);
            bool result2 =CropPicture(Server.MapPath(url), null, origin, source, destLarge, 100);

            var jsonResult = result1 && result2
                ? new { Status = "success", Msg = "操作成功" }
                : new { Status = "error", Msg = "裁剪图片出现错误" };

            return Json(jsonResult);
        }
    }

在上传图片时,我对宽度大于300px的图片进行了等比压缩,目的是控制图片在浏览器截取区内显示的比较友好。

其实这里也可以直接返回源图,在 <img/> 标签内使用 width属性控制图片宽度,再计算出缩放比例并将此数值存储于 <form id="form_crop" />表单内,待请求截取图片接口时将此缩放比例一并发送至后台,此时再按照缩放比例对4个坐标点做偏移计算即可截取出正确的图片。这里就提供思路,源码里我就不做这块了。

源码下载:https://pan.baidu.com/s/1eWiOzvio9EVW2WlYeaKUGA

代码是用VS2015 ASP.NET MVC5写的,我把bin目录内的dll都删了,通过还原 nuget 程序包应该就能运行了。

原文地址:https://www.cnblogs.com/xurongjian/p/9867721.html

时间: 2024-10-04 06:38:17

使用JQuery插件Jcrop进行图片截取的相关文章

jQuery插件之文章图片弹出放大效果

首先先搭写一个基本的格式: $.fn.popImg = function() { //your code goes here } 然后用自调用匿名函数包裹你的代码,将系统变量以变量形式传递到插件内部,如下: ;(function($,window,document,undefined){ $.fn.popImg = function() { //your code goes here } })(jQuery,window,document); 那么接下来我们就在里面实现点击文章图片弹出该图片并放

jquery插件之lazyload图片延时加载功能

公司投票程序,页面图片较多,导致页面显示很慢,做的图片延时加载: 代码: <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta charset="utf-8"> <title>demo</title> </

对jquery插件Jcrop开发一个裁剪组件

Jcrop是一款优秀的裁剪工具,它不仅可以裁剪图像,还可以裁剪canvas及任何的div元素,具体可参考: http://code.ciaoca.com/jquery/jcrop/ 基于Jcrop,开发一个js组件(Cut.js),使之可进行复用: (function(jQuery,window,undefined){    window.Cut = window.Cut || {};    var _default={        boxWidth:0,        boxHeight:0

插件介绍 :cropper是一款使用简单且功能强大的图片剪裁jQuery插件。

简要教程 cropper是一款使用简单且功能强大的图片剪裁jQuery插件.该图片剪裁插件支持图片放大缩小,支持鼠标滚轮操作,支持图片旋转,支持触摸屏设备,支持canvas,并且支持跨浏览器使用. cropper提供了大量的参数.方法和事件供图片的剪裁操作. 安装 可以通过Bower或NPM来安装该插件. 1 2 bower install cropper npm install cropper                使用方法 使用该图片剪裁插件首先要引入必要的js和css文件. 1 2

图片延迟加载jquery插件imgLazyLoad(三)

此Jquery插件是在图片加载前显示一个加载图片,当图片下载完毕后显示图片出来,可对图片进行是否自动缩放功能,此Jquery插件使用时可让页面先加载,而图片后加载的方式,解决了平时使用时要在图片显示出来后才能进行缩放时撑大布局的问题 ///参数设置:scaling     是否等比例自动缩放width       图片最大高height      图片最大宽loadpic     加载中的图片路径 js插件代码: /* **************图片预加载插件*****************

图片和DOM元素网格布局jQuery插件

jMosaic是一款可以将图片或HTML元素均匀分布排列为网格布局的jQuery插件.可以使用的HTML元素有:img.div.li等.该jQuery插件可以将图片等元素整齐排列,元素的宽高比例不会发生变化. 效果演示:http://www.htmleaf.com/Demo/201503291594.html 下载地址:http://www.htmleaf.com/jQuery/Layout-Interface/201503291593.html

jQuery之Jcrop

头像裁剪是一个经常用到的功能,实现原理也较为简单,就是在本地选择好所需裁剪图片的坐标,将坐标发送到服务器,由服务器执行图片裁剪操作. jQuery插件Jcrop提供了强大的图片裁剪坐标选择插件.一下来介绍它的用法.本处采用了AJAX本地上传一张图片的方法让用户裁剪.很多验证没有做,因为作为一个关于Jcrop的例子,很多验证不如与本文研究的范畴.服务器端采用MVC3实现. 直接贴代码,详解注释里面有了. 一.前台页面代码. <link href="http://www.cnblogs.com

【最新】2015年7月之15个最新jQuery插件

Hello,一个激动人心的好消息,现在我为大家整理最近7月发布的jQuery插件. 如果你熟悉任何下面列出的插件,请分享你的反馈与我们的读者,或如果你知道哪一个我们没有收录,那么请与我们分享在下面的评论部分. 我们希望你会发现这个列表下面这个列表对您很有用. 1. 固定表头 固定表头是一个jQuery塞进任何有效的表创建固定表头表标记了. 2. Stackgrid.adem.js stackgrid.adem.js 是一个非常快速和简单的JavaScript插件,帮助你创建一个动态级联网格 3.

2013年优秀jQuery插件

转载于:http://www.cnblogs.com/feng524822/p/3319534.html 今天为大家推荐的是2013年的第一期,在这期里面十个jQuery插件涵盖了响应式的 网格布局插件.图片放大插件.表单元素中自定义select插件,google 地图插件.文件拖放上传插件.tooltip提示插件.3D旋转菜单等等.这些插件的官网都提供了详细的API和相关代码下载,也提供了一些案例展示,可 以说稍懂一点前端的同学按照他们提供的API就会使用这些插件. 1.Makisu : jQ