LemonJournal
1.0.0
이 프로젝트는 Wafer2 프레임워크를 기반으로 개발되었습니다. 백엔드는 Tencent Cloud에서 제공하는 Node.js SDK를 사용하여 객체 스토리지 API에 액세스합니다. 프론트엔드 핵심 코드는 이동, 회전, 크기 조정을 지원하는 이미지 편집기 기능을 구현합니다. , 이미지 및 텍스트의 미리보기 생성 및 편집 상태가 저장되고 애니메이션 부분은 CSS 애니메이션을 사용하여 구현됩니다.
애플릿의 모달 입력 상자는 별도로 패키지된 InputBox 구성 요소입니다.
AppId 등의 민감한 정보가 코드에서 제거되었습니다. 자체 AppId 및 AppSecret을 추가하여 백그라운드 환경을 구성하고 로그인 테스트를 구현할 수 있습니다. 자세한 추가 방법은 아래의 "사용법"을 참조하여 로컬에서 실행하면 됩니다. app.json
파일의 page
필드를 순서대로 봅니다.
git clone https://github.com/yeliudev/LemonJournal.git
LemonJournal
폴더를 엽니다. project.config.json
의 appid
필드에 AppId를 입력하세요./client/utils/util.js
의 해당 위치에 AppId 및 AppSecret을 입력합니다.<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 개체에 저장됩니다. 모두 고유 ID 및 관련 정보를 포함합니다. 저장 시 객체는 클라이언트에 의해 생성되어 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
}
]
}
MIT 라이센스
저작권 (c) 2021 예 리우