Node.js學(xué)習(xí)第九天筆記之切圖功能

1 切圖

  • 圖像的裁切功能
    • 前提條件:下載安裝GraphicsMagick
    • 模塊:第三方模塊gm模塊绳军;
    • 步驟:
      1. 引入模塊凤类;引入gm模塊;var gm = require('gm');
      2. 使用gm()臭墨;
        • gm括號(hào)中為需要裁切的圖片的地址,
        • resize()為裁切后的寬高皮假,里面設(shè)置"!",則為強(qiáng)制骂维,按照設(shè)置大小生成文件惹资,否則,等比例生成文件航闺;
        • crop()為裁切的尺寸褪测,分別為寬,高潦刃,左邊距侮措,上邊距;
        • write("path",function(err){}):指的是生成文件放置的地址和名稱乖杠,匿名函數(shù)中設(shè)置裁切成功后的操作萝毛;
        • 代碼:
         var gm = require('gm');
         gm("./img/meinv.jpg")
             .crop(240,100,720,415)
             .resize(200, 200,"!")//強(qiáng)制變?yōu)?00*200的文件;
             .write("./img/meinv2.jpg",function (err) {
                 if(err){
                     res.send({"bok":false,"msg":err});
                 }else{
                     res.send({"bok":true,"msg":"截圖成功"})
                 }
             })
        

2 扒網(wǎng)站滑黔,實(shí)現(xiàn)截圖效果

  • 前端開發(fā)倉(cāng)庫(kù)
  • node.js實(shí)現(xiàn)切圖环揽;
    • 思路:
      • 發(fā)送get請(qǐng)求"/index"略荡,渲染頁(yè)面;
      • 給按鈕添加點(diǎn)擊事件歉胶,在事件觸發(fā)后汛兜,通過(guò)ajax發(fā)送get請(qǐng)求,將數(shù)據(jù)傳到服務(wù)器通今;
      • 獲取原代碼中的截圖元素粥谬,獲取其寬高和定位left,top值;作為切圖的數(shù)值辫塌;
      • 服務(wù)器拿到數(shù)據(jù)漏策,通過(guò)gm模塊進(jìn)行裁切原圖;然后保存臼氨;
      • 裁切成功后掺喻,響應(yīng)給頁(yè)面,通過(guò)ajax中success拿到數(shù)據(jù)储矩,彈出提示感耙,刷新頁(yè)面;
    • 注意:
      • 必須在點(diǎn)擊事件中持隧,獲取元素即硼,拿到數(shù)據(jù);不能再點(diǎn)擊事件外拿屡拨,否則只酥,拿到的數(shù)據(jù)均為0褥实;
      • 如果圖片在頁(yè)面中被縮放,需要拿到比例层皱,傳給服務(wù)器性锭,因?yàn)椋?wù)器是在原圖上裁切的叫胖;
    • 知識(shí)點(diǎn):
      • 如果一個(gè)元素設(shè)置定位草冈,在jQuery中通過(guò)$("xx").position().left$("xx").position().top來(lái)獲取left和top值;
    • 代碼:
      • ejs中自己寫的script代碼:
       <script>
           //必須在點(diǎn)擊事件觸發(fā)后瓮增,在獲取元素拿值怎棱,否則,無(wú)法拿到值绷跑;
           $("#btn").click(function () {
               var $img=$("#target");
               var imgw=$img.width();
               var bl=1366/imgw;//獲取到一個(gè)比例拳恋;
               var $div=$(".jcrop-holder>div:eq(0)");
               var w=$div.width()*bl;
               var h=$div.height()*bl;
               var l=$div.position().left*bl;
               var t=$div.position().top*bl;
               $.ajax({
                   url:"/jietu",
                   type:"get",
                   data:{w,h,l,t},
                   success:function (val) {
                       if(val.bok){
                           alert(val.msg);
                           window.location.href="/index";//更新頁(yè)面;
                       }else{
                           console.log(val.msg);
                       }
                   }
               })
           })
       </script>
      
      • 服務(wù)器代碼:
       const express=require("express");
       const fs=require("fs");
       const gm=require("gm");
       const app=express();
       app.listen(8080);
       
       //設(shè)置ejs模板引擎
       app.set("view engine","ejs");
       //設(shè)置靜態(tài)資源目錄
       app.use(express.static("./public"));//此靜態(tài)資源是為了引入css和js等砸捏;
       //設(shè)置靜態(tài)資源目錄
       app.use(express.static("./img"));//此靜態(tài)資源是為了引入圖片谬运;
       
       //發(fā)送請(qǐng)求渲染頁(yè)面;
       app.get("/index",function (req, res) {
           res.render("index");
       });
       //ajax發(fā)送請(qǐng)求垦藏,截圖
       app.get("/jietu",function (req, res) {
           //獲取到參數(shù)值
           var {w,h,l,t}=req.query;
           //切圖
           gm("./img/meinv.jpg")
               .crop(w,h,l,t)
               .write("./img/meinv2.jpg",function (err) {
                   if(err){
                       res.send({"bok":false,"msg":err});
                   }else{
                       res.send({"bok":true,"msg":"截圖成功"})
                   }
               })
       });
      

3 封裝后的裁圖文件

  • 封裝后的文件
    • 文件存儲(chǔ)github地址:cutImg
    • 服務(wù)器cutapp.js
     //1.express三步創(chuàng)建服務(wù)器基本構(gòu)架
     const express=require("express");
     const app=express();
     app.listen(3333,function () {
         console.log("3333 server is running");
     });
     //2.引入node系統(tǒng)模塊
     const path=require("path");
     const fs=require("fs");
     //3.引入第三方模塊
     const formidable=require("formidable");
     const sd=require("silly-datetime");
     const gm=require("gm");
     
     //4.設(shè)置ejs模板引擎
     app.set("view engine","ejs");
     
     //5.設(shè)置靜態(tài)資源目錄
     //1)加載ejs文件中的css,js等靜態(tài)資源
     app.use("/public",express.static("./public"));
     //2)加載uploads文件夾中上傳的圖片
     app.use("/uploads",express.static("./uploads"));
     //3)加載avatar文件夾上的裁切后的圖片
     app.use("/avatar",express.static("./avatar"));
     
     //6.設(shè)置路由
     //1)加載上傳文件目錄
     app.get('/tofile',function (req, res, next) {
         res.render('tofile',{});
     });
     //2)提交上傳文件數(shù)據(jù)
     app.post('/todata',function (req, res, next) {
         //新建form對(duì)象
         var form=new formidable.IncomingForm();
         //設(shè)置文件上傳路徑
         form.uploadDir="./uploads/";
         //解析上傳的文件參數(shù)
         form.parse(req,function (err, fields, files) {
             if(err){
                 console.log('formidble錯(cuò)誤');
                 return;
             }
             var oldPath=files.myfile.path;
             var originName=files.myfile.name;
             var originNameObj=path.parse(originName);
             var newName="gms"+sd.format(new Date(),"YYYYMMDD_HHmmss")+originNameObj.ext;
             var newPath=form.uploadDir+newName;
             //更換上傳的文件路徑和名字
             fs.rename(oldPath,newPath,function (err) {
                 if(err){
                     console.log('圖片重命名失敗');
                     return;
                 }
                 res.send({'bok':true,'msg':'上傳圖片成功0鹋!掂骏!','imgsrc':newName});
             });
         })
     });
     //3)渲染裁切圖頁(yè)面
     app.get('/showcutimg',function (req, res, next) {
         var cutimgSrc=req.query.cursrc;
         res.render('mycut',{
             imgsrc:cutimgSrc
         })
     });
     //4)裁切圖片
     app.get('/cutimg',function (req, res, next) {
         var curobj=req.query;
         gm("./uploads/"+curobj.imgsrc)
             .crop(curobj.w,curobj.h,curobj.x,curobj.y)
             .resize(curobj.xsize,curobj.ysize,"!")
             .write("./avatar/"+curobj.imgsrc,function (err) {
                 if(err){
                     res.send({"bok":false,"msg":err});
                 }else{
                     res.send({"bok":true,"msg":"截圖成功"})
                 }
             });
     });
    
    • 上傳頁(yè)面tofile.ejs
     <!DOCTYPE html>
     <html lang="zh-CN">
     <head>
         <meta charset="utf-8">
         <meta http-equiv="X-UA-Compatible" content="IE=edge">
         <meta name="viewport" content="width=device-width, initial-scale=1">
         <!-- 上述3個(gè)meta標(biāo)簽*必須*放在最前面轰驳,任何其他內(nèi)容都*必須*跟隨其后! -->
         <title>文件上傳頁(yè)面</title>
     
         <!-- Bootstrap -->
         <link href="/public/vender/bootstrap/css/bootstrap.css" rel="stylesheet">
     
         <!-- HTML5 shim 和 Respond.js 是為了讓 IE8 支持 HTML5 元素和媒體查詢(media queries)功能 -->
         <!-- 警告:通過(guò) file:// 協(xié)議(就是直接將 html 頁(yè)面拖拽到瀏覽器中)訪問(wèn)頁(yè)面時(shí) Respond.js 不起作用 -->
         <!--[if lt IE 9]>
         <script src="https://cdn.jsdelivr.net/npm/html5shiv@3.7.3/dist/html5shiv.min.js"></script>
         <script src="https://cdn.jsdelivr.net/npm/respond.js@1.4.2/dest/respond.min.js"></script>
         <![endif]-->
     </head>
     <body>
     <div class="container files">
         <div class="row">
             <form class="form-horizontal col-xs-4 col-xs-offset-4">
                 <div class="form-group">
                     <h1 style="margin-top: 150px">請(qǐng)上傳圖像</h1>
                     <label for="myimg">上傳文件</label>
                     <input type="file" id="myimg" name="myfile">
                     <div class="checkbox">
                         <label>
                             <input type="checkbox"> Check me out
                         </label>
                     </div>
                     <button type="button" class="btn btn-primary" id="toBtn">上傳</button>
                 </div>
             </form>
         </div>
     </div>
     
     <!-- jQuery (Bootstrap 的所有 JavaScript 插件都依賴 jQuery弟灼,所以必須放在前邊) -->
     <script src="/public/vender/jquery/jquery.js"></script>
     <!-- 加載 Bootstrap 的所有 JavaScript 插件级解。你也可以根據(jù)需要只加載單個(gè)插件。 -->
     <script src="/public/vender/bootstrap/js/bootstrap.js"></script>
     <script>
         //通過(guò)ajax上傳file文件信息
         $('#toBtn').on('click',function () {
             //獲取form表單的數(shù)據(jù)
             var formData=new FormData();
             formData.append('myfile',$('#myimg')[0].files[0])
             //ajax發(fā)送請(qǐng)求
             $.ajax({
                 url: '/todata',
                 type: 'POST',
                 data:formData,
                 dataType: 'json',
                 contentType: false,//不需要頭田绑;
                 processData: false,//不轉(zhuǎn)換數(shù)據(jù)
                 success: function (data) {
                     alert(data.msg);
                     window.location.href='/showcutimg?cursrc='+data.imgsrc;
                 },
                 error: function (err) {
                     console.log(err);
                 }
             })
         })
     </script>
     </body>
     </html>
    
    • 裁切頁(yè)面cutimg.ejs
     <!DOCTYPE html>
     <html lang="en">
     <head>
         <title>截圖頁(yè)面</title>
         <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
         <script src="/public/js/jquery.min.js"></script>
         <script src="/public/js/jquery.Jcrop.js"></script>
         <script src="/public/js/jquery-cut.js"></script>
         <script src="/public/js/mycut.js"></script>
         <link rel="stylesheet" href="/public/css/main.css" type="text/css" />
         <link rel="stylesheet" href="/public/css/demos.css" type="text/css" />
         <link rel="stylesheet" href="/public/css/jquery.Jcrop.css" type="text/css" />
         <link rel="stylesheet" href="/public/css/jquery-cut.css" type="text/css" />
         <link rel="stylesheet" href="/public/css/mycut.css" type="text/css" />
         <style rel="stylesheet" type="text/css">
             #preview-pane .preview-container{
                 width: 200px;
                 height: 200px;
             }
             .jcrop-holder #preview-pane{
                 top: 30%;
                 right: -300px;
             }
         </style>
     </head>
     <body>
     <div class="container">
         <div class="row">
             <div class="span12">
                 <div class="jc-demo-box">
                     <img src="/uploads/<%= imgsrc%>" data-imgsrc="<%= imgsrc%>" id="target" alt="cuttu" />
                     <div id="preview-pane">
                         <div class="preview-container">
                             <img src="/uploads/<%= imgsrc%>" class="jcrop-preview" alt="Preview" />
                         </div>
                     </div>
                     <div class="description">
                         <button id="btn">提交截圖</button>
                     </div>
                     <div class="clearfix"></div>
                 </div>
             </div>
         </div>
     </div>
     </body>
     <script>
         //必須先聲明
         var curobj;
         $("#btn").click(function () {
             curobj.imgsrc=$("#target").data("imgsrc");
             $.ajax({
                 url:"/cutimg",
                 type:"get",
                 data:curobj,
                 dataType: "json",
                 success:function (val) {
                     if(val.bok){
                         alert(val.msg);
                         window.location.href="/tofile";//裁切成功后勤哗,跳轉(zhuǎn)回上傳文件頁(yè)面
                     }else{
                         console.log(val.msg);
                     }
                 },
                 error:function (err) {
                     console.log(err);
                 }
             })
         });
     </script>
     </html>
    
    • 項(xiàng)目介紹
     1.項(xiàng)目介紹:完成圖片上傳到裁切的功能;
     2.項(xiàng)目依賴
       express gm ejs formidable silly-datetime
     3.項(xiàng)目運(yùn)行
       1)下載node掩驱,運(yùn)行cutapp.js服務(wù)器
       2)網(wǎng)頁(yè)地址:http://localhost:3333/tofile  加載上傳文件頁(yè)面
     4.目錄分析
       uploads: 圖片上傳后的地址
       avatar: 圖片裁切后俺陋,保存的地址
    

4 知識(shí)點(diǎn)

  • gm的一些命令
    • 顯示圖像文件詳細(xì)信息:gm identify a.jpg;
    • 格式轉(zhuǎn)換:gm convert a.jpg a.png;
    • 注意:必須在圖片的目錄下;運(yùn)行命令昙篙;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末腊状,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子苔可,更是在濱河造成了極大的恐慌缴挖,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件焚辅,死亡現(xiàn)場(chǎng)離奇詭異映屋,居然都是意外死亡苟鸯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門棚点,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)早处,“玉大人,你說(shuō)我怎么就攤上這事瘫析∑霭穑” “怎么了?”我有些...
    開封第一講書人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵贬循,是天一觀的道長(zhǎng)咸包。 經(jīng)常有香客問(wèn)我,道長(zhǎng)杖虾,這世上最難降的妖魔是什么烂瘫? 我笑而不...
    開封第一講書人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮奇适,結(jié)果婚禮上坟比,老公的妹妹穿的比我還像新娘。我一直安慰自己嚷往,他們只是感情好温算,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著间影,像睡著了一般。 火紅的嫁衣襯著肌膚如雪茄茁。 梳的紋絲不亂的頭發(fā)上魂贬,一...
    開封第一講書人閱讀 49,821評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音裙顽,去河邊找鬼付燥。 笑死,一個(gè)胖子當(dāng)著我的面吹牛愈犹,可吹牛的內(nèi)容都是我干的键科。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼漩怎,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼勋颖!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起勋锤,我...
    開封第一講書人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤饭玲,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后叁执,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體茄厘,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡矮冬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了次哈。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胎署。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖窑滞,靈堂內(nèi)的尸體忽然破棺而出琼牧,到底是詐尸還是另有隱情,我是刑警寧澤葛假,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布障陶,位于F島的核電站,受9級(jí)特大地震影響聊训,放射性物質(zhì)發(fā)生泄漏抱究。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一带斑、第九天 我趴在偏房一處隱蔽的房頂上張望鼓寺。 院中可真熱鬧,春花似錦勋磕、人聲如沸妈候。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)苦银。三九已至,卻和暖如春赶站,著一層夾襖步出監(jiān)牢的瞬間幔虏,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工贝椿, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留想括,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓烙博,卻偏偏與公主長(zhǎng)得像瑟蜈,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子渣窜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349