From ba20aaf241e4b2ae3a0007d8f547120c28d1f3ac Mon Sep 17 00:00:00 2001 From: wangyaqi Date: Mon, 4 Nov 2019 14:52:26 +0800 Subject: [PATCH] fix(v3): add canvasToTempFilePath etc. --- src/core/service/api/context/canvas.js | 81 +++++---------- src/core/view/components/canvas/index.vue | 99 +++++++++++++++++-- .../app-plus/service/api/context/canvas.js | 78 +++++++++++++++ src/platforms/app-plus/service/api/index.js | 1 + .../h5/service/api/context/canvas.js | 27 +++-- 5 files changed, 213 insertions(+), 73 deletions(-) create mode 100644 src/platforms/app-plus/service/api/context/canvas.js diff --git a/src/core/service/api/context/canvas.js b/src/core/service/api/context/canvas.js index e9813276c..c4f353b1f 100644 --- a/src/core/service/api/context/canvas.js +++ b/src/core/service/api/context/canvas.js @@ -1,9 +1,14 @@ import createCallbacks from 'uni-helpers/callbacks' import { + invokeMethod, getCurrentPageId } from '../../platform' +import { + invoke +} from '../../bridge' + const canvasEventCallbacks = createCallbacks('canvasEvent') UniServiceJSBridge.subscribe('onDrawCanvas', ({ @@ -229,10 +234,6 @@ function checkColor (e) { return [0, 0, 0, 255] } -function TextMetrics (width) { - this.width = width -} - function Pattern (image, repetition) { this.image = image this.repetition = repetition @@ -257,14 +258,6 @@ var methods3 = ['setFillStyle', 'setTextAlign', 'setStrokeStyle', 'setGlobalAlph 'setTextBaseline', 'setLineDash' ] -var tempCanvas -function getTempCanvas () { - if (!tempCanvas) { - tempCanvas = document.createElement('canvas') - } - return tempCanvas -} - class CanvasContext { constructor (id, pageId) { this.id = id @@ -319,11 +312,9 @@ class CanvasContext { return new Pattern(image, repetition) } } - measureText (text) { - var c2d = getTempCanvas().getContext('2d') - c2d.font = this.state.font - return new TextMetrics(c2d.measureText(text).width || 0) - } + // TODO + // measureText (text) { + // } save () { this.actions.push({ method: 'save', @@ -742,10 +733,6 @@ export function createCanvasContext (id, context) { } } -const { - invokeCallbackHandler: invoke -} = UniServiceJSBridge - export function canvasGetImageData ({ canvasId, x, @@ -823,47 +810,27 @@ export function canvasToTempFilePath ({ return } const cId = canvasEventCallbacks.push(function ({ - data, - width, - height + base64 }) { - if (!data || !data.length) { + if (!base64 || !base64.length) { invoke(callbackId, { errMsg: 'canvasToTempFilePath:fail' }) - return } - let imgData - try { - imgData = new ImageData(new Uint8ClampedArray(data), width, height) - } catch (error) { - invoke(callbackId, { - errMsg: 'canvasToTempFilePath:fail' - }) - return - } - const canvas = getTempCanvas() - canvas.width = width - canvas.height = height - const c2d = canvas.getContext('2d') - c2d.putImageData(imgData, 0, 0) - let base64 = canvas.toDataURL('image/png') - const img = new Image() - img.onload = function () { - if (fileType === 'jpeg') { - c2d.fillStyle = '#fff' - c2d.fillRect(0, 0, width, width) - } - c2d.drawImage(img, 0, 0) - base64 = canvas.toDataURL(`image/${fileType}`, qualit) - invoke(callbackId, { - errMsg: 'canvasToTempFilePath:ok', - tempFilePath: base64 - }) - } - img.src = base64 + invokeMethod('base64ToTempFilePath', { + base64Data: base64, + x, + y, + width, + height, + destWidth, + destHeight, + canvasId, + fileType, + qualit + }, callbackId) }) - operateCanvas(canvasId, pageId, 'getImageData', { + operateCanvas(canvasId, pageId, 'getDataUrl', { x, y, width, @@ -871,6 +838,8 @@ export function canvasToTempFilePath ({ destWidth, destHeight, hidpi: false, + fileType, + qualit, callbackId: cId }) } diff --git a/src/core/view/components/canvas/index.vue b/src/core/view/components/canvas/index.vue index 9f7c357f0..7deaf205a 100644 --- a/src/core/view/components/canvas/index.vue +++ b/src/core/view/components/canvas/index.vue @@ -412,7 +412,10 @@ export default { context.__hidpi__ = true context.drawImageByCanvas(canvas, x, y, width, height, 0, 0, destWidth, destHeight, false) imgData = context.getImageData(0, 0, destWidth, destHeight) - } catch (error) { + } catch (error) { + if (!callbackId) { + return + } UniViewJSBridge.publishHandler('onCanvasMethodCallback', { callbackId, data: { @@ -420,16 +423,24 @@ export default { } }, this.$page.id) return + } + if (!callbackId) { + return { + data: [...imgData.data], + width: destWidth, + height: destHeight + } + } else { + UniViewJSBridge.publishHandler('onCanvasMethodCallback', { + callbackId, + data: { + errMsg: 'canvasGetImageData:ok', + data: [...imgData.data], + width: destWidth, + height: destHeight + } + }, this.$page.id) } - UniViewJSBridge.publishHandler('onCanvasMethodCallback', { - callbackId, - data: { - errMsg: 'canvasGetImageData:ok', - data: [...imgData.data], - width: destWidth, - height: destHeight - } - }, this.$page.id) }, putImageData ({ data, @@ -464,6 +475,74 @@ export default { errMsg: 'canvasPutImageData:ok' } }, this.$page.id) + }, + getDataUrl ({ + x = 0, + y = 0, + width, + height, + destWidth, + destHeight, + hidpi = true, + fileType, + qualit, + callbackId + }) { + let res = this.getImageData({ + x, + y, + width, + height, + destWidth, + destHeight, + hidpi + }) + if (!res.data || !res.data.length) { + UniViewJSBridge.publishHandler('onCanvasMethodCallback', { + callbackId, + data: { + errMsg: 'canvasGetDataUrl:fail' + } + }, this.$page.id) + return + } + let imgData + try { + imgData = new ImageData(new Uint8ClampedArray(res.data), res.width, res.height) + } catch (error) { + UniViewJSBridge.publishHandler('onCanvasMethodCallback', { + callbackId, + data: { + errMsg: 'canvasGetDataUrl:fail' + } + }, this.$page.id) + return + } + destWidth = res.width + destHeight = res.height + const canvas = document.createElement('canvas') + canvas.width = destWidth + canvas.height = destHeight + const c2d = canvas.getContext('2d') + c2d.putImageData(imgData, 0, 0) + let base64 = canvas.toDataURL('image/png') + const img = new Image() + img.onload = () => { + if (fileType === 'jpeg') { + c2d.fillStyle = '#fff' + c2d.fillRect(0, 0, destWidth, destHeight) + } + c2d.drawImage(img, 0, 0) + base64 = canvas.toDataURL(`image/${fileType}`, qualit) + UniViewJSBridge.publishHandler('onCanvasMethodCallback', { + callbackId, + data: { + errMsg: 'canvasGetDataUrl:ok', + base64: base64 + } + }, this.$page.id) + } + img.src = base64 } } } diff --git a/src/platforms/app-plus/service/api/context/canvas.js b/src/platforms/app-plus/service/api/context/canvas.js new file mode 100644 index 000000000..fe696eb43 --- /dev/null +++ b/src/platforms/app-plus/service/api/context/canvas.js @@ -0,0 +1,78 @@ +import { + invoke +} from '../../bridge' + +import { + TEMP_PATH +} from '../constants' + +/** + * 5+错误对象转换为错误消息 + * @param {*} error 5+错误对象 + */ +function toErrMsg (error) { + var msg = 'base64ToTempFilePath:fail' + if (error && error.message) { + msg += ` ${error.message}` + } else if (error) { + msg += ` ${error}` + } + return msg +} + +export function base64ToTempFilePath ({ + base64Data, + x, + y, + width, + height, + destWidth, + destHeight, + canvasId, + fileType, + quality +} = {}, callbackId) { + var id = Date.now() + var bitmap = new plus.nativeObj.Bitmap(`bitmap${id}`) + bitmap.loadBase64Data(base64Data, function () { + var formats = ['jpg', 'png'] + var format = String(fileType).toLowerCase() + if (formats.indexOf(format) < 0) { + format = 'png' + } + /** + * 保存配置 + */ + var saveOption = { + overwrite: true, + quality: typeof quality === 'number' ? quality * 100 : 100, + format + } + /** + * 保存文件路径 + */ + var tempFilePath = `${TEMP_PATH}/canvas/${id}.${format}` + + bitmap.save(tempFilePath, saveOption, function () { + clear() + invoke(callbackId, { + tempFilePath, + errMsg: 'base64ToTempFilePath:ok' + }) + }, function (error) { + clear() + invoke(callbackId, { + errMsg: toErrMsg(error) + }) + }) + }, function (error) { + clear() + invoke(callbackId, { + errMsg: toErrMsg(error) + }) + }) + + function clear () { + bitmap.clear() + } +} diff --git a/src/platforms/app-plus/service/api/index.js b/src/platforms/app-plus/service/api/index.js index 8338f60ba..b0a7c5355 100644 --- a/src/platforms/app-plus/service/api/index.js +++ b/src/platforms/app-plus/service/api/index.js @@ -1,5 +1,6 @@ export * from './context/audio' export * from './context/background-audio' +export * from './context/canvas' export * from './context/operate-map-player' export * from './context/operate-video-player' diff --git a/src/platforms/h5/service/api/context/canvas.js b/src/platforms/h5/service/api/context/canvas.js index 290ddcf6f..1c3f5c784 100644 --- a/src/platforms/h5/service/api/context/canvas.js +++ b/src/platforms/h5/service/api/context/canvas.js @@ -1,8 +1,21 @@ -export function operateCanvasContext (canvasId, pageVm, type, data) { - const pageId = pageVm.$page.id - UniServiceJSBridge.publishHandler(pageId + '-canvas-' + canvasId, { - canvasId, - type, - data - }, pageId) +const { + invokeCallbackHandler: invoke +} = UniServiceJSBridge + +export function base64ToTempFilePath ({ + base64Data, + x, + y, + width, + height, + destWidth, + destHeight, + canvasId, + fileType, + quality +} = {}, callbackId) { + invoke(callbackId, { + errMsg: 'canvasToTempFilePath:ok', + tempFilePath: base64Data + }) } -- GitLab