تم تطوير المشروع بناءً على إطار عمل Wafer2. تستخدم الواجهة الخلفية Node.js SDK المقدمة من Tencent Cloud للوصول إلى واجهة برمجة تطبيقات تخزين الكائنات. ينفذ الكود الأساسي للواجهة الأمامية وظيفة محرر الصور ويدعم الحركة والتدوير والقياس ومعاينة إنشاء الصور والنصوص وتحريرها، ويتم حفظ الحالة وتنفيذ جزء الرسوم المتحركة باستخدام الرسوم المتحركة CSS.
مربع الإدخال المشروط في التطبيق الصغير عبارة عن مكون InputBox معبأ بشكل منفصل.
تمت إزالة المعلومات الحساسة مثل AppId من التعليمات البرمجية. يمكنك إضافة AppId وAppSecret الخاصين بك لتكوين بيئة الخلفية وتنفيذ اختبار تسجيل الدخول للحصول على طرق إضافة مفصلة، راجع "الاستخدام" أدناه حقل page
في ملف app.json
عرض صفحات مختلفة بالترتيب
git clone https://github.com/yeliudev/LemonJournal.git
LemonJournal
في أدوات مطور WeChat appid
الخاص بـ project.config.json
/client/utils/util.js
<image>
(المقابلة للصورة) والعلامة <text>
(المقابلة للنص) في نفس المكون المخصص <sticker>
، وإجراء عرض شرطي بناءً على ما إذا كان متغير text
المكشوف فارغًا ، ثم اربطها بثلاثة أحداث onTouchStart()
و onTouchEnd()
و onTouchMove()
لتشغيل موضع المكون بأكمله وزاويته وحجمه ومستواه بالإضافة إلى سلوك زري "التدوير" و"الإزالة". onTouchStart: function ( e ) {
// 若未选中则直接返回
if ( ! this . data . selected ) {
return
}
switch ( e . target . id ) {
case 'sticker' : {
this . touch_target = e . target . id
this . start_x = e . touches [ 0 ] . clientX * 2
this . start_y = e . touches [ 0 ] . clientY * 2
break
}
case 'handle' : {
// 隐藏移除按钮
this . setData ( {
hideRemove : true
} )
this . touch_target = e . target . id
this . start_x = e . touches [ 0 ] . clientX * 2
this . start_y = e . touches [ 0 ] . clientY * 2
this . sticker_center_x = this . data . stickerCenterX ;
this . sticker_center_y = this . data . stickerCenterY ;
this . remove_center_x = this . data . removeCenterX ;
this . remove_center_y = this . data . removeCenterY ;
this . handle_center_x = this . data . handleCenterX ;
this . handle_center_y = this . data . handleCenterY ;
this . scale = this . data . scale ;
this . rotate = this . data . rotate ;
break
}
}
} ,
onTouchEnd : function ( e ) {
this . active ( )
this . touch_target = ''
// 显示移除按钮
this . setData ( {
removeCenterX : 2 * this . data . stickerCenterX - this . data . handleCenterX ,
removeCenterY : 2 * this . data . stickerCenterY - this . data . handleCenterY ,
hideRemove : false
} )
// 若点击移除按钮则触发移除事件,否则触发刷新数据事件
if ( e . target . id === 'remove' ) {
this . triggerEvent ( 'removeSticker' , this . data . sticker_id )
} else {
this . triggerEvent ( 'refreshData' , this . data )
}
} ,
onTouchMove : function ( e ) {
// 若无选中目标则返回
if ( ! this . touch_target ) {
return
}
var current_x = e . touches [ 0 ] . clientX * 2
var current_y = e . touches [ 0 ] . clientY * 2
var diff_x = current_x - this . start_x
var diff_y = current_y - this . start_y
switch ( e . target . id ) {
case 'sticker' : {
// 拖动组件则所有控件同时移动
this . setData ( {
stickerCenterX : this . data . stickerCenterX + diff_x ,
stickerCenterY : this . data . stickerCenterY + diff_y ,
removeCenterX : this . data . removeCenterX + diff_x ,
removeCenterY : this . data . removeCenterY + diff_y ,
handleCenterX : this . data . handleCenterX + diff_x ,
handleCenterY : this . data . handleCenterY + diff_y
} )
break
}
case 'handle' : {
// 拖动操作按钮则原地旋转缩放
this . setData ( {
handleCenterX : this . data . handleCenterX + diff_x ,
handleCenterY : this . data . handleCenterY + diff_y
} )
var diff_x_before = this . handle_center_x - this . sticker_center_x ;
var diff_y_before = this . handle_center_y - this . sticker_center_y ;
var diff_x_after = this . data . handleCenterX - this . sticker_center_x ;
var diff_y_after = this . data . handleCenterY - this . sticker_center_y ;
var distance_before = Math . sqrt ( diff_x_before * diff_x_before + diff_y_before * diff_y_before ) ;
var distance_after = Math . sqrt ( diff_x_after * diff_x_after + diff_y_after * diff_y_after ) ;
var angle_before = Math . atan2 ( diff_y_before , diff_x_before ) / Math . PI * 180 ;
var angle_after = Math . atan2 ( diff_y_after , diff_x_after ) / Math . PI * 180 ;
this . setData ( {
scale : distance_after / distance_before * this . scale ,
rotate : angle_after - angle_before + this . rotate
} )
break
}
}
this . start_x = current_x ;
this . start_y = current_y ;
}
sticker
(الملصق الذي يأتي مع البرنامج)، image
(الصورة التي تم تحميلها بواسطة المستخدم)، text
(نص مخصص)، ويتم حفظها جميعًا في كائن json بالتنسيق التالي لكل مكون مستقل تحتوي جميعها على معرف فريد ومعلومات ذات صلة. عند الحفظ، يتم إنشاء الكائن بواسطة العميل وترميزه في سلسلة json وتخزينه في قاعدة البيانات. عند استعادة حالة التحرير، يتم الحصول على الكائن عن طريق تحليل سلسلة json ثم عرضه من خلال صفحة التحرير {
"backgroundId" : "5" , 背景图id
"assemblies" : [
{
"id" : "jhjg" , 组件id
"component_type" : "image" , 组件类型(自定义图片)
"image_url" : "https://example.com/jhjg.png" , 图片地址
"stickerCenterX" : 269 , 中心横坐标
"stickerCenterY" : 664 , 中心纵坐标
"scale" : 1.7123667831396403 , 缩放比例
"rotate" : - 3.0127875041833434 , 旋转角度
"wh_scale" : 1 , 图片宽高比
"z_index" : 19 组件层级
} ,
{
"id" : "gs47" ,
"component_type" : "text" , 组件类型(文字)
"text" : "test" , 文字内容
"stickerCenterX" : 479 ,
"stickerCenterY" : 546 ,
"scale" : 1.808535318980528 ,
"rotate" : 29.11614626607893 ,
"z_index" : 10
} ,
{
"id" : "chjn" ,
"component_type" : "sticker" , 组件类型(贴纸)
"sticker_type" : "food" , 贴纸类型
"sticker_id" : "1" , 贴纸id
"image_url" : "https://example.com/weapp/stickers/food/1.png" ,
"stickerCenterX" : 277 ,
"stickerCenterY" : 260 ,
"scale" : 1.3984276885130673 ,
"rotate" : - 16.620756913892055 ,
"z_index" : 5
}
]
}
رخصة معهد ماساتشوستس للتكنولوجيا
حقوق الطبع والنشر (ج) 2021 يي ليو