Cropper.js を使用して vue をカプセル化し、オンライン画像トリミング コンポーネント機能を実装する方法 (詳細なチュートリアル)
この記事では、vue をカプセル化した Cropper.js に基づいたオンライン画像トリミング コンポーネント機能を主に紹介します。これは非常に優れており、必要な友人は参考にしてください。
レンダリングは次のとおりです。
: デモ
cropper.jsをダウンロード
github:cropper.js
公式サイト(デモ)
cropper.jsのインストール
- npmまたはbowerのインストール
npm install cropper # or bower install cropperクローンダウンロード: ダウンロードアドレスgit clone https://github.com/fengyuanchen/cropper.git
Cropper.jsを参照
主にCropper.jsとCropper.CSSの2つのファイルを参照します<script src="/path/to/jquery.js"></script><!-- jQuery is required --> <link href="/path/to/cropper.css" rel="external nofollow" rel="stylesheet"> <script src="/path/to/cropper.js"></script>
注: jqueryファイルを導入する必要があります使用する前に Cropper.js プラグイン
使いやすい
スクリーンショットに使用する p コンテナを構築します<!-- Wrap the image or canvas element with a block element (container) --> <p>  </p>コンテナのスタイルを追加し、画像をコンテナ全体に埋め込みます (非常に重要)
/* Limit image width to avoid overflow the container */ img { max-width: 100%; /* This rule is very important, please do not ignore this! */ }cropper.jsメソッドを呼び出してスクリーンショットを初期化 Control
$('#image').cropper({ aspectRatio: 16 / 9, crop: function(e) { // Output the result data for cropping image. console.log(e.x); console.log(e.y); console.log(e.width); console.log(e.height); console.log(e.rotate); console.log(e.scaleX); console.log(e.scaleY); } });その他の詳細なAPIについては、github:cropper.jsを参照してください
vueコンポーネントにカプセル化
vueコンポーネントにパッケージ化する際に解決すべき問題
- cropper.js関連
- vue 関連
入力ボックスをクリックして画像を選択し、選択した画像の形式とサイズを制限する
非表示の入力を構築するタグを付けて、この入力をクリックすることをシミュレートして、画像を選択する機能を実現します<!-- input框 --> <input id="myCropper-input" type="file" :accept="imgCropperData.accept" ref="inputer" @change="handleFile"> //模拟点击 document.getElementById('myCropper-input').click();モニターを入力にバインドします。コンテンツを変更する方法は、アップロードされたファイルを取得し、形式とサイズを確認することです
// imgCropperData: { // accept: 'image/gif, image/jpeg, image/png, image/bmp', // } handleFile (e) { let _this = this; let inputDOM = this.$refs.inputer; // 通过DOM取文件数据 _this.file = inputDOM.files[0]; // 判断文件格式 if (_this.imgCropperData.accept.indexOf(_this.file.type) == -1) { _this.$Modal.error({ title: '格式错误', content: '您选择的图片格式不正确!' }); return; } // 判断文件大小限制 if (_this.file.size > 5242880) { _this.$Modal.error({ title: '超出限制', content: '您选择的图片过大,请选择5MB以内的图片!' }); return; } var reader = new FileReader(); // 将图片将转成 base64 格式 reader.readAsDataURL(_this.file); reader.onload = function () { _this.imgCropperData.imgSrc = this.result; _this.initCropper(); } }
トリミング用の画像
初めて画像を選択するときは、必ず画像を再選択する必要があるという問題に直面するでしょう。画像を選択した後、トリミングボックス内の画像を置き換える方法に直面するでしょう。上記の手順では、FileRender() メソッドを通じて画像の主な情報を取得できます。この問題を解決するには、cropper.js を表示する必要があります。公式のメソッドでは次のことがわかりました。動的にクロッピングコンテナを追加して動作させる方法です。ここでは公式の実装を模倣します。// 初始化剪切 initCropper () { let _this = this; // 初始化裁剪区域 _this.imgObj = $(''); let $avatarPreview = $('.avatar-preview'); $('#myCropper-workspace').empty().html(_this.imgObj); _this.imgObj.cropper({ aspectRatio: _this.proportionX / _this.proportionY, preview: $avatarPreview, crop: function(e) { } }); }
トリミングを確認し、base64形式で画像情報を取得
let $imgData = _this.imgObj.cropper('getCroppedCanvas') imgBase64Data = $imgData.toDataURL('image/png');
アップロード用データを構築
// 构造上传图片的数据 let formData = new FormData(); // 截取字符串 let photoType = imgBase64Data.substring(imgBase64Data.indexOf(",") + 1); //进制转换 const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => { const byteCharacters = atob(b64Data); const byteArrays = []; for(let offset = 0; offset < byteCharacters.length; offset += sliceSize) { const slice = byteCharacters.slice(offset, offset + sliceSize); const byteNumbers = new Array(slice.length); for(let i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } const blob = new Blob(byteArrays, { type: contentType }); return blob; } const contentType = 'image/jepg'; const b64Data2 = photoType; const blob = b64toBlob(b64Data2, contentType); formData.append("file", blob, "client-camera-photo.png") formData.append("type", _this.imgType)
非親子コンポーネント間の通信の問題
以前のプロジェクトでは、親子が一般的に使用されていましたコンポーネント間の通信パラメータには通常2つのメソッドが使用されます
ルーターにパラメータを配置し、route.params.xxxまたはroute.query.xxxを呼び出して取得しますpropsを介して通信しますここではeventBusを使用してコンポーネント間の通信を行います
手順
1. Aコンポーネントにパラメータを渡すためにBコンポーネントのバスコンポーネントを宣言します//bus.js import Vue from 'vue'; export default new Vue();2. Aコンポーネントでバスコンポーネントを参照し、パラメータの変更をリアルタイムでリッスンします
// A.vue import Bus from '../../components/bus/bus.js' export default { components: { Bus }, data () {}, created: function () { Bus.$on('getTarget', imgToken => { var _this = this; console.log(imgToken); ... }); } }3.バス コンポーネントは、コンポーネント A にパラメーターを渡すためにコンポーネント B でも参照されます
// B.vue // 传参 Bus.$emit('getTarget', imgToken);参考:vue-$on
vue-$emit
vue.js road (4) - .0s の vue2 EventBus は兄弟コンポーネント通信を実装します
vue画像の選択とスクリーンショットのプラグインの完全なコード
<template> <p class="myCropper-container"> <p id="myCropper-workspace"> <p class="myCropper-words" v-show="!imgCropperData.imgSrc">请点击按钮选择图片进行裁剪</p> </p> <p class="myCropper-preview" :class="isShort ? 'myCropper-preview-short' : 'myCropper-preview-long'"> <p class="myCropper-preview-1 avatar-preview">  </p> <p class="myCropper-preview-2 avatar-preview">  </p> <p class="myCropper-preview-3 avatar-preview">  </p> <input id="myCropper-input" type="file" :accept="imgCropperData.accept" ref="inputer" @change="handleFile"> <Button type="ghost" class="myCropper-btn" @click="btnClick">选择图片</Button> <Button type="primary" class="myCropper-btn" :loading="cropperLoading" @click="crop_ok">确认</Button> </p> </p> </template> <script> var ezjsUtil = Vue.ezjsUtil; import Bus from './bus/bus.js' export default { components: { Bus }, props: { imgType: { type: String }, proportionX: { type: Number }, proportionY: { type: Number } }, data () { return { imgCropperData: { accept: 'image/gif, image/jpeg, image/png, image/bmp', maxSize: 5242880, file: null, //上传的文件 imgSrc: '', //读取的img文件base64数据流 imgUploadSrc: '', //裁剪之后的img文件base64数据流 }, imgObj: null, hasSelectImg: false, cropperLoading: false, isShort: false, } }, created: function () { let _this = this; }, mounted: function () { let _this = this; // 初始化预览区域 let maxWidthNum = Math.floor(300 / _this.proportionX); let previewWidth = maxWidthNum * _this.proportionX; let previewHeight = maxWidthNum * _this.proportionY; if (previewWidth / previewHeight <= 1.7) { previewWidth = previewWidth / 2; previewHeight = previewHeight / 2; _this.isShort = true; } // 设置最大预览容器的宽高 $('.myCropper-preview-1').css('width', previewWidth + 'px'); $('.myCropper-preview-1').css('height', previewHeight + 'px'); // 设置中等预览容器的宽高 $('.myCropper-container .myCropper-preview .myCropper-preview-2').css('width',( previewWidth / 2) + 'px'); $('.myCropper-container .myCropper-preview .myCropper-preview-2').css('height', (previewHeight / 2) + 'px'); // 设置最小预览容器的宽高 $('.myCropper-container .myCropper-preview .myCropper-preview-3').css('width',( previewWidth / 4) + 'px'); $('.myCropper-container .myCropper-preview .myCropper-preview-3').css('height', (previewHeight / 4) + 'px'); }, methods: { // 点击选择图片 btnClick () { let _this = this; // 模拟input点击选择文件 document.getElementById('myCropper-input').click(); }, // 选择之后的回调 handleFile (e) { let _this = this; let inputDOM = this.$refs.inputer; // 通过DOM取文件数据 _this.file = inputDOM.files[0]; // 判断文件格式 if (_this.imgCropperData.accept.indexOf(_this.file.type) == -1) { _this.$Modal.error({ title: '格式错误', content: '您选择的图片格式不正确!' }); return; } // 判断文件大小限制 if (_this.file.size > 5242880) { _this.$Modal.error({ title: '超出限制', content: '您选择的图片过大,请选择5MB以内的图片!' }); return; } var reader = new FileReader(); // 将图片将转成 base64 格式 reader.readAsDataURL(_this.file); reader.onload = function () { _this.imgCropperData.imgSrc = this.result; _this.initCropper(); } }, // 初始化剪切 initCropper () { let _this = this; // 初始化裁剪区域 _this.imgObj = $(''); let $avatarPreview = $('.avatar-preview'); $('#myCropper-workspace').empty().html(_this.imgObj); _this.imgObj.cropper({ aspectRatio: _this.proportionX / _this.proportionY, preview: $avatarPreview, crop: function(e) { } }); _this.hasSelectImg = true; }, // 确认 crop_ok () { let _this = this, imgToken = null, imgBase64Data = null; // 判断是否选择图片 if (_this.hasSelectImg == false) { _this.$Modal.error({ title: '裁剪失败', content: '请选择图片,然后进行裁剪操作!' }); return false; } // 确认按钮不可用 _this.cropperLoading = true; let $imgData = _this.imgObj.cropper('getCroppedCanvas') imgBase64Data = $imgData.toDataURL('image/png'); // 构造上传图片的数据 let formData = new FormData(); // 截取字符串 let photoType = imgBase64Data.substring(imgBase64Data.indexOf(",") + 1); //进制转换 const b64toBlob = (b64Data, contentType = '', sliceSize = 512) => { const byteCharacters = atob(b64Data); const byteArrays = []; for(let offset = 0; offset < byteCharacters.length; offset += sliceSize) { const slice = byteCharacters.slice(offset, offset + sliceSize); const byteNumbers = new Array(slice.length); for(let i = 0; i < slice.length; i++) { byteNumbers[i] = slice.charCodeAt(i); } const byteArray = new Uint8Array(byteNumbers); byteArrays.push(byteArray); } const blob = new Blob(byteArrays, { type: contentType }); return blob; } const contentType = 'image/jepg'; const b64Data2 = photoType; const blob = b64toBlob(b64Data2, contentType); formData.append("file", blob, "client-camera-photo.png") formData.append("type", _this.imgType) // ajax上传 $.ajax({ url: _this.$nfs.uploadUrl, method: 'POST', data: formData, // 默认为true,设为false后直到ajax请求结束(调完回掉函数)后才会执行$.ajax(...)后面的代码 async: false, // 下面三个,因为直接使用FormData作为数据,contentType会自动设置,也不需要jquery做进一步的数据处理(序列化)。 cache: false, contentType: false, processData: false, type: _this.imgType, success: function(res) { let imgToken = res.data.token; _this.cropperLoading = false; // 传参 Bus.$emit('getTarget', imgToken); }, error: function(error) { _this.cropperLoading = false; _this.$Modal.error({ title: '系统错误', content: '请重新裁剪图片进行上传!' }); } }); }, } } </script> <style lang="less" scoped> .myCropper-container { height: 400px; } .myCropper-container #myCropper-input { width: 0px; height: 0px; } .myCropper-container #myCropper-workspace { width: 500px; height: 400px; border: 1px solid #dddee1; float: left; } // 裁剪图片未选择图片的提示文字 .myCropper-container #myCropper-workspace .myCropper-words{ text-align: center; font-size: 18px; padding-top: 180px; } // 裁剪图片的预览区域 .myCropper-container .myCropper-preview-long { width: 300px; } .myCropper-container .myCropper-preview-short { width: 200px; } .myCropper-container .myCropper-preview { float: left; height: 400px; margin-left: 10px; } .myCropper-container .myCropper-preview .myCropper-preview-1 { border-radius: 5px; overflow: hidden; border: 1px solid #dddee1; box-shadow: 3px 3px 3px #dddee1; img { width: 100%; height: 100%; } } .myCropper-container .myCropper-preview .myCropper-preview-2 { margin-top: 20px; border-radius: 5px; overflow: hidden; border: 1px solid #dddee1; box-shadow: 3px 3px 3px #dddee1; img { width: 100%; height: 100%; } } .myCropper-container .myCropper-preview .myCropper-preview-3 { margin-top: 20px; border-radius: 5px; overflow: hidden; border: 1px solid #dddee1; box-shadow: 3px 3px 3px #dddee1; img { width: 100%; height: 100%; } } // 按钮 .myCropper-btn { float: left; margin-top: 20px; margin-right: 10px; } </style>BY-LucaLJXgithub: lucaljx上記は、私が皆さんのためにまとめたものです。将来的に皆さんのお役に立てれば幸いです。 関連記事:
ドメイン名の購入からpm2を使ったnode.jsプロジェクトのデプロイまでの全過程を詳しく解説
以上がCropper.js を使用して vue をカプセル化し、オンライン画像トリミング コンポーネント機能を実装する方法 (詳細なチュートリアル)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

node.jsは、主にストリームのおかげで、効率的なI/Oで優れています。 ストリームはデータを段階的に処理し、メモリの過負荷を回避します。大きなファイル、ネットワークタスク、リアルタイムアプリケーションの場合。ストリームとTypeScriptのタイプの安全性を組み合わせることで、パワーが作成されます

PythonとJavaScriptのパフォーマンスと効率の違いは、主に以下に反映されています。1)解釈された言語として、Pythonはゆっくりと実行されますが、開発効率が高く、迅速なプロトタイプ開発に適しています。 2)JavaScriptはブラウザ内の単一のスレッドに限定されていますが、マルチスレッドおよび非同期I/Oを使用してnode.jsのパフォーマンスを改善でき、両方とも実際のプロジェクトで利点があります。

JavaScriptは1995年に発信され、Brandon Ikeによって作成され、言語をCに実現しました。 2。JavaScriptのメモリ管理とパフォーマンスの最適化は、C言語に依存しています。 3. C言語のクロスプラットフォーム機能は、さまざまなオペレーティングシステムでJavaScriptを効率的に実行するのに役立ちます。

JavaScriptはブラウザとnode.js環境で実行され、JavaScriptエンジンに依存してコードを解析および実行します。 1)解析段階で抽象的構文ツリー(AST)を生成します。 2)ASTをコンパイル段階のバイトコードまたはマシンコードに変換します。 3)実行段階でコンパイルされたコードを実行します。

PythonとJavaScriptの将来の傾向には、1。Pythonが科学コンピューティングの分野での位置を統合し、AI、2。JavaScriptはWebテクノロジーの開発を促進します。どちらもそれぞれのフィールドでアプリケーションシナリオを拡大し続け、パフォーマンスをより多くのブレークスルーを行います。

開発環境におけるPythonとJavaScriptの両方の選択が重要です。 1)Pythonの開発環境には、Pycharm、Jupyternotebook、Anacondaが含まれます。これらは、データサイエンスと迅速なプロトタイピングに適しています。 2)JavaScriptの開発環境には、フロントエンドおよびバックエンド開発に適したnode.js、vscode、およびwebpackが含まれます。プロジェクトのニーズに応じて適切なツールを選択すると、開発効率とプロジェクトの成功率が向上する可能性があります。

はい、JavaScriptのエンジンコアはCで記述されています。1)C言語は、JavaScriptエンジンの開発に適した効率的なパフォーマンスと基礎となる制御を提供します。 2)V8エンジンを例にとると、そのコアはCで記述され、Cの効率とオブジェクト指向の特性を組み合わせて書かれています。3)JavaScriptエンジンの作業原理には、解析、コンパイル、実行が含まれ、C言語はこれらのプロセスで重要な役割を果たします。

JavaScriptは、Webページのインタラクティブ性とダイナミズムを向上させるため、現代のWebサイトの中心にあります。 1)ページを更新せずにコンテンツを変更できます。2)Domapiを介してWebページを操作する、3)アニメーションやドラッグアンドドロップなどの複雑なインタラクティブ効果、4)ユーザーエクスペリエンスを改善するためのパフォーマンスとベストプラクティスを最適化します。


ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

Video Face Swap
完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

人気の記事

ホットツール

SAP NetWeaver Server Adapter for Eclipse
Eclipse を SAP NetWeaver アプリケーション サーバーと統合します。

MinGW - Minimalist GNU for Windows
このプロジェクトは osdn.net/projects/mingw に移行中です。引き続きそこでフォローしていただけます。 MinGW: GNU Compiler Collection (GCC) のネイティブ Windows ポートであり、ネイティブ Windows アプリケーションを構築するための自由に配布可能なインポート ライブラリとヘッダー ファイルであり、C99 機能をサポートする MSVC ランタイムの拡張機能が含まれています。すべての MinGW ソフトウェアは 64 ビット Windows プラットフォームで実行できます。

VSCode Windows 64 ビットのダウンロード
Microsoft によって発売された無料で強力な IDE エディター

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

SublimeText3 英語版
推奨: Win バージョン、コードプロンプトをサポート!

ホットトピック









