<テンプレート> の<divクラス= "作物イメージ":スタイル= "wrapStyle"> <IMG:SRC = "URL" ALT = "" crossOrigin = "匿名":スタイル= "imgStyle" V-IF = "URL"> <キャンバスREF = "キャンバス" @マウスダウン= "れるonmousedown" @のMouseMove = "れるonmousemove" @マウスホイール= "onmousewheel"> </キャンバス> </ div> </テンプレート> <スクリプト> 輸出デフォルト{ 名:「クロップ-画像」、 小道具:{ OPT:{ タイプ:オブジェクト、 デフォルト(){ リターン{ 幅:400、 高さ:400、 addScale:0.06 //スケーリングされた速度 }; } } }、 データ(){ リターン{ IMG:ヌル、 URL:ヌル、 imgInfo:NULL、//情報圧縮前 imgCInfo:NULL、//後の圧縮情報 ヌル前情報、//圧縮:のClipInfo clipCinfo:ヌル、圧縮後の情報@ NULL、//スケッチ:CTX POS:{X:0、Y:0}、 DEG:0 } }、 計算:{ wrapStyle(){ リターン{ 幅: `$ {this.opt.width px`}、 高さ: `$ {this.opt.height px`} } }、 imgStyle(){ LET imgCInfo = this.imgCInfo。 IF(imgCInfo){ リターン{ 幅: `$ {imgCInfo.w} px`、 高さ:` $ {imgCInfo.h} px`、 左: `$ {this.pos.x} px`、 トップ:` $ { this.pos.y} px`、 変換: `回転Z($ {this.deg} DEG)`、 transformOrigin: "中心" } } 戻り{高さ: "0PX"、高さ"0PX"、表示: "なし" }。 } }、 {)(取り付けられた キャンバスがこの=せ$ refs.canvas。 canvas.width = this.opt.width。 canvas.height = this.opt.height。 this.ctx =キャンバス。 window.addEventListener( "のmouseup"、this.onmouseup)。 }、 INIT(SRC、結合){ this.setSrc(SRC) this.setClip(結合) }、 loadImage(URL、ATTRS)は{ )(IMGは、新しいイメージを=ましょう。 img.src = URL; ATTRS = ATTRS || {}; {(I ATTRSでましょう)のために 、IMG [I] = ATTRS [I] } 戻り新しいプロミス((決意、リジェクト)=> { img.onload =関数(){ 解決(IMG); }; img.onerrorの=拒否; }); }、 圧縮(ターゲット){ //压缩比例 OPT = this.optてみましょう。 wRate = opt.width / opt.heightてみましょう。 tRate = target.width / target.heightてみましょう。 時間、スケール、wはましょう。 IF(wRate> tRate){ H = opt.height。 スケール= H / target.height。 W =規模* target.width。 }他{ = opt.width W。 スケールは、W / target.width =。 H =規模* target.height。 } 戻り{ W、H、スケール } } //外部调用 非同期setSrc(SRC){ 非同期exportBase(){ せIMG =のawait this.loadImage(SRC、{crossOrigin: "匿名"})。 this.url = SRC; this.img = IMG; this.setImg(IMG)。 } //外部调用 setClipメソッド(CLIPINFO){ IF(CLIPINFO){ this.clipInfo = { W:clipInfo.width、 H:clipInfo.height }。 this.clipCinfo = this.compress(CLIPINFO)。 this.clipCinfo.x =(this.opt.width - this.clipCinfo.w)/ 2。 this.clipCinfo.y =(this.opt.height - this.clipCinfo.h)/ 2。 this.fill(); } }、 //导出图片BASE64 度= this.degてみましょう。 POS = this.posてみましょう。 clipCinfo = this.clipCinfoてみましょう。 imgCInfo = this.imgCInfoてみましょう。//压缩后的宽高 ましょうimgInfo = this.imgInfo。//原始的宽高 規模= imgCInfo.scaleをしましょう。 SX = clipCinfo.xてみましょう- pos.x。 SY = clipCinfo.yてみましょう- pos.y。 キャンバス=のdocument.createElement(「キャンバス」)しましょう。 canvas.width =のparseInt(clipCinfo.w /スケール)。 canvas.height =のparseInt(clipCinfo.h /スケール)。 swidth = imgInfo.wてみましょう。 sheight = imgInfo.hてみましょう。 IF(swidth <canvas.width){ swidth = canvas.width } IF(sheight <canvas.height){ sheight = canvas.height } CTX = canvas.getContext( "2D")とします。 IMG = this.imgてみましょう。 IF(DEG!= 0){ IMG =のawait this.loadImage(this.getRotateImg())。 IF(DEG == 90 ||度== 270){ //竖着的、需要坐标转换 せ、X = pos.x +(imgCInfo.w -imgCInfo.h)/ 2。 Y = pos.y +(imgCInfo.h -imgCInfo.w)/ 2ましょう。 SX = clipCinfo.x - X。 SY = clipCinfo.y - Y。 } } SX / =スケール; SY / =スケール; ctx.drawImage(IMG、SX、SY、swidth、sheight、0,0、swidth、sheight)。 リターンcanvas.toDataURL( "画像/ PNG")。 }、 回転(フラグ){ //旋转 せ度= this.deg。 IF(フラグ){ ゜+ = 90。 }他{ ゜- = 90。 } IF(DEG> = 360){ 度- = 360。 } IF(゜<= 0){ ゜+ = 360。 } this.deg =゜; }、 getRotateImg(){ //获取旋转后的图片 DEG = this.degてみましょう。 imgInfo = this.imgInfoてみましょう。 キャンバス=のdocument.createElement(「キャンバス」)しましょう。 W、Hをしましょう。 IF(DEG == 90 ||度== 270){ //垂直 W = imgInfo.h。 H = imgInfo.w。 }他{ //横着的 W = imgInfo.w。 H = imgInfo.h。 } canvas.width = W。 canvas.height = H; CTX = canvas.getContext( "2D")とします。 ctx.translate(W / 2、H / 2)。 ctx.rotate(DEG *にMath.PI / 180)。 ctx.drawImage(this.img、0,0、imgInfo.w、imgInfo.h、-imgInfo.w / 2、-imgInfo.h / 2、imgInfo.w、imgInfo.h)。 リターンcanvas.toDataURL( "画像/ PNG")。 }、 setImg(IMG){ this.imgInfo = { W:img.width、 H:img.height }。 this.imgCInfo = this.compress(IMG)。 せ、X =(this.opt.width - this.imgCInfo.w)/ 2。 Y =せ(this.opt.height - this.imgCInfo.hを)/ 2。 this.pos = { X、Y }; }、 onMouseUpの(){ this.mouse = NULL; }、 (e)はれるonmousedown { this.mouse = { X:e.offsetX、 Y:e.offsetY } } れるonmousemove(E){ IF(this.mouse){ this.pos.x + = e.offsetX - this.mouse.x。 this.pos.y + = e.offsetY - this.mouse.y。 this.mouse = { X:e.offsetX、 Y:e.offsetY }。 } }、 onmousewheel(イベント){ event.preventDefault(); CONST方向=(event.wheelDelta || -event.detail)> 0?1:0。 addScale = this.opt.addScaleましょう|| 0.06; //放大 時間、スケール、wはましょう。 IF(方向){ H = this.imgCInfo.w *(1 + addScale)W。 }他{ //缩小 W = this.imgCInfo.w *(1 - addScale)。 } IF(W <10){ = 10、W; } W / this.imgInfo.wスケール=。 H = this.imgInfo.h *スケール。 X = this.pos.xせ- (W - this.imgCInfo.w)/ 2。 せY = this.pos.y - (H - this.imgCInfo.h)/ 2。 this.pos = { X、Y }; this.imgCInfo = { スケール、 W、 } }、 フィル(){ {W、H、X、Y} = this.clipCinfoましょう。 clipctx = this.ctxてみましょう。 OPT = this.optてみましょう。 clipctx.clearRect(0、0、opt.width、opt.height)。 clipctx.beginPath(); clipctx.fillStyle = 'RGBA(0,0,0,0.6)'。 clipctx.strokeStyle =「グリーン」。 //遮罩层 clipctx.globalCompositeOperation = "ソース・オーバー"。 clipctx.fillRect(0、0、opt.width、opt.height)。 //画框 clipctx.globalCompositeOperation = '先アウト'; clipctx.fillStyle = 'RGBA(0,0,0,1)'。 clipctx.fillRect(X、Y、 //描边 clipctx.globalCompositeOperation =「ソース・オーバー」。 clipctx.moveTo(X、Y) clipctx.lineTo(X + W、Y)。 clipctx.lineTo(X + Y +はH、W)。 clipctx.lineTo(X、Y +のH)。 clipctx.lineTo(X、Y) clipctx.stroke(); clipctx.closePath(); } } } </ SCRIPT> <スタイルのlang = "SCSS"スコープ> .crop画像{ ボーダー:1ピクセル固体RGB(35、184、255)。 マージン:20ピクセルオート; 位置:相対; オーバーフロー:隠されました; 背景:URL(データ:画像/ PNG; base64で、iVBORw0KGgoAAAANSUhEUgAAAR0AAACgCAYAAAAxSbhkAAAIHElEQVR4Xu3dsXIbRxCE4VViR44UOHOoF + D7v4jewIEiRmakwu2ydFtL2BYL09CCHyOJhTpKg8F / Fd2sve / Tksh9chfarbuwp7 + // Wg5tfablje97fash + B + vQ66Af9cMbE1X74NJrl8uLfWmuf34DLS2vt2xvf9 / peFPXpddAP + Ugniav9chiःo03ilo7ya79rlp9in + KOkH0FklnDHBmPC / Cshgs2v / VGatABHZAF2ShkQQd0QAd0QIfHNJEQFEAhCoXqFPuidF5jcimMFObc3PpBP5T0wwU6rl / UqO6oD3VHrb5ju / 7hrilag + dcoLO6un8dBGlGO9LMXxo3 / eh3b3fQAd0QNY + TSK + zrWbCuiADuiADuiMCvCYeEw8pge8KTp7tb6pUhupTUlq42zjUdYXy4ErdCgsCovCKlRYoAM6IAuyUciCDuiADuiAzqiAVEWqEk1Vdt9 / 2eXfT + lQOpQOpRNXOs5ezeDxG / B6PaR4UrySFM9yYKFLb83 / KK4x2Zg8jcmgAzqgAApR7wx0QAd0QAd0RgUYnAzOqMFpHM6Mw5QOpUPpUDpxpXNRFJcvqY3U5tx8 + A / lPSDPZ1V6RjrjHXGusIJAHRAB2RBNgpZ0AEd0AEd0BkVYHAyOKMG5y5nl3ZP2SgdSofSoXTiSsfZqxk8UhupTUlq01r7tt7jPl5qbE + n0KXfXQb79x / Nyarchy / 8ZgPOqDjQ3XjDxVv6Cjo1bEddEAHdEAnatiDDuiADuiAzqiAVEWqEk1VeFgZD8tzr1al4zfm9ZpI8aR4JSmePR17OhQlRRlVlKADOqADOqAzKsDgZHBGDU5R979H3beqD6VD6VA6lA6lQ + lMJAQFUIhCoTrFuygdZ69mtSO1kdqUpDbOXvVU1HLgOl7xknhJvKRC2wF0QAdkQTYKWdABHdABHdAZFWCgMlAfykCtNmh3uT6lQ + lQOpROXOl47tUMHmevej2keFK8khTPcmChS3 + rDc5dZLP / 79FMbIH / sAVAB3R8SHhnUe8MdEAHdEAHdEYFGJwMzqjBaTzMjIeUDqVD6VA6caXj7NUMHqmN1KYktXH2qqei9nTs6RhjjbHRMRZ0QAd0QAd0RgV4DbyGqNdgH + OOD / lNiNKhdMqbTCqUSYV2gSbogA7oGK / i45WzVzN4nL3q9ZDiSfFKUjx7OvZ0eGe8s6h3BjqgAzqgAzqjArwGXkPUa2B4ZwxvSofSoXQoHUqH0plICAqgEIVCdfTuuVer0pHaSG1KUhtnr3oqak / Hng7vjHcW9c5AB3RAB3RAZ1SAl8HLeCgvo9or2eX6lA6lQ + lQOpQOpTOREBRAIQqF6n2li9Jx9mpWO85e9XpI8aR4JSme5cB1vOIl8ZJ4SYW2A + iADsiCbBSyoAM6oAM6oDMqwEBloD6UgVpt0O5yfUqH0qF0KJ240vHcqxk8UhupTUlq4 + xVT0UtBxa69LtsiO4iy9XzaNbtbQfQAZ3tmxg0jybeZkwGHdABHYZ91LAHHdABHdABnVGBbeQieb + XvPd + 3ff9cvZqVTrOXvWaSPGkeCUpnj0dezoUpT2d + J7O0 / iJZnuzfXS2N + bcd8y5V / 0pHUqH0qF0KB3KayIhKIBCFArVS5iUDqUDaqAWhZrnXq3QkdpIbUpSG2eveipqOXCFDkOdoc5QL5wAQAd0QBZko5AFHdABHdABnVEBBieDM2pwVqc2rn 8nc + + + UDqVD6VA6caXjuVczeJy96vWQ4knxSlI8ezqFLv291szJ C7j1f + owy9nU4AO6PxyTQmajw1N0AEd0GHYRw170AEd0AEd0BkVMJNLVaKpCg8o4wE5e7UqHamN1KYktXH2qqei9nTs6VCUFGVUUYIO6IAO6IDOqACDk8EZNThF9ZmontKhdCgdSofSoXQmEoICKEShUJ3iee7VqnScveo1keJJ8UpSPMuBK3R4SbwkXlKh7QA6oAOyIBuFLOiADuiADuiMCjBQGagPZaBWG7S7XJ / SoXQoHUonrnS + jJ8otZHanJtPP iHkn6wHFjo0ttwPYprTDYmT2My6IAOKIBC1DsDHdABHdABnVEBBieDM2pwGocz4zClQ + + + lQOpROXOl47tUMHqmN1KYktWmtfV7vce3D9Zs9HXs6xlhjbHSMBR3QAR3QAZ1RAV4DryHqNexyjGB3w5vSoXQoHUqH0qF0JhKCAihEoVCtpDz3alU6fmNer8mHS1U8l p438v7356OPR3eGe8s6p2BDuiADuiAzqgAL4OX8VBeRrVXssv1KR1Kh9KhdCgdSmciISiAQhQK1ftKnnu1Kh2pTa9JeYrhLNLHTAktB67Q4SXxknhJhbYD6IAOyIJsFLKgAzqgAzqgMyrAQGWgPpSBWm3Q7nJ9SofSoXQonbjS8dyrGTxSm14PKZ4U7 / zJuFk / WA4sdOl32RDdRZar59Gs29sOoAM62zcxaB5NvM2YDDqgAzoM + 6hhDzqgAzqgAzqjAtvIRfJ + L3nv /歩道橋++ Xs1ap0bubSO1skBTu1l1R0pKL2dOzpUJT2dOJ7Ok / jJ5rtzfbR2d6Yc98x5171p3QoHUqH0qF0KK + JhKAAClEoVC9hUjqUDqiBWhRqnnu1QkfKMFIGz4E6CqEfbtwPlgMtBwoQBAjRAAF0QAd0QAd0RgV4DbyGqNdQbaC6 / vF2PlM6lA6lQ + lQOpTOREJQAIUoFKqXBp29WpWOs1e9JlKbG6c2zuIdBX2xp7NCh5fES + IlFdoOF + j8Na7 / T2vt7 / Vntd9ba3 ++ 8X2v70VRn14H / aAfzpi42g / fASYLwjjeopD0AAAAAElFTkSuQmCC)中央リピート; キャンバス{ 幅:100%。 高さ:100%; 位置:相対; Zインデックス:2。 カーソル:移動。 } IMG { 位置:絶対。 Zインデックス:1。 } } </スタイル>
初期化:
この$ refs.cropImage.init( "画像パス"、{幅80、高さ:120});
回転:
この。$ refs.cropImage.rotate()
画像の等しい割合をエクスポートします。
this.src =はこれを待っています$ refs.cropImage.exportBase();