zoukankan      html  css  js  c++  java
  • 仿百度文库实现文档在线预览

    一.分析

     

    实现方式

    ①   

    Txt/Word/Excel/PPT=>PDF(OpenOffice+JodConverter)=>SWF(pdf2swf)=>FlexPaper浏览

    ②   

    Txt/Word/Excel/PPT=>PDF(MSOffice+JACOB)=>SWF(pdf2swf)=>FlexPaper浏览

    ③   

    Txt/Word/Excel/PPT=>SWF (FlashPaper)=> FlexPaper浏览

    ④   

    Txt/Word/Excel/PPT=>SWF(print2flash)=> FlexPaper浏览

    前两种方式比较麻烦,都是先转成PDF,再转成SWF,最后用FlexPaper浏览。后两种比较快捷,可直接将源文件转为SWF,用 FlexPaper浏览。由于FlashPaper不是开源工具,加之Win7系统不兼容(我现在用的系统),所以就没采用第三种实现方式。 Print2flash是开源工具,即使公司产品中用到也不会出现版权纠纷,遗憾的是没找到如何用程序控制该工具转换文件的命令。第二种方式转PDF的时 候相当复杂,也淘汰掉了。最后直接用的第一种方式。

     

     

    二.功能所需工具

    下载工具

    OpenOffice

    http://zh.openoffice.org/new/zh_cn/downloads.html

    JodConverter

    http://dldx.csdn.net/fd.php?i=992314146801277&s=08dbee95a6e2dda1a95aa8cbf4df197b

    Swftools(pdf2swf)

    http://dldx.csdn.net/fd.php?i=389133735472350&s=2f7430ad3c00cca78ada8b4671a50b24

    xpdf-chinese-simplified.tar.gz (pdf2swf的中文语言包)

    ftp://ftp.foolabs.com/pub/xpdf/xpdf-chinese-simplified.tar.gz

    FlexPaper

    http://flexpaper.googlecode.com/files/FlexPaper_1.4.5_flash.zip

     

    本来想把自己实际用到没问题的安装文件上传上来,但是太大了,无法共享。 当时的下载地址又找不到了,好吧,悲催了。截图自己用到的版本

     

    ***三、搭建所需环境及实现

    第一步:安装OpenOffice。从上述下载地址得到可执行安装文件,直接双击执行,安装过程较为人性化,只需选择下一步即可。此处注意下安装路径,文件转换之前需在Windows命令行窗口打开安装根目录,然后执行开启服务命令。找到安装路径并执行:cd C:Program FilesOpenOffice.org 3program,再执行soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard。可用telnet localhost 8100测试

    第二步:解压JodConverter。解压目录结构如下图:

     

    打开lib文件夹,

    将其中的jar包复制到Web工程的WebRoot/WEB-INF/lib下。

    第三步:安装Swftools。从下载的压缩包中解压得到可执行安装文件,直接双击执行。该转换工具用来将 pdf文件转换成swf文件。改工具既可以安装使用实现文件转换,也拷贝安装后Program Files下的Swftools文件夹放到工程中,以绿色软件方式来使用。转换命令将在FileConverterUtil.java中特别指明。

    第四步:使用Flexpaper。Flexpaper就是一个播放swf文件的播放器。解压后目录如下:

    其中Paper.swf、所有的txt文件、php文件夹和example文件夹都可以删掉。清理完之后,新建readFile.jsp(jsp页面代码在后面附加),然后将flexpaper文件夹拷贝到WebRoot下即可。

    FileConverterUtil.java代码如下:

     

     

     

    import java.io.BufferedReader;

    import java.io.File;

    import java.io.IOException;

    import java.io.InputStream;

    import java.io.InputStreamReader;

    import java.io.LineNumberReader;

    import java.util.HashMap;

    import java.util.List;

    import java.util.Properties;

     

    import org.apache.struts2.ServletActionContext;

     

    import com.artofsolving.jodconverter.DocumentConverter;

    importcom.artofsolving.jodconverter.openoffice.connection.OpenOfficeConnection;

    importcom.artofsolving.jodconverter.openoffice.connection.SocketOpenOfficeConnection;

    import com.artofsolving.jodconverter.openoffice.converter.OpenOfficeDocumentConverter;

    import com.doone.comm.paginaction.Pagination;

    import com.doone.comm.struts.BaseAction;

    import com.doone.knowledge.info.dao.KnowledgeInfoDao;

     

     

    /**

     * 课件资源管理

     * @authorhsp

     *

     */

    public class KnowledgeInfoAction2 extends BaseAction{

     

       private Paginationpage = new Pagination();// 分页对象  

       private KnowledgeInfoDaoknowledgeInfoFacade;

       private HashMap<String,Object>knowledgeInfoMap = newHashMap<String,Object>();

      

      

       /**

        * 获取知识信息

        * @return

        */

       @SuppressWarnings("unchecked")

       public String seeKnowledgeInfo()throws Exception{

          String id=this.getRequest().getParameter("kinfoid");

         

          //信息评论分页:

          //设置每页显示多少条

          page.setPageRecord(5);

          //求出总记录数并判断是否为第一次查询

            if(getQueryFlag("page") == -1) {

               page.setTotalRecord(knowledgeInfoFacade.getKnowledgeRecommentCount(id));

            } else {

               page.setTotalRecord(getQueryFlag("page"));

           }

            //设置查询条件

          this.setPageParameters(page,"page");

          //结果List

          HashMap infoMap = knowledgeInfoFacade.getKnowledgeInfoInfo(id,page.getPageStart(), page.getPageRecord());

          knowledgeInfoMap=(HashMap)infoMap.get("kinfo");

          if(infoMap.get("krecomment")!=null&&!"".equals(infoMap.get("krecomment"))){

             List list=(List)infoMap.get("krecomment");

             this.getRequest().setAttribute("recommentList", list);

          }

          //文件类别

          String fileType =this.knowledgeInfoMap.get("KNOWLEDGE_FILE_TYPE").toString().substring(1,knowledgeInfoMap.get("KNOWLEDGE_FILE_TYPE").toString().length());

         

          //是否可预览标志  0普通文档,MP3SWF,可以预览         1 不支持的文件类型,不能预览        2MP4播放

          String previewFlag=""

          String returnValue="";

          //可以预览的文件

          if(fileType.equals("XLS")  || fileType.equals("PPT") || fileType.equals("DOC") ||fileType.equals("PDF") || fileType.equals("TXT") || fileType.equals("MP3") ||fileType.equals("SWF")){

             previewFlag = "0";

             returnValue="nomp4";

          }else if(fileType.indexOf(".MP4")>0){

             returnValue="mp4";

             previewFlag = "2";

          }else{

             returnValue="nomp4";

             previewFlag = "1";

          }

          System.out.println("fileType==========="+fileType+"=========="+ previewFlag+ previewFlag.equals("0"));

         

          /**************************************以下为文件预览*****************************************************/

          if(previewFlag.equals("0")){

                //服务器信息

                Properties props=System.getProperties();

                //不同系统分隔符

                String separator=props.getProperty("file.separator");

                //系统版本LinuxWindow XPWindow 7

                String os_name=props.getProperty("os.name");

                String os_flag="";

                if(os_name.indexOf("Linux")==0){

                    os_flag="linux";

                }else if(os_name.indexOf("Windows")==0){

                    os_flag="window";

                }

               

                //服务器存储的文件名称     201212171709212889.doc

                String sysFileName=this.knowledgeInfoMap.get("KNOWLEDGE_PATH").toString();

                //文件原名      年会活动初稿请车友定稿.doc

                String oriFileName =this.knowledgeInfoMap.get("KNOWLEDGE_FNAME").toString();

               

               

                //文件完整路径

                //window下是一个反斜杠

                //linux 是一个正斜杠/home/apache-tomcat-6.0.33/webapps/jd/WebRoot/upload/knowledge/201212181318342606.ppt

                String fullPath =ServletActionContext.getServletContext().getRealPath(separator+"upload"+separator+"knowledge"+separator+sysFileName);

                //文件夹名称绝对路径   F:\workspace\doone-jdedu\WebRoot\upload\knowledge

                StringfolderName=fullPath.substring(0,fullPath.lastIndexOf(separator));

                //sysFileName保持一致,如果已经存在,不再每次生成

                String sysFileName_temp =sysFileName.substring(0,sysFileName.lastIndexOf("."));

                //工程的绝对路径

                String basePath = this.getRequest().getScheme()+"://"+this.getRequest().getServerName()+":"+this.getRequest().getServerPort()+this.getRequest().getContextPath();

               

                File sourceFile;            //转换源文件

                File pdfFile;               //PDF媒介文件

                File swfFile;               //SWF目标文件

                File createPath;            //创建文件存放目录

                Runtime rt;                 //转换命令执行类

                String finalFilePath = "";    //最终显示在前台的转换之后的SWF文件名称

                String swfToolsPath ="";       //swfTools 安装路径,

                if(os_flag.equals("linux")){

                    swfToolsPath="";

                }else{

                   swfToolsPath ="C:\Program Files\SWFTools\";

                }

               

               

                 //swf

                if(fileType.equals("SWF")){

                    //文件原路径

                    finalFilePath = basePath+separator+"upload"+separator+"knowledge"+separator+sysFileName;

                    System.out.println("It'sSWF=================="+finalFilePath);

                }

                 //pdf

                if(fileType.equals("PDF")){

                    //PDF格式文件处理方式

                    rt = Runtime.getRuntime();

                    sourceFile = new File(fullPath);

                    //创建SWF文件存放目录

                    createPath = new File(folderName+separator+"swfFiles"+separator);

                    if(!createPath.isDirectory()){

                       createPath.mkdir();

                    }

                    swfFile = new File(folderName+separator+"swfFiles"+separator+sysFileName_temp+".swf");

                    //为了避免版本问题,不用7,8版本,用9

                    Process p= null;

                    if(os_flag.equals("window")){

                        p =rt.exec(swfToolsPath+"pdf2swf.exe" + sourceFile.getPath() +" -o " +swfFile.getPath() + " -T 9");

                    }else{

                        p =rt.exec("pdf2swf -slanguagedir=/usr/local/xpdf-chinese-simplified -T 9 -s poly2bitmap -s zoom=150-s flashversion=9 "+ sourceFile.getPath()+" -o "+swfFile.getPath());

                    }

                    //各系统清理缓存

                    if(os_flag.equals("window")){

                       clearCache(p.getInputStream(),p.getErrorStream());

                    }else if(os_flag.equals("linux")){

                        InputStreamReader ir=newInputStreamReader(p.getInputStream()); 

                        LineNumberReader input = new LineNumberReader(ir); 

                        Stringline; 

                        while ((line =input.readLine ()) !=null){ 

                          System.out.println("linux clear===================="+line);

                        } 

                    }

                    finalFilePath = basePath+separator+"upload"+separator+"knowledge"+separator+"swfFiles"+separator+sysFileName_temp+".swf";

                    System.out.println("It'sPDF=========sourceFile"+sourceFile.getPath()+"========="+swfFile+"========="+finalFilePath);

                }

                //pdf,非swf

                else{

                    System.out.println("It's "+fileType+"===================="+sysFileName_temp);

                    //PDF格式文件处理方式

                    if(isLegal(fileType.toUpperCase())){

                       sourceFile = new File(fullPath);

                       pdfFile = new File(folderName+separator+"swfFiles"+separator+sysFileName_temp+".pdf");

                       swfFile = new File(folderName+separator+"swfFiles"+separator+sysFileName_temp+".swf");

                       if(!pdfFile.exists()){

                          //获取连接对象

                          OpenOfficeConnection connection = newSocketOpenOfficeConnection(8100);

                          //取得连接

                          connection.connect();

                          //创建文件格式转换对象

                          DocumentConverter converter = newOpenOfficeDocumentConverter(connection);

                          //实现文件格式转换

                          converter.convert(sourceFile, pdfFile);

                          //生成已转换的PDF文件

                          pdfFile.createNewFile();

                          //释放连接

                          connection.disconnect();

                          System.out.println("create a new pdf=========="+pdfFile.getParent());

                          if(!swfFile.exists()){

                                rt = Runtime.getRuntime();

                                //执行PDF文件转换成SWF文件命令

                                //linux命令: pdf2swf -slanguagedir=/usr/local/xpdf-chinese-simplified-T 9 -s poly2bitmap -s zoom=150 -sflashversion=9"/home/s.pdf" -o "/home/%.swf"

                                Process p= null;

                                if(os_flag.equals("window")){

                                    p = rt.exec(swfToolsPath+"pdf2swf.exe " + pdfFile.getPath() +" -o " + swfFile.getPath() + " -T 9");

                                }else{

                                    p = rt.exec("pdf2swf -s languagedir=/usr/local/xpdf-chinese-simplified -T 9 -spoly2bitmap -s zoom=150 -s flashversion=9 "+ pdfFile.getPath() +" -o "+swfFile.getPath());

                                }

                                //各系统清理缓存

                                if(os_flag.equals("window")){

                                   clearCache(p.getInputStream(),p.getErrorStream());

                                }elseif(os_flag.equals("linux")){

                                    InputStreamReader ir=newInputStreamReader(p.getInputStream()); 

                                    LineNumberReader input = new LineNumberReader(ir); 

                                    String line; 

                                    while ((line = input.readLine ()) !=null){ 

                                      System.out.println("linux clear===================="+line);

                                    } 

                                }

                                System.out.println("create a new swf=========="+swfFile.getParent());

                          }

                       }else{

                          //如果已经存在了pdf,但是swf由于某种原因不存在

                          if(!swfFile.exists()){

                             rt = Runtime.getRuntime();

                             //执行PDF文件转换成SWF文件命令

                             //linux命令: pdf2swf -slanguagedir=/usr/local/xpdf-chinese-simplified-T 9 -s poly2bitmap -s zoom=150 -sflashversion=9 "/home/s.pdf"-o "/home/%.swf"

                             Process p= null;

                             if(os_flag.equals("window")){

                                 p= rt.exec(swfToolsPath+"pdf2swf.exe" + pdfFile.getPath() +" -o " +swfFile.getPath() + " -T 9");

                             }else{

                                 p= rt.exec("pdf2swf -s languagedir=/usr/local/xpdf-chinese-simplified-T 9 -s poly2bitmap -s zoom=150 -s flashversion=9 "+ pdfFile.getPath() +" -o "+swfFile.getPath());

                             }

                             //各系统清理缓存

                             if(os_flag.equals("window")){

                                clearCache(p.getInputStream(),p.getErrorStream());

                             }elseif(os_flag.equals("linux")){

                                 InputStreamReader ir=newInputStreamReader(p.getInputStream()); 

                                 LineNumberReader input = new LineNumberReader(ir); 

                                 String line; 

                                 while ((line =input.readLine ()) !=null){ 

                                   System.out.println("linux clear===================="+line);

                                 } 

                             }

                             System.out.println("pdf exists,but create a new swf=========="+swfFile.getParent());

                            }

                          System.out.println("pdf exists=========="+swfFile.getParent());

                       }

                       finalFilePath = basePath+separator+"upload"+separator+"knowledge"+separator+"swfFiles"+separator+sysFileName_temp+".swf";

                      

                    }

                }

                //可以预览的,放解析后的文件完整路径到页面

                this.getSession().setAttribute("finalFilePath", finalFilePath);

          }

          this.getSession().setAttribute("previewFlag",previewFlag);

          this.getSession().setAttribute("fileType",fileType);

          return returnValue;

       }

      

      

       /**

        * 清理缓冲区

        * @param isi

        * @param ise  

        */

       public void clearCache(InputStream isi, InputStream ise){

          try {

          System.out.println("clearCache==========="+isi.toString()+"============"+ise.toString());

             final InputStream is1 = isi;

             //启用单独线程清空InputStream缓冲区

             new Thread(new Runnable() {

                 public void run() {

                    System.out.println("before BufferedReader=========================");

                     BufferedReaderbr = new BufferedReader(new InputStreamReader(is1));

                     try {

                       while(br.readLine() !=null) ;

                    } catch (IOException e) {

                       e.printStackTrace();

                    }

                 }

             }).start();

             //读入ErrorStream缓冲

             System.out.println("333333333333333333333333");

             BufferedReader br = new BufferedReader(new InputStreamReader(ise));

             //保存缓冲输出结果

             StringBuilder buf = new StringBuilder();

             String line = null;

             try {

                System.out.println("beforereadLine==================");

                line = br.readLine();

             } catch (IOException e) {

                e.printStackTrace();

             }

             //循环等待进程结束

             while(line !=null)

                buf.append(line);

             is1.close();

             ise.close();

             br.close();

          } catch (Exception e) {

             System.out.println("clearCacheException==========="+e+"============");

             e.printStackTrace();

          }

       }

      

      

       /**

        * 判断所转换文件类型是否合法

        * @paramgetFileType //文件格式

        * @param fileLegalFlag  //是否合法标志  false:非法   true:合法

        */

      

       public boolean isLegal(String getFileType){

          boolean fileLegalFlag =false;

          if(getFileType.equals("TXT")){

             fileLegalFlag = true;

          }else if(getFileType.equals("DOC")||getFileType.equals("DOCX")){

             fileLegalFlag = true;

          }else if(getFileType.equals("PPT")||getFileType.equals("PPTX")){

             fileLegalFlag = true;

          }else if(getFileType.equals("XLS")||getFileType.equals("XLSX")){

             fileLegalFlag = true;

          }

          return fileLegalFlag;

       }

      

    }

     

     

     

     

     

     

    readFile.jsp页面代码如下:

    <%@ page language="java"import="java.lang.String"pageEncoding="UTF-8"%>

    <%

    String path =request.getContextPath();

    String getFilePath =request.getParameter("recFileName");

    String basePath =request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";

    %>

     

     

    <!DOCTYPEHTML PUBLIC "-//W3C//DTDHTML 4.01 Transitional//EN">

    <htmlxmlns="http://www.w3.org/1999/xhtml"lang="en"xml:lang="en">

      <head>

       

        <title>在线阅读</title>

            <styletype="text/css"media="screen">

             html, body  { height:100%; }

             body { margin:0; padding:0; overflow:auto; }  

             #flashContent { display:none; }

            </style>

          <!--

          <script type="text/javascript"src="js/flexpaper_flash.js"></script>

           -->

           <scripttype="text/javascript"src="${pageContext.request.contextPath}/knowledge/info/js/jquery.js"></script>

           <scripttype="text/javascript"src="${pageContext.request.contextPath}/knowledge/info/js/flexpaper_flash_debug.js"></script>

           <scripttype="text/javascript"language="javascript"src="${pageContext.request.contextPath}/knowledge/info/js/flexpaper_flash.js"></script>

         

      </head>

     

      <body>

      <divstyle="position:absolute;left:200px;top:0px;">

              <%    //是否可预览   0可预览   1 不可预览

                    StringpreviewFlag=(String)session.getAttribute("previewFlag");

                    //文件类型  swf的直接播放

                     StringfileType=(String)session.getAttribute("fileType");

                     //swf,MP3预览

                    if(previewFlag.equals("0") &&!fileType.equals("SWF") && !fileType.equals("MP3"))  {

                    %>

               <aid="viewerPlaceHolder"style="1000px;height:778px;display:block">http://172.0.6.26:8081/jd/upload/knowledge/swfFiles <%=(String)session.getAttribute("finalFileName")%>/</a>

               <scripttype="text/javascript">

                 var fp =new FlexPaperViewer( 

                        '<%=basePath%>knowledge/info/FlexPaperViewer',

                        'viewerPlaceHolder', { config : {

                        SwfFile :escape('<%=(String)session.getAttribute("finalFilePath")%>'),

                        Scale :0.6,

                        ZoomTransition : 'easeOut',

                        ZoomTime :0.5,

                        ZoomInterval : 0.2,

                        FitPageOnLoad : true,

                        FitWidthOnLoad : false,

                        PrintEnabled : false,

                        FullScreenAsMaxWindow : false,

                        ProgressiveLoading : true,

                        MinZoomSize: 0.2,

                        MaxZoomSize: 5,

                        SearchMatchAll : false,

                        InitViewMode : 'Portrait',

                        

                        ViewModeToolsVisible : true,

                        ZoomToolsVisible : true,

                        NavToolsVisible : true,

                        CursorToolsVisible : true,

                        SearchToolsVisible : true,

                      

                        localeChain: 'zh_CN'

                        }});

               </script>

                <%}

                    //swf预览

                    else if(previewFlag.equals("0") &&fileType.equals("SWF")){

                 %>

                      <objectid="FlashID"classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"width="1000"height="778">

                                 <paramname="movie"value="<%=(String)session.getAttribute("finalFilePath")%>"/>

                                 <paramname="quality"value="high"/>

                                 <paramname="wmode"value="opaque"/>

                                 <paramname="swfversion"value="8.0.35.0"/>

                                 <!-- param标签提示使用 Flash Player 6.0 r65和更高版本的用户下载最新版本的 Flash Player。如果您不想让用户看到该提示,请将其删除。 -->

                                 <paramname="expressinstall"value="Scripts/expressInstall.swf"/>

                                 <!-- 下一个对象标签用于非 IE 浏览器。所以使用 IECC 将其从 IE 隐藏。 -->

                                 <!--[if !IE]>-->

                                 <objecttype="application/x-shockwave-flash"data="${pageContext.request.contextPath}/images/jdindeximages/fla.swf"width="960"height="209">

                                  <!--<![endif]-->

                                  <paramname="quality"value="high"/>

                                  <paramname="wmode"value="opaque"/>

                                  <paramname="swfversion"value="8.0.35.0"/>

                                  <paramname="expressinstall"value="Scripts/expressInstall.swf"/>

                                  <!-- 浏览器将以下替代内容显示给使用 Flash Player 6.0和更低版本的用户。 -->

                                  <div>

                                    <h4>此页面上的内容需要较新版本的 Adobe Flash Player。</h4>

                                   <p><ahref="http://www.adobe.com/go/getflashplayer"><imgsrc="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif"alt="获取 Adobe Flash Player" width="112"height="33"/></a></p>

                                  </div>

                                  <!--[if !IE]>-->

                                </object>

                            <!--<![endif]-->

                       </object>

                       <%

                     }

                    //mp3预览

                    else if(previewFlag.equals("0") &&fileType.equals("MP3")){

                     %>

                      <objectclassid="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA" width="640"height="90"id="rp">

                                 <paramname="autostart"value="1"/>

                                  <paramname="controls"value="IMAGEWINDOW,ControlPanel,StatusBar"/>

                                  <paramname="console"value="Clip1"/>

                                  <paramname="type"value="audio/x-pn-realaudio-plugin"/>

                                  <paramname="src"value="rtsp://172.0.0.16:554/knowledge/${knowledgeInfoMap.KNOWLEDGE_PATH}"/>

                      </object>

                     <%

                    }

                     //不能预览的

                    else if(previewFlag.equals("1")){

                     %>

                       

                       对不起,不支持预览,请直接下载

                    <%

                    }

                 %>

            </div>

       </body>

    </html>

     

     

     

     

     

    windows下OpenOffice服务启动命令:

    cd C:Program FilesOpenOffice.org 3program

    soffice -headless-accept="socket,host=127.0.0.1,port=8100;urp;" –nofirststartwizard

    启动后在进程中可以看到soffice

    linux 下openoffice启动命令:

    /opt/openoffice.org3/program/soffice -headless -accept="socket,host=127.0.0.1,port=8100;urp;" -nofirststartwizard &

    需注意的问题

    转换TXT时内容中文乱码问题

    反编译jodconverter-2.2.2.jar,反编译好的已经放在在线阅读文件夹下。Jodconverter-2.2.1.jar不出现TXT乱码问题,但是不支持office2007格式的文件转换。

    Flexpaper不支持中文路径

    中文名称的文件转换成了汉语拼音.swf

    参考资料

    http://topic.csdn.net/u/20110712/18/4daf5746-e64e-434d-aeb0-77b05f6c9903.html

    http://www.cnblogs.com/qinpeifeng107/archive/2011/08/29/2158879.html

    http://blog.csdn.net/liuyuhua0066/article/details/6603493

    http://blog.csdn.net/lyq123333321/article/details/6546104

    http://www.cnblogs.com/compass/articles/2046311.html

    Swftools在linux下安装: http://www.cnblogs.com/jony413/articles/2650765.html



    在网友基础上改进,时间太久,忘记出处,表示歉意和感谢。


    另附本文档,源代码及部分安装文件的下载地址:http://download.csdn.net/detail/qingwangyoucao/5043933


  • 相关阅读:
    C# json字符串格式
    JS网页换肤
    JS 播放列表收缩展开
    js学习系列之-----apply和call
    JS下拉图片Demo3
    算法---001
    inline-block 左边固定,右边自适应
    css3动画特效:上下晃动的div
    通过js写一个消息弹框
    css3 操作动画要点
  • 原文地址:https://www.cnblogs.com/coprince/p/3309343.html
Copyright © 2011-2022 走看看