提交 7062b625 编写于 作者: Q qiang

fix: 优化H5端canvas组件内存占用

上级 6537109e
export const pixelRatio = (function () { export const pixelRatio = (function () {
const canvas = document.createElement('canvas') const canvas = document.createElement('canvas')
canvas.height = canvas.width = 0
const context = canvas.getContext('2d') const context = canvas.getContext('2d')
const backingStore = context.backingStorePixelRatio || const backingStore = context.backingStorePixelRatio ||
context.webkitBackingStorePixelRatio || context.webkitBackingStorePixelRatio ||
context.mozBackingStorePixelRatio || context.mozBackingStorePixelRatio ||
context.msBackingStorePixelRatio || context.msBackingStorePixelRatio ||
context.oBackingStorePixelRatio || context.oBackingStorePixelRatio ||
context.backingStorePixelRatio || 1 context.backingStorePixelRatio || 1
return (window.devicePixelRatio || 1) / backingStore return (window.devicePixelRatio || 1) / backingStore
})() })()
......
...@@ -259,10 +259,12 @@ var methods3 = ['setFillStyle', 'setTextAlign', 'setStrokeStyle', 'setGlobalAlph ...@@ -259,10 +259,12 @@ var methods3 = ['setFillStyle', 'setTextAlign', 'setStrokeStyle', 'setGlobalAlph
] ]
var tempCanvas var tempCanvas
function getTempCanvas () { function getTempCanvas (width = 0, height = 0) {
if (!tempCanvas) { if (!tempCanvas) {
tempCanvas = document.createElement('canvas') tempCanvas = document.createElement('canvas')
} }
tempCanvas.width = width
tempCanvas.height = height
return tempCanvas return tempCanvas
} }
......
<template> <template>
<uni-canvas <uni-canvas
:canvas-id="canvasId" :canvas-id="canvasId"
:disable-scroll="disableScroll" :disable-scroll="disableScroll"
v-on="_listeners"> v-on="_listeners">
<canvas <canvas
ref="canvas" ref="canvas"
width="300" width="300"
height="150" /> height="150" />
<div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden;"> <div style="position: absolute; top: 0; left: 0; width: 100%; height: 100%; overflow: hidden;">
<slot /> <slot />
</div> </div>
<v-uni-resize-sensor <v-uni-resize-sensor
ref="sensor" ref="sensor"
@resize="_resize"/> @resize="_resize" />
</uni-canvas> </uni-canvas>
</template> </template>
<script> <script>
...@@ -42,6 +42,16 @@ function processTouches (target, touches) { ...@@ -42,6 +42,16 @@ function processTouches (target, touches) {
}) })
} }
var tempCanvas
function getTempCanvas (width = 0, height = 0) {
if (!tempCanvas) {
tempCanvas = document.createElement('canvas')
}
tempCanvas.width = width
tempCanvas.height = height
return tempCanvas
}
export default { export default {
name: 'Canvas', name: 'Canvas',
mixins: [subscriber], mixins: [subscriber],
...@@ -97,6 +107,10 @@ export default { ...@@ -97,6 +107,10 @@ export default {
height: this.$refs.sensor.$el.offsetHeight height: this.$refs.sensor.$el.offsetHeight
}) })
}, },
beforeDestroy () {
const canvas = this.$refs.canvas
canvas.height = canvas.width = 0
},
methods: { methods: {
_handleSubscribe ({ _handleSubscribe ({
type, type,
...@@ -335,7 +349,7 @@ export default { ...@@ -335,7 +349,7 @@ export default {
} else { } else {
// 解决 PLUS-APP(wkwebview)以及 H5 图像跨域问题(H5图像响应头需包含access-control-allow-origin) // 解决 PLUS-APP(wkwebview)以及 H5 图像跨域问题(H5图像响应头需包含access-control-allow-origin)
if (window.plus && src.indexOf('http://') !== 0 && src.indexOf('https://') !== if (window.plus && src.indexOf('http://') !== 0 && src.indexOf('https://') !==
0) { 0) {
loadFile(src) loadFile(src)
} else if (/^data:.*,.*/.test(src)) { } else if (/^data:.*,.*/.test(src)) {
sefl._images[src].src = src sefl._images[src].src = src
...@@ -392,7 +406,6 @@ export default { ...@@ -392,7 +406,6 @@ export default {
height = canvas.offsetHeight - y height = canvas.offsetHeight - y
} }
try { try {
const newCanvas = document.createElement('canvas')
if (!hidpi) { if (!hidpi) {
if (!destWidth && !destHeight) { if (!destWidth && !destHeight) {
destWidth = Math.round(width * pixelRatio) destWidth = Math.round(width * pixelRatio)
...@@ -406,15 +419,15 @@ export default { ...@@ -406,15 +419,15 @@ export default {
destWidth = width destWidth = width
destHeight = height destHeight = height
} }
newCanvas.width = destWidth const newCanvas = getTempCanvas(destWidth, destHeight)
newCanvas.height = destHeight
const context = newCanvas.getContext('2d') const context = newCanvas.getContext('2d')
context.__hidpi__ = true context.__hidpi__ = true
context.drawImageByCanvas(canvas, x, y, width, height, 0, 0, destWidth, destHeight, false) context.drawImageByCanvas(canvas, x, y, width, height, 0, 0, destWidth, destHeight, false)
imgData = context.getImageData(0, 0, destWidth, destHeight) imgData = context.getImageData(0, 0, destWidth, destHeight)
} catch (error) { newCanvas.height = newCanvas.width = 0
if (!callbackId) { } catch (error) {
return if (!callbackId) {
return
} }
UniViewJSBridge.publishHandler('onCanvasMethodCallback', { UniViewJSBridge.publishHandler('onCanvasMethodCallback', {
callbackId, callbackId,
...@@ -423,13 +436,13 @@ export default { ...@@ -423,13 +436,13 @@ export default {
} }
}, this.$page.id) }, this.$page.id)
return return
} }
if (!callbackId) { if (!callbackId) {
return { return {
data: [...imgData.data], data: [...imgData.data],
width: destWidth, width: destWidth,
height: destHeight height: destHeight
} }
} else { } else {
UniViewJSBridge.publishHandler('onCanvasMethodCallback', { UniViewJSBridge.publishHandler('onCanvasMethodCallback', {
callbackId, callbackId,
...@@ -439,7 +452,7 @@ export default { ...@@ -439,7 +452,7 @@ export default {
width: destWidth, width: destWidth,
height: destHeight height: destHeight
} }
}, this.$page.id) }, this.$page.id)
} }
}, },
putImageData ({ putImageData ({
...@@ -454,12 +467,11 @@ export default { ...@@ -454,12 +467,11 @@ export default {
if (!height) { if (!height) {
height = Math.round(data.length / 4 / width) height = Math.round(data.length / 4 / width)
} }
const canvas = document.createElement('canvas') const canvas = getTempCanvas(width, height)
canvas.width = width
canvas.height = height
const context = canvas.getContext('2d') const context = canvas.getContext('2d')
context.putImageData(new ImageData(new Uint8ClampedArray(data), width, height), 0, 0) context.putImageData(new ImageData(new Uint8ClampedArray(data), width, height), 0, 0)
this.$refs.canvas.getContext('2d').drawImage(canvas, x, y, width, height) this.$refs.canvas.getContext('2d').drawImage(canvas, x, y, width, height)
canvas.height = canvas.width = 0
} catch (error) { } catch (error) {
UniViewJSBridge.publishHandler('onCanvasMethodCallback', { UniViewJSBridge.publishHandler('onCanvasMethodCallback', {
callbackId, callbackId,
...@@ -475,91 +487,92 @@ export default { ...@@ -475,91 +487,92 @@ export default {
errMsg: 'canvasPutImageData:ok' errMsg: 'canvasPutImageData:ok'
} }
}, this.$page.id) }, this.$page.id)
}, },
getDataUrl ({ getDataUrl ({
x = 0, x = 0,
y = 0, y = 0,
width, width,
height, height,
destWidth, destWidth,
destHeight, destHeight,
hidpi = true, hidpi = true,
fileType, fileType,
qualit, qualit,
callbackId callbackId
}) { }) {
let res = this.getImageData({ let res = this.getImageData({
x, x,
y, y,
width, width,
height, height,
destWidth, destWidth,
destHeight, destHeight,
hidpi hidpi
}) })
if (!res.data || !res.data.length) { if (!res.data || !res.data.length) {
UniViewJSBridge.publishHandler('onCanvasMethodCallback', { UniViewJSBridge.publishHandler('onCanvasMethodCallback', {
callbackId, callbackId,
data: { data: {
errMsg: 'canvasGetDataUrl:fail' errMsg: 'canvasGetDataUrl:fail'
} }
}, this.$page.id) }, this.$page.id)
return return
} }
let imgData let imgData
try { try {
imgData = new ImageData(new Uint8ClampedArray(res.data), res.width, res.height) imgData = new ImageData(new Uint8ClampedArray(res.data), res.width, res.height)
} catch (error) { } catch (error) {
UniViewJSBridge.publishHandler('onCanvasMethodCallback', { UniViewJSBridge.publishHandler('onCanvasMethodCallback', {
callbackId, callbackId,
data: { data: {
errMsg: 'canvasGetDataUrl:fail' errMsg: 'canvasGetDataUrl:fail'
} }
}, this.$page.id) }, this.$page.id)
return return
} }
destWidth = res.width destWidth = res.width
destHeight = res.height destHeight = res.height
const canvas = document.createElement('canvas') const canvas = getTempCanvas(destWidth, destHeight)
canvas.width = destWidth const c2d = canvas.getContext('2d')
canvas.height = destHeight c2d.putImageData(imgData, 0, 0)
const c2d = canvas.getContext('2d') let base64 = canvas.toDataURL('image/png')
c2d.putImageData(imgData, 0, 0) canvas.height = canvas.width = 0
let base64 = canvas.toDataURL('image/png') const img = new Image()
const img = new Image() img.onload = () => {
img.onload = () => { const canvas = getTempCanvas(destWidth, destHeight)
if (fileType === 'jpeg') { if (fileType === 'jpeg') {
c2d.fillStyle = '#fff' c2d.fillStyle = '#fff'
c2d.fillRect(0, 0, destWidth, destHeight) c2d.fillRect(0, 0, destWidth, destHeight)
} }
c2d.drawImage(img, 0, 0) c2d.drawImage(img, 0, 0)
base64 = canvas.toDataURL(`image/${fileType}`, qualit) base64 = canvas.toDataURL(`image/${fileType}`, qualit)
UniViewJSBridge.publishHandler('onCanvasMethodCallback', { canvas.height = canvas.width = 0
callbackId, UniViewJSBridge.publishHandler('onCanvasMethodCallback', {
data: { callbackId,
errMsg: 'canvasGetDataUrl:ok', data: {
base64: base64 errMsg: 'canvasGetDataUrl:ok',
} base64: base64
}, this.$page.id) }
} }, this.$page.id)
img.src = base64 }
img.src = base64
} }
} }
} }
</script> </script>
<style> <style>
uni-canvas { uni-canvas {
width: 300px; width: 300px;
height: 150px; height: 150px;
display: block; display: block;
position: relative; position: relative;
} }
uni-canvas>canvas { uni-canvas > canvas {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
</style> </style>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册