Skip to content

Commit

Permalink
Merge pull request #60 from hi-our/feature/v2.2.6-christmas-20201219
Browse files Browse the repository at this point in the history
Feature/v2.2.6 christmas 20201219
  • Loading branch information
shenghanqin authored Dec 20, 2020
2 parents 3fed077 + e3990d0 commit 3285e1a
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 38 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
### v2.2.6 (2020-10-14)

* 完善本地部署命令和 DEMO 站点快速部署
* 圣诞节物料补充、戴口罩主题上线
* Webp 图片格式的优化,支持 Safari 浏览器

### v2.2.5 (2020-09-30)

* 启动引导图换成国庆节
Expand Down
8 changes: 3 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Hi头像

让头像有趣一点

<!--
## 核心亮点
| 特性 | 介绍 |
Expand All @@ -13,7 +13,7 @@
| 部署文档详细 | 本项目的部署文档非常详细,详情请查看《[DEPLOYMENT](https://github.com/hi-our/hi-face/blob/master/DEPLOYMENT.md)》文档 |
| 数据管理方便 | 使用 CloudBase CMS 管理数据,并贴心地给出初始化数据模型及默认数据 |
| 前端工程化 | 核心配置已抽取,基于 Cloudbase Framework 完成云函数、Web 端 和小程序端部署|
| 技术小册 | 独家拥有技术小册《**[从0到1开发一个智能头像识别小程序](https://www.xiaoxili.com/hi-face/docs/README.html)**》,详细说明 Hi 头像主要实现思路 |
| 技术小册 | 独家拥有技术小册《**[从0到1开发一个智能头像识别小程序](https://www.xiaoxili.com/hi-face/docs/README.html)**》,详细说明 Hi 头像主要实现思路 | -->


## 功能体验
Expand Down Expand Up @@ -65,15 +65,13 @@ CMS 数据体验:https://face-demo.xiaoxili.com/tcb-cms/

20-35喜欢分享的年轻人


### 作品效果图
![](https://image-hosting.xiaoxili.com/img/img/20200921/6562b94a148b112a6c6b092821bee6f3-4768c7.png)
![](https://image-hosting.xiaoxili.com/img/img/20200921/236e9b57e5c2a8ad170c1edada9c2724-149cab.png)

### 产品介绍视频

[#小程序云开发挑战赛# Hi头像小程序介绍视频-完整版](https://v.qq.com/x/page/l3152qjx9e8.html)

[Hi头像小程序介绍视频-完整版](https://v.qq.com/x/page/l3152qjx9e8.html)

## 主创人员

Expand Down
2 changes: 1 addition & 1 deletion cloud/functions/hiface-api/controllers/avatar.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ class AvatarController extends BaseController {
console.log('orderBy :>> ', orderBy);
operation = operation.orderBy(orderBy.field, orderBy.orderType || 'desc')
} else {
operation = operation.orderBy('order', 'asc')
operation = operation.orderBy('updateTime', 'desc')
}
let { data } = await operation.get()

Expand Down
10 changes: 4 additions & 6 deletions project.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"setting": {
"urlCheck": false,
"es6": false,
"enhance": false,
"postcss": false,
"preloadBackgroundData": false,
"minified": false,
Expand All @@ -30,12 +31,14 @@
"disablePlugins": [],
"outputPath": ""
},
"bundle": false,
"useIsolateContext": true,
"useCompilerModule": true,
"userConfirmedUseCompilerModuleSwitch": true,
"userConfirmedBundleSwitch": false,
"packNpmManually": false,
"packNpmRelationList": [],
"remoteDebugLogEnable": false
"minifyWXSS": true
},
"compileType": "miniprogram",
"simulatorType": "wechat",
Expand All @@ -48,26 +51,21 @@
"libVersion": "2.12.2",
"condition": {
"search": {
"current": -1,
"list": []
},
"conversation": {
"current": -1,
"list": []
},
"plugin": {
"current": -1,
"list": []
},
"game": {
"list": []
},
"gamePlugin": {
"current": -1,
"list": []
},
"miniprogram": {
"current": -1,
"list": [
{
"id": 0,
Expand Down
Binary file added taro/src/images/bg-lead-christmas.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
21 changes: 16 additions & 5 deletions taro/src/pages/avatar-edit/avatar-edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import PageLoading from 'components/page-status'
import ShapeEdit from './components/shape-edit'
import TabCategoryList from './components/tab-category-list'
import PosterDialog from './components/poster-dialog'
import { getHatList, getHatShapeList } from 'utils/face-utils'
import { getHatList, getHatShapeList, getMouthList, getMaskShapeList } from 'utils/face-utils'
import { getImg, fsmReadFile, getBase64Main, saveImageToPhotosAlbum, onUploadFile } from 'utils/image-utils'
import { h5PageModalTips, imageThumb } from 'utils/common'
import { DEFAULT_SHARE_COVER } from 'constants/status'
Expand Down Expand Up @@ -170,7 +170,7 @@ class AvatarEdit extends Component {
return
}
// web版用老逻辑
if (shapeOne.position === 2 || isH5Page) {
if ((shapeOne.position == 2 || shapeOne.position == 3) || isH5Page) {
let cloudFunc = isH5Page ? this.cloudAnalyzeFaceH5 : this.cloudAnalyzeFaceWx

const couldRes = await cloudFunc(cutImageSrc)
Expand All @@ -186,8 +186,19 @@ class AvatarEdit extends Component {
})
return
}
const hatList = getHatList(couldRes, shapeOne)
shapeList = getHatShapeList(hatList, shapeOne, SAVE_IMAGE_WIDTH)

if (shapeOne.position == 3) {
// 口罩
const mouthList = getMouthList(couldRes, shapeOne)
console.log('mouthList', mouthList)
shapeList = getMaskShapeList(mouthList, shapeOne, SAVE_IMAGE_WIDTH)
console.log('shapeList', shapeList)
} else {
// 皇冠
const hatList = getHatList(couldRes, shapeOne)
shapeList = getHatShapeList(hatList, shapeOne, SAVE_IMAGE_WIDTH)

}

this.setState({
shapeList,
Expand Down Expand Up @@ -479,7 +490,7 @@ class AvatarEdit extends Component {
)
: (
<View className="page-cover-wrap">
{!!coverImageUrl && <Image src={imageThumb(coverImageUrl, 600, 600, 1, 'webp')} webp className="page-theme-cover" />}
{!!coverImageUrl && <Image src={imageThumb(coverImageUrl, 636, 744)} webp className="page-theme-cover" />}
<View className='page-theme-name'>{themeName}</View>
<View className='page-theme-slug'>{shareTitleSlug}</View>
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
transition ease-in-out 0.8s

.page-china
background-image url('../../../../images/bg-lead-china.jpg')
background-image url('../../../../images/bg-lead-christmas.jpg')
&:before
content ''
position absolute
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export default class ImageChoose extends Taro.Component {

return (
<View className='tab-wrap'>
<View className='tab-hd'>
<ScrollView className="tab-hd" scrollX enableFlex>
{
categoryList.map((item, itemIndex) => {
const { _id, categoryName } = item
Expand All @@ -55,7 +55,7 @@ export default class ImageChoose extends Taro.Component {
)
})
}
</View>
</ScrollView>
<View className='tab-bd'>
{
categoryList.map((item, itemIndex) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
.tab-wrap
background #fcfcfc
.tab-hd
padding 10px 10px 5px
display flex
padding 10px 0 5px
white-space nowrap



.tab-hd-item
display inline-block
padding 3px
border-radius 10px
font-size 16px
line-height 20px
margin-right 10px
color #AAAAAA
white-space nowrap

&:first-child
margin-left 10px

.tab-hd-active
padding 3px 10px
Expand Down
37 changes: 31 additions & 6 deletions taro/src/utils/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@ import Taro from '@tarojs/taro'

export const isH5Page = Taro.getEnv() === 'WEB'

/**
* 判断浏览器是否兼容 Webp 格式图片
*/
let hasWebP = false
function checkWebp() {
var img = new Image()
img.onload = function () {
hasWebP = !!(img.height > 0 && img.width > 0)
}
img.onerror = function () {
hasWebP = false
}
img.src = 'data:image/webp;base64,UklGRh4AAABXRUJQVlA4TBEAAAAvAAAAAAfQ//73v/+BiOh/AAA='
}

// 小程序上无需判断,H5需要判断,
if (isH5Page) {
checkWebp()
} else {
hasWebP = true
}

// 这个方法,不兼容Safari浏览器,所以改用了加载webp图片的方式
// Safari 14支持webp格式,但dataUrl中还是 image/png
function checkSupportWebP() {
const ele = document.createElement('canvas')
if (ele && typeof ele.toDataURL === 'function') {
Expand All @@ -11,8 +35,8 @@ function checkSupportWebP() {
return false
}

// 判断支持 WebP 格式图片
const isSupportWebP = isH5Page ? checkSupportWebP() : true
// // 判断支持 WebP 格式图片
// const isSupportWebP = isH5Page ? checkSupportWebP() : true

let _systemInfo = null
let _isXPhoneArea = null
Expand Down Expand Up @@ -71,9 +95,9 @@ export function h5PageModalTips() {
* 文档:https://cloud.tencent.com/document/product/460/6929
*/
export const imageThumb = (src, width, height, format = 'webp', mode = 1, ) => {

if (!src) return ''
if (src.includes('cloud')) return src
if (src.includes('cloud:')) return src

let pathn = src.trim().replace(/^http(s)?:\/\//ig, '')

pathn = pathn.split('/')
Expand All @@ -89,8 +113,9 @@ export const imageThumb = (src, width, height, format = 'webp', mode = 1, ) => {
} else {
returnUrl = src.replace(/(\.[a-z_]+)$/ig, `$1?imageView2/${mode}/w/${width || 0}/h/${height || 0}`)
}

if (format && isSupportWebP) {

if (format === 'webp' && hasWebP) {

returnUrl += '/format/webp/ignore-error/1'
}
}
Expand Down
22 changes: 12 additions & 10 deletions taro/src/utils/face-utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,14 +161,13 @@ export function getHatShapeList(hatList, shapeItem, saveImageWidth = 600) {

return {
shapeId,
timeNow: Date.now(),
timeNow: Date.now() * Math.random(),
imageUrl,
imageReverseUrl,
shapeWidth,
shapeHeight: shapeWidth,
position: parseInt(shapeItem.position),
currentShapeId: 1,
timeNow: Date.now() * Math.random(),
shapeCenterX,
shapeCenterY,
reserve: 1,
Expand Down Expand Up @@ -246,31 +245,34 @@ export function getMouthList(results) {
* @param {array} shapeItem 贴纸信息
* @param {number} saveImageWidth 预期保存的图片宽
*/
export function getMaskShapeList(mouthList, dprCanvasWidth, shapeSize) {
export function getMaskShapeList(mouthList, shapeItem, saveImageWidth = 600) {
const { imageUrl = '', imageReverseUrl, _id: shapeId } = shapeItem || {}
return mouthList.map(item => {
let { faceWidth, angle, mouthMidPoint, ImageWidth } = item
let dpr = ImageWidth / dprCanvasWidth
let dpr = saveImageWidth / ImageWidth // 头像宽高为132,达不到600
const shapeCenterX = mouthMidPoint.X / dpr
const shapeCenterY = mouthMidPoint.Y / dpr
const scale = faceWidth / shapeSize / dpr
const rotate = angle / Math.PI * 180

// 角度计算有点难
let widthScaleDpr = Math.sin(Math.PI / 4 - angle) * Math.sqrt(2) * scale * 50
let heightScaleDpr = Math.cos(Math.PI / 4 - angle) * Math.sqrt(2) * scale * 50
let widthScaleDpr = Math.sin(Math.PI / 4 - angle) * Math.sqrt(2) * faceWidth * dpr
let heightScaleDpr = Math.cos(Math.PI / 4 - angle) * Math.sqrt(2) * faceWidth * dpr

const resizeCenterX = shapeCenterX + widthScaleDpr - 2
const resizeCenterY = shapeCenterY + heightScaleDpr - 2

const shapeWidth = faceWidth * 1.2 / dpr

return {
name: 'mask',
shapeId,
timeNow: Date.now() * Math.random(),
imageUrl,
imageReverseUrl,
shapeWidth,
shapeHeight: shapeWidth,
// position: parseInt(shapeItem.position),
name: 'mask',
position: parseInt(shapeItem.position),
currentShapeId: 1,
timeNow: Date.now() * Math.random(),
shapeCenterX,
shapeCenterY,
reserve: 1,
Expand Down

0 comments on commit 3285e1a

Please sign in to comment.