【蜘蛛管家】邀请码- UI还原不足】 https://www.tapd.cn/53459131/bugtrace/bugs/view/1153459131001000938
269 lines
7.7 KiB
TypeScript
269 lines
7.7 KiB
TypeScript
import { Canvas } from '@tarojs/components'
|
|
import Taro from '@tarojs/taro'
|
|
import { forwardRef, useImperativeHandle, useRef, useState } from 'react'
|
|
import Downloader from './lib/downloader'
|
|
import Pen from './lib/pen'
|
|
import { equal, toPx } from './lib/util'
|
|
/**
|
|
*
|
|
* 入参 palette 格式
|
|
* const imgDraw = {
|
|
width: '1124rpx',
|
|
height: '1578rpx',
|
|
background: getCDNSource('/user/inviteCodePopup.png'),
|
|
views: [
|
|
{
|
|
type: 'image',
|
|
url: 'https://qiniu-image.qtshe.com/1560248372315_467.jpg',
|
|
css: {
|
|
top: '32rpx',
|
|
left: '30rpx',
|
|
right: '32rpx',
|
|
width: '688rpx',
|
|
height: '420rpx',
|
|
borderRadius: '16rpx',
|
|
},
|
|
},
|
|
{
|
|
type: 'text',
|
|
text: '青团子',
|
|
css: {
|
|
top: '532rpx',
|
|
fontSize: '28rpx',
|
|
left: '375rpx',
|
|
align: 'center',
|
|
color: '#3c3c3c',
|
|
},
|
|
},
|
|
],
|
|
}
|
|
*
|
|
*/
|
|
const downloader = new Downloader()
|
|
|
|
let SystemInfo = Taro.getSystemInfoSync()
|
|
|
|
// 最大尝试的绘制次数
|
|
const MAX_PAINT_COUNT = 5
|
|
|
|
interface PropsType {
|
|
customStyle?: React.CSSProperties
|
|
painterStyle?: React.CSSProperties
|
|
dirty?: boolean
|
|
palette?: any // 参考上方
|
|
onImgErr: (result) => void
|
|
onImgOK: (result) => void
|
|
}
|
|
// 绘画
|
|
const Painter = (props: PropsType, ref) => {
|
|
const { customStyle, painterStyle: _painterStyle, dirty, palette, onImgErr, onImgOK } = props
|
|
const [painterStyle, setPainterStyle] = useState(_painterStyle)
|
|
const canvasWidthInPx = useRef(0)
|
|
const canvasHeightInPx = useRef(0)
|
|
const paintCount = useRef(0)
|
|
|
|
const [, setForceUpdate] = useState({})
|
|
const canvasNode = useRef<any>(null)
|
|
const ctx = useRef<any>(null)
|
|
/**
|
|
* 判断一个 object 是否为 空
|
|
* @param {object} object
|
|
*/
|
|
const isEmpty = (object) => {
|
|
for (const i in object) {
|
|
if (i) {
|
|
return false
|
|
}
|
|
}
|
|
return true
|
|
}
|
|
const isNeedRefresh = (newVal, oldVal) => {
|
|
if (!newVal || isEmpty(newVal) || (dirty && equal(newVal, oldVal))) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
const downloadImages = () => {
|
|
return new Promise((resolve, reject) => {
|
|
let preCount = 0
|
|
let completeCount = 0
|
|
const paletteCopy = JSON.parse(JSON.stringify(palette))
|
|
if (paletteCopy.background) {
|
|
preCount++
|
|
downloader.download(paletteCopy.background).then((path) => {
|
|
paletteCopy.background = path
|
|
completeCount++
|
|
if (preCount === completeCount) {
|
|
resolve(paletteCopy)
|
|
}
|
|
}, () => {
|
|
completeCount++
|
|
if (preCount === completeCount) {
|
|
resolve(paletteCopy)
|
|
}
|
|
})
|
|
}
|
|
if (paletteCopy.views) {
|
|
for (const view of paletteCopy.views) {
|
|
if (view && view.type === 'image' && view.url) {
|
|
preCount++
|
|
console.log('url', view.url)
|
|
/* eslint-disable no-loop-func */
|
|
downloader.download(view.url).then((path) => {
|
|
console.log('path', path)
|
|
view.url = path
|
|
Taro.getImageInfo({
|
|
src: view.url,
|
|
success: (res) => {
|
|
// 获得一下图片信息,供后续裁减使用
|
|
view.sWidth = res.width
|
|
view.sHeight = res.height
|
|
},
|
|
fail: (error) => {
|
|
console.log(`imgDownloadErr failed, ${JSON.stringify(error)}`)
|
|
onImgErr({ error })
|
|
},
|
|
complete: () => {
|
|
completeCount++
|
|
if (preCount === completeCount) {
|
|
resolve(paletteCopy)
|
|
}
|
|
},
|
|
})
|
|
}, () => {
|
|
completeCount++
|
|
if (preCount === completeCount) {
|
|
resolve(paletteCopy)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
if (preCount === 0) {
|
|
resolve(paletteCopy)
|
|
}
|
|
})
|
|
}
|
|
// 初始化 canvas
|
|
const initCanvas = async() => {
|
|
return new Promise<{ canvas: Taro.Canvas; ctx: Taro.RenderingContext }>((resolve, reject) => {
|
|
Taro.nextTick(() => {
|
|
const query = Taro.createSelectorQuery()
|
|
query.select('#canvas').node(({ node: canvas }: { node: Taro.Canvas }) => {
|
|
console.log('canvas==>', canvas)
|
|
const context = canvas.getContext('2d')
|
|
console.log('ctx', context)
|
|
canvasNode.current = canvas
|
|
ctx.current = context
|
|
console.log('canvas', canvas)
|
|
setForceUpdate({})
|
|
resolve({ canvas: canvasNode.current, ctx: ctx.current })
|
|
}).exec()
|
|
})
|
|
})
|
|
}
|
|
// 开始绘制
|
|
const _startPaint = () => {
|
|
if (isEmpty(palette)) {
|
|
return
|
|
}
|
|
console.log('startPaint', palette)
|
|
if (!(SystemInfo && SystemInfo.screenWidth)) {
|
|
try {
|
|
SystemInfo = Taro.getSystemInfoSync()
|
|
}
|
|
catch (e) {
|
|
const error = `Painter get system info failed, ${JSON.stringify(e)}`
|
|
// that.triggerEvent('imgErr', { error })
|
|
onImgErr({ error })
|
|
console.log(error)
|
|
return
|
|
}
|
|
}
|
|
|
|
downloadImages().then((palette: any) => {
|
|
const { width, height } = palette
|
|
canvasWidthInPx.current = toPx(width)
|
|
canvasHeightInPx.current = toPx(height)
|
|
if (!width || !height) {
|
|
console.log(`You should set width and height correctly for painter, width: ${width}, height: ${height}`)
|
|
return
|
|
}
|
|
console.log('palette', palette, width, height)
|
|
setPainterStyle({
|
|
width: `${width}`,
|
|
height: `${height}`,
|
|
})
|
|
// 初始化canvas
|
|
initCanvas().then(({ ctx, canvas }) => {
|
|
// const ctx = Taro.createCanvasContext('k-canvas', this)
|
|
const pen = new Pen(ctx, canvas, palette)
|
|
pen.paint((canvas) => {
|
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
saveImgToLocal(canvas)
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
const getImageInfo = (filePath: string) => {
|
|
Taro.getImageInfo({
|
|
src: filePath,
|
|
success: (infoRes) => {
|
|
if (paintCount.current > MAX_PAINT_COUNT) {
|
|
const error = `The result is always fault, even we tried ${MAX_PAINT_COUNT} times`
|
|
console.log(error)
|
|
onImgErr({ error })
|
|
return
|
|
}
|
|
// 比例相符时才证明绘制成功,否则进行强制重绘制
|
|
if (Math.abs((infoRes.width * canvasHeightInPx.current - canvasWidthInPx.current * infoRes.height) / (infoRes.height * canvasHeightInPx.current)) < 0.01) {
|
|
onImgOK({ path: filePath })
|
|
}
|
|
else {
|
|
console.log('infoRes filePath', infoRes, filePath, canvasHeightInPx.current, canvasWidthInPx.current)
|
|
_startPaint()
|
|
}
|
|
paintCount.current++
|
|
},
|
|
fail: (error) => {
|
|
console.log(`getImageInfo failed, ${JSON.stringify(error)}`)
|
|
onImgErr({ error })
|
|
},
|
|
})
|
|
}
|
|
const saveImgToLocal = (canvas) => {
|
|
setTimeout(() => {
|
|
Taro.canvasToTempFilePath({
|
|
canvas,
|
|
fileType: 'png',
|
|
success(res) {
|
|
console.log('tempFilePath', res.tempFilePath, canvas)
|
|
getImageInfo(res.tempFilePath)
|
|
},
|
|
fail(error) {
|
|
console.log(`canvasToTempFilePath failed, ${JSON.stringify(error)}`)
|
|
// that.triggerEvent('imgErr', { error })
|
|
onImgErr({ error })
|
|
},
|
|
}, this)
|
|
}, 300)
|
|
}
|
|
// 暴露
|
|
useImperativeHandle(
|
|
ref,
|
|
() => {
|
|
return {
|
|
startPaint: () => {
|
|
paintCount.current = 0
|
|
_startPaint()
|
|
},
|
|
}
|
|
},
|
|
[paintCount.current],
|
|
)
|
|
return <Canvas style={{ ...customStyle, ...painterStyle }} id="canvas" type="2d" />
|
|
}
|
|
export default forwardRef(Painter)
|