MaLiang
MaLiang copied to clipboard
渐进恢复数据
新开 issue,渐进恢复数据问题集中在这里讨论
哈哈哈,这个响应速度可以呀。 https://github.com/Harley-xk/MaLiang/issues/34
自己给自己加班中。。。
哈哈哈。。。 +1 。。。 有什么好的思路么?
@liufsd 这几个属性的访问权限忘了调整了,我来改一下。要对单个线条进行渐进恢复的话,需要深入到LineStrip
的 lines
属性了,思路是一样的。
不过现在 redraw()
函数确实存在性能问题,画布内容数量多的时候重绘的效率比较低(可以在缩放画布上测试,现在缩放的时候是每一帧调用 redraw
的),要避免高频调用。暂时还没有好的优化的办法,需要深入研究一下 Metal 的高阶用法。
是的。之前openGL的方案,当时体验这个效果的思路大概也是这样的,内容不多的话,好像也还可以的吧。
还有就是,如果操作数据是在子线程,redraw() 又在主线程,这样切换线程性能开销也是个问题。
嗯, 内容不多的话, 适当控制一下频率(比如每秒十次), 问题应该不大
redraw
要把内容提交到缓冲区,只能在主线程操作。数据量不大的话,可以考虑把数据操作也放在主线程,或许可以稍微提升一些速度。
不过从目前调试的结果来看,性能瓶颈主要在 buffer 的创建和释放上。
嗯 好像这样的话,每次 canvas.data.elements拿到的数据都是上一次的数据加上接下来要话的元素集合。然后再调用redraw() , 不知道会不会有问题,毕竟相当于同一个坐标掉被绘制了很多次。
内容放在缓冲区?是指?
Metal 层要把需要显示的像素数据提交到缓冲区才能在屏幕上显示,redraw
会触发这一步操作,所以也要在主线程调用。
嗯 听下来:大概思路是:每隔一段时间取一下数据到 canvas.data.elements
上,然后再调用 canvas.redraw()
差不多是这样,其实恢复数据和绘制过程是很类似的,一个是通过用户手势触发相关操作,向 canvas.data
中添加数据,一个是由我们的程序主动向其中添加数据,最终结果是一样的。
用这种思路,甚至可以添加一些原本不是用户绘制的内容,这个就可以看上层 App 的发挥了。
嗯,是的,只是程序每隔一段时间绘制一个线条。
拉取了你刚才提交的代码’ $0.brush‘ 编译不过。
改过来了
在 2019年5月11日,16:48,liupeng [email protected] 写道:
嗯,是的,只是程序每隔一段时间绘制一个线条。 拉取了你刚才提交的代码’ $0.brush‘ 编译不过。 https://user-images.githubusercontent.com/1910405/57567482-9cc38680-740c-11e9-9806-5167026ffdd8.png — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/Harley-xk/MaLiang/issues/43#issuecomment-491492838, or mute the thread https://github.com/notifications/unsubscribe-auth/ADBLWHOU46SOYDK4ZB3HOTLPU2B6NANCNFSM4HMHS6KA.
嗯 看到了的,写了个简单的实现,效果不是很理想:
let elements: [CanvasElement] = (content.lineStrips + content.chartlets).sorted(by: { $0.index < $1.index})
let list = elements.chunks(3)
for frames in list {
sleep(1)
canvas.data.elements += frames
DispatchQueue.main.async {
/// redraw must be call on main thread
canvas.redraw()
}
}
extension Array {
func chunks(_ chunkSize: Int) -> [[Element]] {
return stride(from: 0, to: self.count, by: chunkSize).map {
Array(self[$0..<Swift.min($0 + chunkSize, self.count)])
}
}
}
有其他什么好的思路么?
感觉都是一个一个线条直接“蹦”出来的,不是很理想~
粒度再细一些,对每一个linestrip的数据也进行渐进恢复,另外时间间隔可以再短一些
在 2019年5月11日,17:14,liupeng [email protected] 写道:
感觉都是一个一个线条直接“蹦”出来的,不是很理想~
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.
啊? 我看你做的数据源不是: content.lineStrips + content.chartlets 还加了排序的么? 能在例子中添加一个简单实现不? 我看一下你那边的思路。
linestrip 的 lines 数组中的 MLLine 也用定时器一个一个添进去
发自我的 iPhone
在 2019年5月11日,18:42,liupeng [email protected] 写道:
啊? 我看你做的数据源不是: content.lineStrips + content.chartlets 还加了排序的么? 能在例子中添加一个简单实现不? 我看一下你那边的思路。
— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub, or mute the thread.
定时器?
不一定用定时器,像你之前用 sleep 也没什么问题。 主要是要对每一条 LineStrip
本身进行渐进恢复,原来直接操作 canvas.data.elements
是没有这么细的,elements 里面每一个元素都是一条完整的线,不能直接添加进去。一个 LineStrip
由 n 多个 MLLine
组成,应该把每一个 LineStrip
的 lines
属性里面的 MLLine
元素拿出来,也用逐渐添加的方式添加回去,同时进行重绘。一条线恢复完了之后下一条线继续这么做,这样一条线才是逐渐画出来的。你可以看一下 Canvas
里面 pushPoint
和 render(lines:)
两个方法的实现。
我后面写一个专门给渐进恢复数据用的重绘方法。现在的重绘是针对清空、缩放还有平移这种会导致整个画布的内容发生变化的场景用的,所以每次都会清空画布之后对所有数据进行重绘,所以效率比较低。渐进恢复数据的时候其实不需要清空画布全部重新绘制,可以只绘制新增的内容,这样就不会有性能问题了。
嗯,好,什么时候更新呢?很期待您的更新哦,感觉是一个比较炫酷的功能。 我刚才也只是先尝试体验一下~发现那样做确实效果不好。
要晚一些,最近事情比较多
哈哈哈哈 好的 看来大家最近 都一样…
有进展了么? 哈哈哈😝~
😅还没有空出来
还记得之前跟你讨论过的么? 如果是把大画板上画的数据恢复到一个小的画板上么? 似乎不行,因为对应的坐标点在小的画板上已经超出view的范围了的。所以需要对每条mlline进行缩放。???
你可以下载我之前写的App: Soul Sketch 体验一下这个场景,当时基于的OpenGL的方案。
应该是在恢复之前检查保存文件中的画布大小属性,然后重设当前画板的大小之后再执行数据恢复的操作。
画布尺寸保存在 content 文件里面的 size
字段。
不过恢复数据的时候也要看情况,针对固定大小的画板,应该是是重设尺寸,如果是可滚动的画板,应该是重设 content size
。
重设尺寸这一步目前可以在自定义的数据恢复逻辑里面做。在 MaLiang 内置的 DataImporter 里面暂时还没有实现,需要考虑一个完善的策略。