Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

加入“非实时渲染”以解决频繁绘制 canvas 带来的卡顿问题 #55

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 60 additions & 5 deletions dist/we-cropper.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ var DEFAULT = {
tmp.cut = value;
}
},
inRealTime: {
ttys026 marked this conversation as resolved.
Show resolved Hide resolved
default: true,
get: function get () {
return tmp.inRealTime
},
set: function set (value) {
if (typeof (value) !== 'boolean') {
console.error(('inRealTime:' + value + ' is invalid'));
}
tmp.inRealTime = value;
}
},
onReady: {
default: null,
get: function get () {
Expand Down Expand Up @@ -180,6 +192,7 @@ function prepare () {
var pageContext = pages[pages.length - 1];
// 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问
pageContext.wecropper = self;
self.pageContext = pageContext;
};

self.createCtx = function () {
Expand Down Expand Up @@ -622,6 +635,30 @@ function methods () {
return self
};

self.updateImage = function (isInit) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

能否有办法避免在库中setData呢,因为这样处理的话,和外部cropperOpt耦合了,能否做成外部的拓展模块,因为imgLeft、imgTop等属性是可以通过实例拿到的

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

如果要在外部 page 中更新 UI 的话,这就可以解决 cropperOpt 耦合的问题了。可以在 __oneTouchMove__twoTouchMove 中放置两个钩子函数,比如 onTouchMove, 然后开发者在自己的 page 中调用钩子函数来 setData

这样会有个问题: <image/> 要由开发者去处理。以及 <image/> 是放在 template 里,还是开发者自己写在 page 里。

更好的方式应该是:开发者在使用 we-cropper 时,只需指定参数和监听事件,其他裁切相关的具体逻辑都无需过问。

如果将 cropperOpt 定义为固定的接口参数,那在 we-croppersetData应该就不是问题。只需在裁切成功、失败以及取消之后,再 we-cropper.pageContext = null 来解决循环引用导致的内存泄漏问题。

如果以小程序的 component 组件 来实现 we-cropper,是不是会更合适

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里我的考虑是,we-cropper理念还是设计成一个库,最终可以运行在各个平台(框架)上,尽可能脱离宿主上下文环境,目前we-cropper缺乏一套可靠的插件拓展机制,这个是一个必须解决的首要问题。

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

更新你的代码以后,跑不起来呀,cropperImageSrc imageTop 这些属性都是获不到值,例子,应该是1.2版本的吧,

if ( isInit === void 0 ) isInit = false;

if (self.croperTarget && isInit) {
self.pageContext.setData({
'cropperOpt.cropperImageSrc': self.croperTarget
});
}

if (!self.imgLeft || !self.imgTop) {
return
}

self.pageContext.setData({
'cropperOpt.imageLeft': self.imgLeft,
'cropperOpt.imageTop': self.imgTop,
'cropperOpt.imageWidth': self.scaleWidth,
'cropperOpt.imageHeight': self.scaleHeight

});

return self
};

self.pushOrign = function (src) {
self.src = src;

Expand All @@ -633,7 +670,7 @@ function methods () {
var innerAspectRadio = res.width / res.height;

self.croperTarget = res.path;

if (innerAspectRadio < width / height) {
self.rectX = x;
self.baseWidth = width;
Expand All @@ -651,7 +688,11 @@ function methods () {
self.scaleWidth = self.baseWidth;
self.scaleHeight = self.baseHeight;

self.updateCanvas();
if (!self.inRealTime) {
self.updateImage(true);
} else {
self.updateCanvas();
}

isFunction(self.onImageLoad) && self.onImageLoad(self.ctx, self);
}
Expand All @@ -677,6 +718,8 @@ function methods () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];

self.updateCanvas();

var ARG_TYPE = toString.call(args[0]);
var fn = args[args.length - 1];

Expand Down Expand Up @@ -760,7 +803,11 @@ function update () {
var xMove, yMove;
// 计算单指移动的距离
if (self.touchended) {
return self.updateCanvas()
if (!self.inRealTime) {
return self.updateImage()
} else {
return self.updateCanvas()
}
}
xMove = Math.round(touch.x - self.touchX0);
yMove = Math.round(touch.y - self.touchY0);
Expand All @@ -770,7 +817,11 @@ function update () {

self.outsideBound(imgLeft, imgTop);

self.updateCanvas();
if (!self.inRealTime) {
self.updateImage();
} else {
self.updateCanvas();
}
};

self.__twoTouchStart = function (touch0, touch1) {
Expand Down Expand Up @@ -806,7 +857,11 @@ function update () {

self.outsideBound(imgLeft, imgTop);

self.updateCanvas();
if (!self.inRealTime) {
self.updateImage();
} else {
self.updateCanvas();
}
};

self.__xtouchEnd = function () {
Expand Down
2 changes: 1 addition & 1 deletion dist/we-cropper.min.js

Large diffs are not rendered by default.

13 changes: 8 additions & 5 deletions dist/we-cropper.wxml
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<template name="we-cropper">
<canvas
<view style='position:absolute;top:0px;width:{{width}}px;height:{{height}}px;background-color: rgba(0, 0, 0, 0.8);'>
<image wx:if="{{!inRealTime}}" src="{{cropperImageSrc}}" style="top:{{imageTop}}px;left:{{imageLeft}}px; width:{{imageWidth}}px;height:{{imageHeight}}px;position:absolute;"></image>
<canvas
class="cropper"
disable-scroll="true"
bindtouchstart="touchStart"
bindtouchstart="touchStart"
bindtouchmove="touchMove"
bindtouchend="touchEnd"
style="width:{{width}}px;height:{{height}}px;background-color: rgba(0, 0, 0, 0.8)"
style="width:{{width}}px;height:{{height}}px;"
canvas-id="{{id}}">
</canvas>
</template>
</canvas>
</view>
</template>
7 changes: 7 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ canvas组件标识符(必填)
- width: `Number` 裁剪框宽度(默认 画布宽度),单位:px
- height: `Number` 裁剪框高度(默认 画布高度),单位:px

#### inRealTime

- Type: `Boolean`
- Default: `true`

是否实时在 canvas 上绘制渲染裁切后的图片

#### onReady

- Type: `Function`
Expand Down
65 changes: 60 additions & 5 deletions example/we-cropper/we-cropper.js
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,18 @@ var DEFAULT = {
tmp.cut = value;
}
},
inRealTime: {
default: true,
get: function get () {
return tmp.inRealTime
},
set: function set (value) {
if (typeof (value) !== 'boolean') {
console.error(('inRealTime:' + value + ' is invalid'));
}
tmp.inRealTime = value;
}
},
onReady: {
default: null,
get: function get () {
Expand Down Expand Up @@ -180,6 +192,7 @@ function prepare () {
var pageContext = pages[pages.length - 1];
// 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问
pageContext.wecropper = self;
self.pageContext = pageContext;
};

self.createCtx = function () {
Expand Down Expand Up @@ -622,6 +635,30 @@ function methods () {
return self
};

self.updateImage = function (isInit) {
if ( isInit === void 0 ) isInit = false;

if (self.croperTarget && isInit) {
self.pageContext.setData({
'cropperOpt.cropperImageSrc': self.croperTarget
});
}

if (!self.imgLeft || !self.imgTop) {
return
}

self.pageContext.setData({
'cropperOpt.imageLeft': self.imgLeft,
'cropperOpt.imageTop': self.imgTop,
'cropperOpt.imageWidth': self.scaleWidth,
'cropperOpt.imageHeight': self.scaleHeight

});

return self
};

self.pushOrign = function (src) {
self.src = src;

Expand All @@ -633,7 +670,7 @@ function methods () {
var innerAspectRadio = res.width / res.height;

self.croperTarget = res.path;

if (innerAspectRadio < width / height) {
self.rectX = x;
self.baseWidth = width;
Expand All @@ -651,7 +688,11 @@ function methods () {
self.scaleWidth = self.baseWidth;
self.scaleHeight = self.baseHeight;

self.updateCanvas();
if (!self.inRealTime) {
self.updateImage(true);
} else {
self.updateCanvas();
}

isFunction(self.onImageLoad) && self.onImageLoad(self.ctx, self);
}
Expand All @@ -677,6 +718,8 @@ function methods () {
var args = [], len = arguments.length;
while ( len-- ) args[ len ] = arguments[ len ];

self.updateCanvas();

var ARG_TYPE = toString.call(args[0]);
var fn = args[args.length - 1];

Expand Down Expand Up @@ -760,7 +803,11 @@ function update () {
var xMove, yMove;
// 计算单指移动的距离
if (self.touchended) {
return self.updateCanvas()
if (!self.inRealTime) {
return self.updateImage()
} else {
return self.updateCanvas()
}
}
xMove = Math.round(touch.x - self.touchX0);
yMove = Math.round(touch.y - self.touchY0);
Expand All @@ -770,7 +817,11 @@ function update () {

self.outsideBound(imgLeft, imgTop);

self.updateCanvas();
if (!self.inRealTime) {
self.updateImage();
} else {
self.updateCanvas();
}
};

self.__twoTouchStart = function (touch0, touch1) {
Expand Down Expand Up @@ -806,7 +857,11 @@ function update () {

self.outsideBound(imgLeft, imgTop);

self.updateCanvas();
if (!self.inRealTime) {
self.updateImage();
} else {
self.updateCanvas();
}
};

self.__xtouchEnd = function () {
Expand Down
13 changes: 8 additions & 5 deletions example/we-cropper/we-cropper.wxml
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
<template name="we-cropper">
<canvas
<view style='position:absolute;top:0px;width:{{width}}px;height:{{height}}px;background-color: rgba(0, 0, 0, 0.8);'>
<image wx:if="{{!inRealTime}}" src="{{cropperImageSrc}}" style="top:{{imageTop}}px;left:{{imageLeft}}px; width:{{imageWidth}}px;height:{{imageHeight}}px;position:absolute;"></image>
<canvas
class="cropper"
disable-scroll="true"
bindtouchstart="touchStart"
bindtouchstart="touchStart"
bindtouchmove="touchMove"
bindtouchend="touchEnd"
style="width:{{width}}px;height:{{height}}px;background-color: rgba(0, 0, 0, 0.8)"
style="width:{{width}}px;height:{{height}}px;"
canvas-id="{{id}}">
</canvas>
</template>
</canvas>
</view>
</template>
12 changes: 12 additions & 0 deletions src/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@ export default {
tmp.cut = value
}
},
inRealTime: {
default: true,
get () {
return tmp.inRealTime
},
set (value) {
if (typeof (value) !== 'boolean') {
console.error(('inRealTime:' + value + ' is invalid'))
}
tmp.inRealTime = value
}
},
onReady: {
default: null,
get () {
Expand Down
30 changes: 29 additions & 1 deletion src/methods.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,28 @@ export default function methods () {
return self
}

self.updateImage = (isInit = false) => {
if (self.croperTarget && isInit) {
self.pageContext.setData({
'cropperOpt.cropperImageSrc': self.croperTarget
})
}

if (!self.imgLeft || !self.imgTop) {
return
}

self.pageContext.setData({
'cropperOpt.imageLeft': self.imgLeft,
'cropperOpt.imageTop': self.imgTop,
'cropperOpt.imageWidth': self.scaleWidth,
'cropperOpt.imageHeight': self.scaleHeight

})

return self
}

self.pushOrign = (src) => {
self.src = src

Expand Down Expand Up @@ -50,7 +72,11 @@ export default function methods () {
self.scaleWidth = self.baseWidth
self.scaleHeight = self.baseHeight

self.updateCanvas()
if (!self.inRealTime) {
self.updateImage(true)
} else {
self.updateCanvas()
}

isFunction(self.onImageLoad) && self.onImageLoad(self.ctx, self)
}
Expand All @@ -71,6 +97,8 @@ export default function methods () {
}

self.getCropperImage = (...args) => {
self.updateCanvas()

const ARG_TYPE = toString.call(args[0])
const fn = args[args.length - 1]

Expand Down
1 change: 1 addition & 0 deletions src/prepare.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export default function prepare () {
const pageContext = pages[pages.length - 1]
// 把this依附在Page上下文的wecropper属性上,便于在page钩子函数中访问
pageContext.wecropper = self
self.pageContext = pageContext
}

self.createCtx = () => {
Expand Down
Loading