العنوان الأصلي: github.com/whinc/blog/…
لقد تلقيت مؤخرًا طلبًا لنشر التعليقات: يقوم المستخدمون بإدخال التعليقات ويمكنهم التقاط صور أو تحديد صور من الألبوم لتحميلها، مما يعني دعم التعليقات النصية والصورية. يجب تنفيذه على كل من برامج H5 والبرامج الصغيرة في نفس الوقت، ويتطلب هذا المتطلب العديد من الأماكن لمعالجة الصور. تقدم هذه المقالة ملخصًا لممارسة معالجة الصور في نهاية H5. يعتمد رمز المشروع على إطار عمل Vue لتجنب التأثر بإطار العمل، لقد قمت بتغيير جميع التعليمات البرمجية إلى تنفيذ واجهة برمجة التطبيقات الأصلية للشرح ، الاقتصاص، التقدم في التحميل، وما إلى ذلك) في كود المشروع هنا، احذفه وقدم فقط الأفكار والرموز الأساسية المتعلقة بمعالجة الصور. تنفيذ البرنامج المصغر مشابه لـ H5 ولن يتكرر كود تنفيذ البرنامج المصغر مرفق في نهاية المقال.
تصويراستخدم علامة <input>، واضبط النوع على ملف لتحديد الملف، واضبط القبول على الصورة/* لتحديد نوع الملف والكاميرا، واضبط عدة لدعم التحديدات المتعددة. استمع إلى حدث التغيير للحصول على قائمة الملفات المحددة، كل ملف هو نوع Blob.
<نوع الإدخال=قبول الملف=صورة/* متعدد /> <img class=preivew /> <script type=text/javascript> function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files ) files.forEach(file => console.log('اسم الملف:', file.name)) } document.querySelector('input').addEventListener('change', onFileChange) </script>معاينة الصورة
يمكن لطريقة URL.createObjectURL إنشاء مسار URL محلي يشير إلى كائن المورد المحلي. يتم استخدام هذه الواجهة أدناه لإنشاء عنوان الصورة المحددة وعرضها.
وظيفة onFileChange (الحدث) { ملفات const = Array.prototype.slice.call(event.target.files) ملف const = files[0] document.querySelector('img').src = window.URL.createObjectURL(file) }تدوير الصورة
قد يتم تدوير الصور الملتقطة بالكاميرا بسبب الاتجاه الذي تم حمل الكاميرا فيه عند التصوير، وتحتاج إلى تصحيح. يتطلب تصحيح التدوير معرفة معلومات دوران الصورة، وهنا نستخدم مكتبة تسمى exif-js، والتي يمكنها قراءة بيانات EXIF الخاصة بالصورة، بما في ذلك اتجاه الكاميرا عند التصوير، وبناءً على هذا الاتجاه، يتم التدوير يمكن حساب معلومات الصورة.
فيما يلي بت علم دوران EXIF هناك 8 أنواع في المجموع، ولكن عند التصوير من خلال الكاميرا، يمكن إنشاء 1 و3 و6 و8 فقط، والتي تتوافق على التوالي مع دوران الكاميرا العادي بزاوية 180 درجة في اتجاه عقارب الساعة. ، دوران عكس اتجاه عقارب الساعة 90 درجة، ودوران في اتجاه عقارب الساعة تم التقاط الصورة بزاوية 90 درجة.
لذلك، لتصحيح زاوية دوران الصورة، ما عليك سوى قراءة علامة تدوير EXIF للصورة، وتحديد زاوية التدوير، وتدوير الصورة على اللوحة القماشية، وإعادة تصدير صورة جديدة. فيما يتعلق بعملية تدوير اللوحة القماشية، يمكنك الرجوع إلى المقالة "تدوير صورة اللوحة القماشية وفتح وضعية الوجه". تقوم الوظيفة التالية بتنفيذ تصحيح زاوية الدوران لملف الصورة، وتستقبل ملف صورة، وترجع ملف الصورة الجديد المصحح.
/** * إصلاح مشكلة زاوية دوران الصورة * @param {file} الصورة الأصلية * @return {Promise} حل الوعد إرجاع الصورة الجديدة المصححة */functionfixImageOrientation (file) { return new Promise((resolve,reject) => { // احصل على الصورة const img = new Image(); img.src = window.URL.createObjectURL(file); img.onload = () => { // احصل على البيانات التعريفية للصورة (متغيرات EXIF هي متغيرات عامة تعرضها مكتبة exif-js المقدمة) EXIF.getData(img, function() { // احصل على علامة تدوير الصورة varتوجيه = EXIF.getTag(this, Orientation); // قم بتدوير الصورة على اللوحة القماشية وفقًا لزاوية التدوير if (orientation === 3 || التوجه === 6 || الاتجاه === 8) { const Canvas = document.createElement(canvas); const ctx = Canvas.getContext(2d); Switch (orientation) { الحالة 3: // تدوير 180 درجة Canvas.width = img.width; (180 * Math.PI) / 180)؛ ctx.drawImage(img, -img.width, -img.height, img.width, img.height);break; الحالة 6: // تدوير 90 درجة Canvas.width = img.height; ctx.drawImage(img, 0, -img.height, img.width, img.height الحالة 8: // Rotate -90° Canvas.width = img.height; Canvas.height = img.width; .width, img.height);break; } // إرجاع الصورة الجديدة Canvas.toBlob(file => Resolve(file), 'image/jpeg', 0.92) } else { return Resolve(file);ضغط الصورة
في الوقت الحاضر، أصبح تأثير كاميرا الهواتف المحمولة أفضل وأفضل، ومع ذلك زاد حجم الصور، والتي يمكن أن تصل بسهولة إلى بضعة ميغابايت أو حتى أكثر من عشرة ميغابايت، كما أن تحميل الصورة الأصلية مباشرة بطيء وسهل التحميل ، والخلفية لها أيضًا قيود على حجم نص الطلب، وسيكون التحميل اللاحق لعرض الصورة أبطأ أيضًا. يمكن حل هذه المشكلات إذا قامت الواجهة الأمامية بضغط الصور ثم تحميلها.
تقوم الوظيفة التالية بتنفيذ ضغط الصور. المبدأ هو رسم الصورة المقاسة على اللوحة القماشية، ثم تصدير الصورة المضغوطة من اللوحة القماشية في النهاية. هناك طريقتان للتحكم في ضغط الصورة: إحداهما هي التحكم في نسبة تكبير الصورة، والأخرى هي التحكم في جودة الصورة المصدرة.
/** * صورة مضغوطة * @param {file} صورة الإدخال * @returns {Promise} تم حل الوعد إرجاع الصورة المضغوطة الجديدة */function CompressImage(file) { return new Promise((resolve,reject) => { // Get الصورة (تحميل الصورة هو الحصول على عرض الصورة وارتفاعها) const img = new Image(); return(error); img.onload = () => { // عرض اللوحة القماشية وارتفاعها const CanvasWidth = document.documentElement.clientWidth * window.devicePixelRatio; const CanvasHeight = document.documentElement.clientHeight * window.devicePixelRatio; العامل // هنا أتخذ عوامل القياس الأفقية والرأسية الأكبر كعامل القياس، وذلك للتأكد من أن محتوى الصورة بأكمله مرئي constscaleX = CanvasWidth / img.width; constscaleY = CanvasHeight / img.height; constscale = Math.min(scaleX,scaleY); ('canvas')؛ const ctx = Canvas.getContext(2d); img.width *scale; const imageHeight = img.height *scale; const dx = (canvasWidth - imageWidth) / 2; const dy = (canvasHeight - imageHeight) / 2; ); // تصدير صورة جديدة // حدد نوع MIME للصورة كـ "image/jpeg"، وقم بتمرير الجودة التحكم في جودة الصور المصدرة وتنفيذ جودة ضغط الصور = 0.92 Canvas.toBlob(file => Resolve(tempFile), image/jpeg,quality });};تحميل الصورة
قم بإنشاء بيانات النموذج من خلال FormData وبدء طلب POST من نوع ajax. تقوم الوظيفة التالية بتنفيذ تحميل الملفات.
ملاحظة: عند إرسال بيانات FormData، سيقوم المتصفح تلقائيًا بتعيين نوع المحتوى على قيمة مناسبة ليست هناك حاجة لتعيين نوع المحتوى، وإلا سيتم الإبلاغ عن خطأ لأن حدود محدد نص طلب HTTP يتم إنشاؤها بواسطة المتصفح. ولا يمكن ضبطه يدويًا.
/** * تحميل الملف* @param {File} ملف الملف المراد تحميله* @returns {Promise} يُرجع الوعد الذي تم حله إذا كان التحميل ناجحًا، وإلا فإنه يُرجع الوعد المرفوض */function uploadFile (file) { return new Promise((resolve ، رفض) = > { // تحضير بيانات النموذج const formData = new FormData() formData.append('file', file) // إرسال الطلب const xhr = new XMLHttpRequest() xhr.open('POST', uploadUrl) xhr.onreadystatechange = function () { if (this.readyState === XMLHttpRequest.DONE && this.status === 200) { Resolve(JSON.parse(this.responseText)) } else { رفض (this.responseText) } } xhr.send(formData) })}ملخص
مع الوظائف المساعدة المذكورة أعلاه، تكون المعالجة أبسط بكثير، ويكون رمز الاتصال النهائي كما يلي:
function onFileChange (event) { const files = Array.prototype.slice.call(event.target.files) ملف const = files[0] // إصلاح دوران الصورةfixImageOrientation(file).then(file2 => { // إنشاء معاينة image document.querySelector('img').src = window.URL.createObjectURL(file2) // إرجاع الضغط CompressImage(file2) }).then(file3 => { // تحديث صورة المعاينة document.querySelector('img').src = window.URL.createObjectURL(file3) // تحميل return uploadFile(file3) }).then(data => { console.log('تم التحميل بنجاح') }).catch(error => { console.error('فشل التحميل') })}
يوفر H5 واجهة لمعالجة الملفات بمساعدة اللوحة القماشية، ويمكن تنفيذ معالجة الصور المعقدة في المتصفح مرجع جزئي عند مواجهة احتياجات مماثلة في المستقبل.
مرفق مرفق مرجع صغير لتنفيذ البرنامج
// التقاط صور wx.chooseImage({ sourceType: [camera], Success: ({ tempFiles }) => { const file = tempFiles[0] // معالجة الصور }});/** * ضغط الصور* @param { Object } params * filePath: String مسار صورة الإدخال * النجاح: يتم استدعاء الوظيفة مرة أخرى عندما يكون الضغط ناجحًا ويعيد مسار الصورة المضغوطة الجديد * فشل: الوظيفة رد الاتصال عند فشل الضغط */compressImage({ filePath, Success, Fail }) { // احصل على عرض الصورة وارتفاعها wx.getImageInfo({ src: filePath, Success: ({ width, height }) => { const systemInfo = wx .getSystemInfoSync(); const CanvasWidth = systemInfo.screenWidth; قم بتحديث حجم اللوحة القماشية this.setData({ CanvasWidth, CanvasHeight }) // احسب نسبة القياس constscaleX = CanvasWidth / width; *scale ; const imageHeight = height *scale; dx = (canvasWidth - imageWidth) / 2; Let dy = (canvasHeight - imageHeight) / 2; ctx.drawImage(filePath, dx, dy, imageWidth, imageHeight); الصور المضغوطة إلى ملفات مؤقتة wx.canvasToTempFilePath({ CanvasId: Hidden-canvas, width: CanvasWidth، الارتفاع: CanvasHeight، destWidth: CanvasWidth، destHeight: CanvasHeight، fileType: jpg، الجودة: 0.92، النجاح: ({ tempFilePath }) => { // إخفاء اللوحة القماشية this.setData({ CanvasWidth: 0, CanvasHeight: 0 } ) // اكتمل الضغط بنجاح({ tempFilePath } }, Fail: error => { // إخفاء قماش this.setData({ CanvasWidth: 0, CanvasHeight: 0 }) Fail(error } }); تحميل الملف*/uploadFile({ uploadUrl, filePath, onData, onError }) { wx.uploadFile({ url: uploadUrl filePath: filePath, name: الملف، الرأس: {ملف تعريف الارتباط: ملف تعريف الارتباط}، النجاح: الدقة => { if (res.statusCode === 200) { onData(res.data) } else { onError(res } }، فشل: خطأ => { onError(error);}تلخيص
ما ورد أعلاه هو برنامج HTML5 وبرنامج صغير قدمه المحرر لتحقيق وظائف تدوير الصور وضغطها وتحميلها، وآمل أن يكون مفيدًا لك. إذا كانت لديك أي أسئلة، فيرجى ترك رسالة لي وسيقوم المحرر بالرد عليها لك في الوقت المناسب. أود أيضًا أن أشكر الجميع على دعمكم لموقع VeVb للفنون القتالية!