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 サイトの他の関連記事を参照してください。

はじめに私はあなたがそれを奇妙に思うかもしれないことを知っています、JavaScript、C、およびブラウザは正確に何をしなければなりませんか?彼らは無関係であるように見えますが、実際、彼らは現代のウェブ開発において非常に重要な役割を果たしています。今日は、これら3つの間の密接なつながりについて説明します。この記事を通して、JavaScriptがブラウザでどのように実行されるか、ブラウザエンジンでのCの役割、およびそれらが協力してWebページのレンダリングと相互作用を駆動する方法を学びます。私たちは皆、JavaScriptとブラウザの関係を知っています。 JavaScriptは、フロントエンド開発のコア言語です。ブラウザで直接実行され、Webページが鮮明で興味深いものになります。なぜJavascrを疑問に思ったことがありますか

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言語はこれらのプロセスで重要な役割を果たします。


ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

SublimeText3 中国語版
中国語版、とても使いやすい

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

PhpStorm Mac バージョン
最新(2018.2.1)のプロフェッショナル向けPHP統合開発ツール

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SecLists
SecLists は、セキュリティ テスターの究極の相棒です。これは、セキュリティ評価中に頻繁に使用されるさまざまな種類のリストを 1 か所にまとめたものです。 SecLists は、セキュリティ テスターが必要とする可能性のあるすべてのリストを便利に提供することで、セキュリティ テストをより効率的かつ生産的にするのに役立ちます。リストの種類には、ユーザー名、パスワード、URL、ファジング ペイロード、機密データ パターン、Web シェルなどが含まれます。テスターはこのリポジトリを新しいテスト マシンにプルするだけで、必要なあらゆる種類のリストにアクセスできるようになります。

ホットトピック









