From b7cbe089ae03e28781b45893d808f9732e349943 Mon Sep 17 00:00:00 2001 From: lx Date: Tue, 2 Nov 2021 14:23:21 +0800 Subject: [PATCH] fixed bug --- build.bat | 2 +- .../SimulationTurePageAnimation.dart | 1244 ++++++++--------- lib/model/ReadModel.dart | 40 +- lib/view/book/Menu.dart | 8 +- lib/view/book/PageContentRender.dart | 8 +- lib/view/newBook/ReaderPageManager.dart | 3 +- lib/view/person/Me.dart | 7 +- lib/view/route/empty_page_route.dart | 22 - lib/view/route/fade_page_route.dart | 27 - lib/view/route/pop_route.dart | 32 - lib/widgets/BooksWidget.dart | 2 +- 11 files changed, 663 insertions(+), 732 deletions(-) delete mode 100644 lib/view/route/empty_page_route.dart delete mode 100644 lib/view/route/fade_page_route.dart delete mode 100644 lib/view/route/pop_route.dart diff --git a/build.bat b/build.bat index 11bc97d..b6b6b32 100644 --- a/build.bat +++ b/build.bat @@ -1,2 +1,2 @@ -flutter build apk --obfuscate --split-debug-info=HLQ_Struggle --target-platform android-arm64 --split-per-abi --build-name=4.1.9 --build-number=3 --bundle-sksl-path flutter_01.sksl.json +flutter build apk --obfuscate --split-debug-info=HLQ_Struggle --target-platform android-arm64 --split-per-abi --build-name=4.2.0 --build-number=3 --bundle-sksl-path flutter_01.sksl.json diff --git a/lib/animation/SimulationTurePageAnimation.dart b/lib/animation/SimulationTurePageAnimation.dart index 0748f97..64a5432 100644 --- a/lib/animation/SimulationTurePageAnimation.dart +++ b/lib/animation/SimulationTurePageAnimation.dart @@ -1,622 +1,622 @@ -// import 'dart:math' as math; -// import 'dart:ui'; -// import 'package:book/animation/AnimationControllerWithListenerNumber.dart'; -// import 'package:book/animation/BaseAnimationPage.dart'; -// import 'package:book/common/Screen.dart'; -// import 'package:book/view/newBook/ReaderPageManager.dart'; -// import 'package:vector_math/vector_math_64.dart' as v; - -// import 'package:flutter/material.dart'; - -// /// 仿真翻页动画 /// -// class SimulationTurnPageAnimation extends BaseAnimationPage { -// bool isStartAnimation = false; -// Offset minDragDistance = Offset(10, 10); - -// Path mTopPagePath = Path(); -// Path mBottomPagePath = Path(); -// Path mTopBackAreaPagePath = Path(); -// Path mShadowPath = Path(); - -// double mCornerX = 1; // 拖拽点对应的页脚 -// double mCornerY = 1; - -// bool mIsRTandLB; // 是否属于右上左下 - -// Offset mBezierStart1 = new Offset(0, 0); // 贝塞尔曲线起始点 -// Offset mBezierControl1 = new Offset(0, 0); // 贝塞尔曲线控制点 -// Offset mBezierVertex1 = new Offset(0, 0); // 贝塞尔曲线顶点 -// Offset mBezierEnd1 = new Offset(0, 0); // 贝塞尔曲线结束点 - -// Offset mBezierStart2 = new Offset(0, 0); // 另一条贝塞尔曲线 -// Offset mBezierControl2 = new Offset(0, 0); -// Offset mBezierVertex2 = new Offset(0, 0); -// Offset mBezierEnd2 = new Offset(0, 0); - -// double mMiddleX; -// double mMiddleY; -// double mDegrees; -// double mTouchToCornerDis; - -// double mMaxLength; - -// TextPainter textPainter = TextPainter(textDirection: TextDirection.ltr); - -// bool isTurnToNext = false; -// bool isConfirmAnimation=false; - -// Tween currentAnimationTween; -// Animation currentAnimation; - -// AnimationStatusListener statusListener; - -// void calBezierPoint() { -// mMiddleX = (mTouch.dx + mCornerX) / 2; -// mMiddleY = (mTouch.dy + mCornerY) / 2; - -// mMaxLength = math -// .sqrt(math.pow(currentSize.width, 2) + math.pow(currentSize.height, 2)); - -// mBezierControl1 = Offset( -// mMiddleX - -// (mCornerY - mMiddleY) * -// (mCornerY - mMiddleY) / -// (mCornerX - mMiddleX), -// mCornerY.toDouble()); - -// double f4 = mCornerY - mMiddleY; -// if (f4 == 0) { -// mBezierControl2 = Offset(mCornerX.toDouble(), -// mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1); -// } else { -// mBezierControl2 = Offset( -// mCornerX.toDouble(), -// mMiddleY - -// (mCornerX - mMiddleX) * -// (mCornerX - mMiddleX) / -// (mCornerY - mMiddleY)); -// } - -// mBezierStart1 = Offset( -// mBezierControl1.dx - (mCornerX - mBezierControl1.dx) / 2, -// mCornerY.toDouble()); - -// // 当mBezierStart1.x < 0或者mBezierStart1.x > 480时 -// // 如果继续翻页,会出现BUG故在此限制 -// if (mTouch.dx > 0 && mTouch.dx < currentSize.width) { -// if (mBezierStart1.dx < 0 || mBezierStart1.dx > currentSize.width) { -// if (mBezierStart1.dx < 0) { -// mBezierStart1 = -// Offset(currentSize.width - mBezierStart1.dx, mBezierStart1.dy); -// } - -// double f1 = (mCornerX - mTouch.dx).abs(); -// double f2 = currentSize.width * f1 / mBezierStart1.dx; -// mTouch = Offset((mCornerX - f2).abs(), mTouch.dy); - -// double f3 = -// (mCornerX - mTouch.dx).abs() * (mCornerY - mTouch.dy).abs() / f1; -// mTouch = Offset((mCornerX - f2).abs(), (mCornerY - f3).abs()); - -// mMiddleX = (mTouch.dx + mCornerX) / 2; -// mMiddleY = (mTouch.dy + mCornerY) / 2; - -// mBezierControl1 = Offset( -// mMiddleX - -// (mCornerY - mMiddleY) * -// (mCornerY - mMiddleY) / -// (mCornerX - mMiddleX), -// mCornerY); - -// double f5 = mCornerY - mMiddleY; -// if (f5 == 0) { -// mBezierControl2 = Offset(mCornerX, -// mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1); -// } else { -// mBezierControl2 = Offset( -// mCornerX, -// mMiddleY - -// (mCornerX - mMiddleX) * -// (mCornerX - mMiddleX) / -// (mCornerY - mMiddleY)); -// } - -// mBezierStart1 = Offset( -// mBezierControl1.dx - (mCornerX - mBezierControl1.dx) / 2, -// mBezierStart1.dy); -// } -// } - -// mBezierStart2 = Offset(mCornerX.toDouble(), -// mBezierControl2.dy - (mCornerY - mBezierControl2.dy) / 2); - -// mTouchToCornerDis = math.sqrt(math.pow((mTouch.dx - mCornerX), 2) + -// math.pow((mTouch.dy - mCornerY), 2)); - -// mBezierEnd1 = -// getCross(mTouch, mBezierControl1, mBezierStart1, mBezierStart2); -// mBezierEnd2 = -// getCross(mTouch, mBezierControl2, mBezierStart1, mBezierStart2); - -// mBezierVertex1 = Offset( -// (mBezierStart1.dx + 2 * mBezierControl1.dx + mBezierEnd1.dx) / 4, -// (2 * mBezierControl1.dy + mBezierStart1.dy + mBezierEnd1.dy) / 4); - -// mBezierVertex2 = Offset( -// (mBezierStart2.dx + 2 * mBezierControl2.dx + mBezierEnd2.dx) / 4, -// (2 * mBezierControl2.dy + mBezierStart2.dy + mBezierEnd2.dy) / 4); -// } - -// /// 获取交点 /// -// Offset getCross(Offset p1, Offset p2, Offset p3, Offset p4) { -// // 二元函数通式: y=kx+b(k是斜率) -// double k1 = (p2.dy - p1.dy) / (p2.dx - p1.dx); -// double b1 = ((p1.dx * p2.dy) - (p2.dx * p1.dy)) / (p1.dx - p2.dx); - -// double k2 = (p4.dy - p3.dy) / (p4.dx - p3.dx); -// double b2 = ((p3.dx * p4.dy) - (p4.dx * p3.dy)) / (p3.dx - p4.dx); - -// return Offset((b2 - b1) / (k1 - k2), k1 * ((b2 - b1) / (k1 - k2)) + b1); -// } - -// /// 计算拖拽点对应的拖拽脚 /// -// void calcCornerXY(double x, double y) { -// if (x <= currentSize.width / 2) { -// mCornerX = 0; -// } else { -// mCornerX = currentSize.width; -// } -// if (y <= currentSize.height / 2) { -// mCornerY = 0; -// } else { -// mCornerY = currentSize.height; -// } - -// if ((mCornerX == 0 && mCornerY == currentSize.height) || -// (mCornerX == currentSize.width && mCornerY == 0)) { -// mIsRTandLB = true; -// } else { -// mIsRTandLB = false; -// } -// } - -// @override -// void onTouchEvent(TouchEvent event) { -// if (event.touchPos != null) { -// mTouch = event.touchPos; -// } - -// switch (event.action) { -// case TouchEvent.ACTION_DOWN: -// calcCornerXY(mTouch.dx, mTouch.dy); -// break; -// case TouchEvent.ACTION_MOVE: -// isTurnToNext = mTouch.dx - mCornerX < 0; -// if ((!isTurnToNext && isCanGoPre()) || -// (isTurnToNext && isCanGoNext())) { -// isStartAnimation = true; -// } -// break; -// case TouchEvent.ACTION_UP: -// case TouchEvent.ACTION_CANCEL: -// if ((!isTurnToNext && isCanGoPre()) || -// (isTurnToNext && isCanGoNext())) { -// isStartAnimation = true; -// } -// break; -// default: -// break; -// } - -// calBezierPoint(); -// } - -// @override -// void onDraw(Canvas canvas) { -// if (isStartAnimation && (mTouch.dx != 0 && mTouch.dy != 0)) { -// drawTopPageCanvas(canvas); -// drawBottomPageCanvas(canvas); -// drawTopPageBackArea(canvas); -// } else { -// var targetPicture=readerViewModel?.getCurrentPage()?.pagePicture; -// if(targetPicture!=null) { -// canvas.drawPicture(targetPicture); -// } -// } - -// isStartAnimation = false; -// } - -// /// 画在最顶上的那页 /// -// void drawTopPageCanvas(Canvas canvas) { -// mTopPagePath.reset(); - -// mTopPagePath.moveTo(mCornerX == 0 ? currentSize.width : 0, mCornerY); -// mTopPagePath.lineTo(mBezierStart1.dx, mBezierStart1.dy); -// mTopPagePath.quadraticBezierTo( -// mBezierControl1.dx, mBezierControl1.dy, mBezierEnd1.dx, mBezierEnd1.dy); -// mTopPagePath.lineTo(mTouch.dx, mTouch.dy); -// mTopPagePath.lineTo(mBezierEnd2.dx, mBezierEnd2.dy); -// mTopPagePath.quadraticBezierTo(mBezierControl2.dx, mBezierControl2.dy, -// mBezierStart2.dx, mBezierStart2.dy); -// mTopPagePath.lineTo(mCornerX, mCornerY == 0 ? currentSize.height : 0); -// mTopPagePath.lineTo(mCornerX == 0 ? currentSize.width : 0, -// mCornerY == 0 ? currentSize.height : 0); -// mTopPagePath.close(); - -// /// 去掉PATH圈在屏幕外的区域,减少GPU使用 -// mTopPagePath = Path.combine( -// PathOperation.intersect, -// Path() -// ..moveTo(0, 0) -// ..lineTo(currentSize.width, 0) -// ..lineTo(currentSize.width, currentSize.height) -// ..lineTo(0, currentSize.height) -// ..close(), -// mTopPagePath); - -// canvas.save(); - -// // canvas.drawImageRect( -// // readerViewModel.getCurrentPage().pageImage, -// // Offset.zero & currentSize, -// // Offset.zero & currentSize, -// // Paint()..isAntiAlias = true); -// canvas.drawPicture(readerViewModel.getCurrentPage().pagePicture); - -// drawTopPageShadow(canvas); - -// canvas.restore(); -// } - -// /// 画顶部页的阴影 /// -// void drawTopPageShadow(Canvas canvas) { -// Path shadowPath = Path(); - -// int dx = mCornerX == 0 ? 5 : -5; -// int dy = mCornerY == 0 ? 5 : -5; - -// shadowPath = Path.combine( -// PathOperation.intersect, -// Path() -// ..moveTo(0, 0) -// ..lineTo(currentSize.width, 0) -// ..lineTo(currentSize.width, currentSize.height) -// ..lineTo(0, currentSize.height) -// ..close(), -// Path() -// ..moveTo(mTouch.dx + dx, mTouch.dy + dy) -// ..lineTo(mBezierControl2.dx + dx, mBezierControl2.dy + dy) -// ..lineTo(mBezierControl1.dx + dx, mBezierControl1.dy + dy) -// ..close()); - -// canvas.drawShadow(shadowPath, Colors.black, 5, true); -// } - -// /// 画翻起来的底下那页 /// -// void drawBottomPageCanvas(Canvas canvas) { -// mBottomPagePath.reset(); -// mBottomPagePath.moveTo(mCornerX, mCornerY); -// mBottomPagePath.lineTo(mBezierStart1.dx, mBezierStart1.dy); -// mBottomPagePath.quadraticBezierTo( -// mBezierControl1.dx, mBezierControl1.dy, mBezierEnd1.dx, mBezierEnd1.dy); -// mBottomPagePath.lineTo(mBezierEnd2.dx, mBezierEnd2.dy); -// mBottomPagePath.quadraticBezierTo(mBezierControl2.dx, mBezierControl2.dy, -// mBezierStart2.dx, mBezierStart2.dy); -// mBottomPagePath.close(); - -// Path extraRegion = Path(); - -// extraRegion.reset(); -// extraRegion.moveTo(mTouch.dx, mTouch.dy); -// extraRegion.lineTo(mBezierVertex1.dx, mBezierVertex1.dy); -// extraRegion.lineTo(mBezierVertex2.dx, mBezierVertex2.dy); -// extraRegion.close(); - -// mBottomPagePath = -// Path.combine(PathOperation.difference, mBottomPagePath, extraRegion); - -// // /// 使用fillType来反选填充区域 /// -// // mBottomPagePath = mTopPagePath -// // ..addRect(Offset.zero & currentSize) -// // ..addPath(mTopBackAreaPagePath, Offset(0, 0)) -// // ..fillType = PathFillType.evenOdd; - -// /// 去掉PATH圈在屏幕外的区域,减少GPU使用 -// mBottomPagePath = Path.combine( -// PathOperation.intersect, -// Path() -// ..moveTo(0, 0) -// ..lineTo(currentSize.width, 0) -// ..lineTo(currentSize.width, currentSize.height) -// ..lineTo(0, currentSize.height) -// ..close(), -// mBottomPagePath); - -// canvas.save(); -// canvas.clipPath(mBottomPagePath, doAntiAlias: false); -// // canvas.drawPaint(Paint()..color = Color(0xfffff2cc)); -// // canvas.drawImageRect( -// // isTurnToNext?readerViewModel.getNextPage().pageImage:readerViewModel.getPrePage().pageImage, -// // Offset.zero & currentSize, -// // Offset.zero & currentSize, -// // Paint() -// // ..isAntiAlias = true -// // ..blendMode = BlendMode.srcATop); -// canvas.drawPicture(isTurnToNext?readerViewModel.getNextPage().pagePicture:readerViewModel.getPrePage().pagePicture); -// // -// drawBottomPageShadow(canvas); - -// canvas.restore(); -// } - -// /// 画底下那页的阴影 /// -// void drawBottomPageShadow(Canvas canvas) { -// double left; -// double right; - -// Gradient shadowGradient; -// if (mIsRTandLB) { -// //左下及右上 -// left = 0; -// right = mTouchToCornerDis / 4; - -// shadowGradient = new LinearGradient( -// colors: [ -// Color(0xAA000000), -// Colors.transparent, -// ], -// ); -// } else { -// left = -mTouchToCornerDis / 4; -// right = 0; - -// shadowGradient = new LinearGradient( -// colors: [ -// Colors.transparent, -// Color(0xAA000000), -// ], -// ); -// } - -// canvas.translate(mBezierStart1.dx, mBezierStart1.dy); -// canvas.rotate(math.atan2( -// mBezierControl1.dx - mCornerX, mBezierControl2.dy - mCornerY)); - -// var shadowPaint = Paint() -// ..isAntiAlias = false -// ..style = PaintingStyle.fill //填充 -// ..shader = shadowGradient -// .createShader(Rect.fromLTRB(left, 0, right, mMaxLength)); - -// canvas.drawRect(Rect.fromLTRB(left, 0, right, mMaxLength), shadowPaint); -// } - -// /// 画在最顶上的那页的翻转过来的部分 /// -// /// 仿真翻页中性能损失最大的部分,注释掉drawTopPageBackArea能保证绘制会在16ms以内,但是去掉注释,部分情况甚至会到40+ -// /// 盲猜是过于复杂的图层处理导致的(Flutter的图层处理性能还是不如原生啊……但是好像图层绘制性能很强大,好像甚至优于原生) -// void drawTopPageBackArea(Canvas canvas) { -// mBottomPagePath.reset(); -// mBottomPagePath.moveTo(mCornerX, mCornerY); -// mBottomPagePath.lineTo(mBezierStart1.dx, mBezierStart1.dy); -// mBottomPagePath.quadraticBezierTo( -// mBezierControl1.dx, mBezierControl1.dy, mBezierEnd1.dx, mBezierEnd1.dy); -// mBottomPagePath.lineTo(mTouch.dx, mTouch.dy); -// mBottomPagePath.lineTo(mBezierEnd2.dx, mBezierEnd2.dy); -// mBottomPagePath.quadraticBezierTo(mBezierControl2.dx, mBezierControl2.dy, -// mBezierStart2.dx, mBezierStart2.dy); -// mBottomPagePath.close(); - -// Path tempBackAreaPath = Path(); - -// tempBackAreaPath.reset(); -// tempBackAreaPath.moveTo(mBezierVertex1.dx, mBezierVertex1.dy); -// tempBackAreaPath.lineTo(mBezierVertex2.dx, mBezierVertex2.dy); -// tempBackAreaPath.lineTo(mTouch.dx, mTouch.dy); -// tempBackAreaPath.close(); - -// if (tempBackAreaPath == null || mBottomPagePath == null) { -// return; -// } - -// /// 取path 相交部分 /// -// mTopBackAreaPagePath = Path.combine( -// PathOperation.intersect, tempBackAreaPath, mBottomPagePath); - -// /// 去掉PATH圈在屏幕外的区域,减少GPU使用 -// mTopBackAreaPagePath = Path.combine( -// PathOperation.intersect, -// Path() -// ..moveTo(0, 0) -// ..lineTo(currentSize.width, 0) -// ..lineTo(currentSize.width, currentSize.height) -// ..lineTo(0, currentSize.height) -// ..close(), -// mTopBackAreaPagePath); - -// canvas.save(); - -// canvas.clipPath(mTopBackAreaPagePath); -// canvas.drawPaint(Paint()..color = readerViewModel.bgPaint.color); - -// canvas.save(); - -// mTopBackAreaPagePath.getBounds(); - -// canvas.translate(mBezierControl1.dx, mBezierControl1.dy); - -// /// 矩阵公式:α表示翻转页面和边的夹角 -// /// https://juejin.im/post/5a32ade0f265da43252954b2 -// /// -// /// -(1-2sin(a)^2 ) 2sin(a)cos(a) 0 -// /// 2sin(a)cos(a) 1-2sin(a)^2 0 -// /// 0 0 1 - -// double dis = math.sqrt(math.pow((mCornerX - mBezierControl1.dx), 2) + -// math.pow((mBezierControl2.dy - mCornerY), 2)); -// double sinAngle = (mCornerX - mBezierControl1.dx) / dis; -// double cosAngle = (mBezierControl2.dy - mCornerY) / dis; - -// Matrix4 matrix4 = Matrix4.columns( -// v.Vector4( -// -(1 - 2 * sinAngle * sinAngle), 2 * sinAngle * cosAngle, 0, 0), -// v.Vector4(2 * sinAngle * cosAngle, (1 - 2 * sinAngle * sinAngle), 0, 0), -// v.Vector4(0, 0, 1, 0), -// v.Vector4(0, 0, 0, 1)); - -// matrix4.translate(-mBezierControl1.dx, -mBezierControl1.dy); -// canvas.transform(matrix4.storage); - -// /// 用image处理有奇效……原因未知,好像是picture是保存了绘制信息的原因,所以像这种n次平移->翻转->半透明图层叠加->裁剪->加阴影 的复杂操作处理不过来 -// /// image相对简单,就是张图片,处理了就处理了,不会留下需要保存的信息 -// /// 反正是一个半透明处理的,所以对清晰度没要求,所以这里用image绘制 -// /// 我个人的猜测……求精通底层的大佬解惑 -// canvas.drawImageRect( -// readerViewModel.cur(), -// Offset.zero & currentSize, -// Offset.zero & currentSize, -// Paint()..isAntiAlias = true); -// // canvas.drawImage(configManager.currentPageImage, Offset.zero, Paint()..isAntiAlias=true); -// // canvas.drawPicture(configManager.currentPagePicture); -// // canvas.drawPaint(Paint()..color = Color(0xCCFFFFFF)); -// // canvas.drawPaint(Paint()..color =Colors.blue); -// canvas.drawPaint(Paint()..color = Color(readerViewModel.bgPaint.color.value& 0xAAFFFFFF)); -// // canvas.drawPaint(Paint()..color = Color(0xAAfff2cc)); - -// canvas.restore(); - -// drawTopPageBackAreaShadow(canvas); - -// canvas.restore(); -// } - -// /// 画翻起页的阴影 /// -// void drawTopPageBackAreaShadow(Canvas canvas) { -// double i = (mBezierStart1.dx + mBezierControl1.dx) / 2; -// double f1 = (i - mBezierControl1.dx).abs(); -// double i1 = (mBezierStart2.dy + mBezierControl2.dy) / 2; -// double f2 = (i1 - mBezierControl2.dy).abs(); -// double f3 = math.min(f1, f2); - -// double left; -// double right; -// double width; -// if (mIsRTandLB) { -// left = (mBezierStart1.dx - 1); -// right = (mBezierStart1.dx + f3 + 1); -// width = right - left; -// } else { -// left = (mBezierStart1.dx - f3 - 1); -// right = (mBezierStart1.dx + 1); -// width = left - right; -// } - -// canvas.translate(mBezierStart1.dx, mBezierStart1.dy); -// canvas.rotate(math.atan2( -// mBezierControl1.dx - mCornerX, mBezierControl2.dy - mCornerY)); - -// Gradient shadowGradient = new LinearGradient( -// colors: [ -// Colors.transparent, -// Color(0xAA000000), -// ], -// ); - -// var shadowPaint = Paint() -// ..isAntiAlias = true -// ..style = PaintingStyle.fill //填充 -// ..shader = -// shadowGradient.createShader(Rect.fromLTRB(0, 0, width, mMaxLength)); - -// canvas.drawRect(Rect.fromLTRB(0, 0, width, mMaxLength), shadowPaint); -// } - -// @override -// Animation getCancelAnimation( -// AnimationController controller, GlobalKey canvasKey) { -// if ((!isTurnToNext && !isCanGoPre()) || (isTurnToNext && !isCanGoNext())) { -// return null; -// } -// isConfirmAnimation=false; - -// if (currentAnimation == null) { -// currentAnimationTween = Tween(begin: Offset.zero, end: Offset.zero); - -// currentAnimation = currentAnimationTween.animate(controller); -// } - -// currentAnimationTween.begin = mTouch; -// currentAnimationTween.end = Offset(mCornerX, mCornerY); - -// return currentAnimation; -// } - -// @override -// Animation getConfirmAnimation( -// AnimationController controller, GlobalKey canvasKey) { -// if ((!isTurnToNext && !isCanGoPre()) || (isTurnToNext && !isCanGoNext())) { -// return null; -// } -// isConfirmAnimation=true; - -// if (currentAnimation == null) { -// currentAnimationTween = Tween(begin: Offset.zero, end: Offset.zero); -// currentAnimation = currentAnimationTween.animate(controller); -// } - -// if(statusListener==null){ -// statusListener=(status) { -// switch (status) { -// case AnimationStatus.dismissed: -// break; -// case AnimationStatus.completed: -// if(isConfirmAnimation){ -// if (isTurnToNext) { -// // readerViewModel.nextPage(); -// } else { -// // readerViewModel.prePage(); -// } -// canvasKey.currentContext.findRenderObject().markNeedsPaint(); -// } -// break; -// case AnimationStatus.forward: -// case AnimationStatus.reverse: -// break; -// } -// }; - -// currentAnimation.addStatusListener(statusListener); -// } - -// if(statusListener!=null&&!(controller as AnimationControllerWithListenerNumber).statusListeners.contains(statusListener)){ -// currentAnimation.addStatusListener(statusListener); -// } - -// currentAnimationTween.begin = mTouch; -// currentAnimationTween.end = Offset( -// mCornerX == 0 ? currentSize.width * 3 / 2 : 0 - currentSize.width / 2, -// mCornerY == 0 ? 0 : currentSize.height); - -// // if (!controller.isCompleted) { -// // -// // } -// return currentAnimation; -// } - -// @override -// Simulation getFlingAnimationSimulation( -// AnimationController controller, DragEndDetails details) { -// return null; -// } - -// @override -// bool isCancelArea() { - -// return isTurnToNext?(mTouch.dx).abs() > (currentSize.width / 4*3):(mTouch.dx).abs() < (currentSize.width / 4); -// } - -// @override -// bool isConfirmArea() { -// return isTurnToNext?(mTouch.dx).abs() < (currentSize.width / 4*3):(mTouch.dx).abs() > (currentSize.width / 4); -// } -// } +import 'dart:math' as math; +import 'dart:ui'; +import 'package:book/animation/AnimationControllerWithListenerNumber.dart'; +import 'package:book/animation/BaseAnimationPage.dart'; +import 'package:book/common/Screen.dart'; +import 'package:book/view/newBook/ReaderPageManager.dart'; +import 'package:vector_math/vector_math_64.dart' as v; + +import 'package:flutter/material.dart'; + +/// 仿真翻页动画 /// +class SimulationTurnPageAnimation extends BaseAnimationPage { + bool isStartAnimation = false; + Offset minDragDistance = Offset(10, 10); + + Path mTopPagePath = Path(); + Path mBottomPagePath = Path(); + Path mTopBackAreaPagePath = Path(); + Path mShadowPath = Path(); + + double mCornerX = 1; // 拖拽点对应的页脚 + double mCornerY = 1; + + bool mIsRTandLB; // 是否属于右上左下 + + Offset mBezierStart1 = new Offset(0, 0); // 贝塞尔曲线起始点 + Offset mBezierControl1 = new Offset(0, 0); // 贝塞尔曲线控制点 + Offset mBezierVertex1 = new Offset(0, 0); // 贝塞尔曲线顶点 + Offset mBezierEnd1 = new Offset(0, 0); // 贝塞尔曲线结束点 + + Offset mBezierStart2 = new Offset(0, 0); // 另一条贝塞尔曲线 + Offset mBezierControl2 = new Offset(0, 0); + Offset mBezierVertex2 = new Offset(0, 0); + Offset mBezierEnd2 = new Offset(0, 0); + + double mMiddleX; + double mMiddleY; + double mDegrees; + double mTouchToCornerDis; + + double mMaxLength; + + TextPainter textPainter = TextPainter(textDirection: TextDirection.ltr); + + bool isTurnToNext = false; + bool isConfirmAnimation=false; + + Tween currentAnimationTween; + Animation currentAnimation; + + AnimationStatusListener statusListener; + + void calBezierPoint() { + mMiddleX = (mTouch.dx + mCornerX) / 2; + mMiddleY = (mTouch.dy + mCornerY) / 2; + + mMaxLength = math + .sqrt(math.pow(currentSize.width, 2) + math.pow(currentSize.height, 2)); + + mBezierControl1 = Offset( + mMiddleX - + (mCornerY - mMiddleY) * + (mCornerY - mMiddleY) / + (mCornerX - mMiddleX), + mCornerY.toDouble()); + + double f4 = mCornerY - mMiddleY; + if (f4 == 0) { + mBezierControl2 = Offset(mCornerX.toDouble(), + mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1); + } else { + mBezierControl2 = Offset( + mCornerX.toDouble(), + mMiddleY - + (mCornerX - mMiddleX) * + (mCornerX - mMiddleX) / + (mCornerY - mMiddleY)); + } + + mBezierStart1 = Offset( + mBezierControl1.dx - (mCornerX - mBezierControl1.dx) / 2, + mCornerY.toDouble()); + + // 当mBezierStart1.x < 0或者mBezierStart1.x > 480时 + // 如果继续翻页,会出现BUG故在此限制 + if (mTouch.dx > 0 && mTouch.dx < currentSize.width) { + if (mBezierStart1.dx < 0 || mBezierStart1.dx > currentSize.width) { + if (mBezierStart1.dx < 0) { + mBezierStart1 = + Offset(currentSize.width - mBezierStart1.dx, mBezierStart1.dy); + } + + double f1 = (mCornerX - mTouch.dx).abs(); + double f2 = currentSize.width * f1 / mBezierStart1.dx; + mTouch = Offset((mCornerX - f2).abs(), mTouch.dy); + + double f3 = + (mCornerX - mTouch.dx).abs() * (mCornerY - mTouch.dy).abs() / f1; + mTouch = Offset((mCornerX - f2).abs(), (mCornerY - f3).abs()); + + mMiddleX = (mTouch.dx + mCornerX) / 2; + mMiddleY = (mTouch.dy + mCornerY) / 2; + + mBezierControl1 = Offset( + mMiddleX - + (mCornerY - mMiddleY) * + (mCornerY - mMiddleY) / + (mCornerX - mMiddleX), + mCornerY); + + double f5 = mCornerY - mMiddleY; + if (f5 == 0) { + mBezierControl2 = Offset(mCornerX, + mMiddleY - (mCornerX - mMiddleX) * (mCornerX - mMiddleX) / 0.1); + } else { + mBezierControl2 = Offset( + mCornerX, + mMiddleY - + (mCornerX - mMiddleX) * + (mCornerX - mMiddleX) / + (mCornerY - mMiddleY)); + } + + mBezierStart1 = Offset( + mBezierControl1.dx - (mCornerX - mBezierControl1.dx) / 2, + mBezierStart1.dy); + } + } + + mBezierStart2 = Offset(mCornerX.toDouble(), + mBezierControl2.dy - (mCornerY - mBezierControl2.dy) / 2); + + mTouchToCornerDis = math.sqrt(math.pow((mTouch.dx - mCornerX), 2) + + math.pow((mTouch.dy - mCornerY), 2)); + + mBezierEnd1 = + getCross(mTouch, mBezierControl1, mBezierStart1, mBezierStart2); + mBezierEnd2 = + getCross(mTouch, mBezierControl2, mBezierStart1, mBezierStart2); + + mBezierVertex1 = Offset( + (mBezierStart1.dx + 2 * mBezierControl1.dx + mBezierEnd1.dx) / 4, + (2 * mBezierControl1.dy + mBezierStart1.dy + mBezierEnd1.dy) / 4); + + mBezierVertex2 = Offset( + (mBezierStart2.dx + 2 * mBezierControl2.dx + mBezierEnd2.dx) / 4, + (2 * mBezierControl2.dy + mBezierStart2.dy + mBezierEnd2.dy) / 4); + } + + /// 获取交点 /// + Offset getCross(Offset p1, Offset p2, Offset p3, Offset p4) { + // 二元函数通式: y=kx+b(k是斜率) + double k1 = (p2.dy - p1.dy) / (p2.dx - p1.dx); + double b1 = ((p1.dx * p2.dy) - (p2.dx * p1.dy)) / (p1.dx - p2.dx); + + double k2 = (p4.dy - p3.dy) / (p4.dx - p3.dx); + double b2 = ((p3.dx * p4.dy) - (p4.dx * p3.dy)) / (p3.dx - p4.dx); + + return Offset((b2 - b1) / (k1 - k2), k1 * ((b2 - b1) / (k1 - k2)) + b1); + } + + /// 计算拖拽点对应的拖拽脚 /// + void calcCornerXY(double x, double y) { + if (x <= currentSize.width / 2) { + mCornerX = 0; + } else { + mCornerX = currentSize.width; + } + if (y <= currentSize.height / 2) { + mCornerY = 0; + } else { + mCornerY = currentSize.height; + } + + if ((mCornerX == 0 && mCornerY == currentSize.height) || + (mCornerX == currentSize.width && mCornerY == 0)) { + mIsRTandLB = true; + } else { + mIsRTandLB = false; + } + } + + @override + void onTouchEvent(TouchEvent event) { + if (event.touchPos != null) { + mTouch = event.touchPos; + } + + switch (event.action) { + case TouchEvent.ACTION_DOWN: + calcCornerXY(mTouch.dx, mTouch.dy); + break; + case TouchEvent.ACTION_MOVE: + isTurnToNext = mTouch.dx - mCornerX < 0; + if ((!isTurnToNext && isCanGoPre()) || + (isTurnToNext && isCanGoNext())) { + isStartAnimation = true; + } + break; + case TouchEvent.ACTION_UP: + case TouchEvent.ACTION_CANCEL: + if ((!isTurnToNext && isCanGoPre()) || + (isTurnToNext && isCanGoNext())) { + isStartAnimation = true; + } + break; + default: + break; + } + + calBezierPoint(); + } + + @override + void onDraw(Canvas canvas) { + if (isStartAnimation && (mTouch.dx != 0 && mTouch.dy != 0)) { + drawTopPageCanvas(canvas); + drawBottomPageCanvas(canvas); + drawTopPageBackArea(canvas); + } else { + var targetPicture=readerViewModel?.cur(); + if(targetPicture!=null) { + canvas.drawPicture(targetPicture); + } + } + + isStartAnimation = false; + } + + /// 画在最顶上的那页 /// + void drawTopPageCanvas(Canvas canvas) { + mTopPagePath.reset(); + + mTopPagePath.moveTo(mCornerX == 0 ? currentSize.width : 0, mCornerY); + mTopPagePath.lineTo(mBezierStart1.dx, mBezierStart1.dy); + mTopPagePath.quadraticBezierTo( + mBezierControl1.dx, mBezierControl1.dy, mBezierEnd1.dx, mBezierEnd1.dy); + mTopPagePath.lineTo(mTouch.dx, mTouch.dy); + mTopPagePath.lineTo(mBezierEnd2.dx, mBezierEnd2.dy); + mTopPagePath.quadraticBezierTo(mBezierControl2.dx, mBezierControl2.dy, + mBezierStart2.dx, mBezierStart2.dy); + mTopPagePath.lineTo(mCornerX, mCornerY == 0 ? currentSize.height : 0); + mTopPagePath.lineTo(mCornerX == 0 ? currentSize.width : 0, + mCornerY == 0 ? currentSize.height : 0); + mTopPagePath.close(); + + /// 去掉PATH圈在屏幕外的区域,减少GPU使用 + mTopPagePath = Path.combine( + PathOperation.intersect, + Path() + ..moveTo(0, 0) + ..lineTo(currentSize.width, 0) + ..lineTo(currentSize.width, currentSize.height) + ..lineTo(0, currentSize.height) + ..close(), + mTopPagePath); + + canvas.save(); + +// canvas.drawImageRect( +// readerViewModel.getCurrentPage().pageImage, +// Offset.zero & currentSize, +// Offset.zero & currentSize, +// Paint()..isAntiAlias = true); + canvas.drawPicture(readerViewModel.cur()); + + drawTopPageShadow(canvas); + + canvas.restore(); + } + + /// 画顶部页的阴影 /// + void drawTopPageShadow(Canvas canvas) { + Path shadowPath = Path(); + + int dx = mCornerX == 0 ? 5 : -5; + int dy = mCornerY == 0 ? 5 : -5; + + shadowPath = Path.combine( + PathOperation.intersect, + Path() + ..moveTo(0, 0) + ..lineTo(currentSize.width, 0) + ..lineTo(currentSize.width, currentSize.height) + ..lineTo(0, currentSize.height) + ..close(), + Path() + ..moveTo(mTouch.dx + dx, mTouch.dy + dy) + ..lineTo(mBezierControl2.dx + dx, mBezierControl2.dy + dy) + ..lineTo(mBezierControl1.dx + dx, mBezierControl1.dy + dy) + ..close()); + + canvas.drawShadow(shadowPath, Colors.black, 5, true); + } + + /// 画翻起来的底下那页 /// + void drawBottomPageCanvas(Canvas canvas) { + mBottomPagePath.reset(); + mBottomPagePath.moveTo(mCornerX, mCornerY); + mBottomPagePath.lineTo(mBezierStart1.dx, mBezierStart1.dy); + mBottomPagePath.quadraticBezierTo( + mBezierControl1.dx, mBezierControl1.dy, mBezierEnd1.dx, mBezierEnd1.dy); + mBottomPagePath.lineTo(mBezierEnd2.dx, mBezierEnd2.dy); + mBottomPagePath.quadraticBezierTo(mBezierControl2.dx, mBezierControl2.dy, + mBezierStart2.dx, mBezierStart2.dy); + mBottomPagePath.close(); + + Path extraRegion = Path(); + + extraRegion.reset(); + extraRegion.moveTo(mTouch.dx, mTouch.dy); + extraRegion.lineTo(mBezierVertex1.dx, mBezierVertex1.dy); + extraRegion.lineTo(mBezierVertex2.dx, mBezierVertex2.dy); + extraRegion.close(); + + mBottomPagePath = + Path.combine(PathOperation.difference, mBottomPagePath, extraRegion); + +// /// 使用fillType来反选填充区域 /// +// mBottomPagePath = mTopPagePath +// ..addRect(Offset.zero & currentSize) +// ..addPath(mTopBackAreaPagePath, Offset(0, 0)) +// ..fillType = PathFillType.evenOdd; + + /// 去掉PATH圈在屏幕外的区域,减少GPU使用 + mBottomPagePath = Path.combine( + PathOperation.intersect, + Path() + ..moveTo(0, 0) + ..lineTo(currentSize.width, 0) + ..lineTo(currentSize.width, currentSize.height) + ..lineTo(0, currentSize.height) + ..close(), + mBottomPagePath); + + canvas.save(); + canvas.clipPath(mBottomPagePath, doAntiAlias: false); +// canvas.drawPaint(Paint()..color = Color(0xfffff2cc)); +// canvas.drawImageRect( +// isTurnToNext?readerViewModel.getNextPage().pageImage:readerViewModel.getPrePage().pageImage, +// Offset.zero & currentSize, +// Offset.zero & currentSize, +// Paint() +// ..isAntiAlias = true +// ..blendMode = BlendMode.srcATop); + canvas.drawPicture(isTurnToNext?readerViewModel.next():readerViewModel.pre()); +// + drawBottomPageShadow(canvas); + + canvas.restore(); + } + + /// 画底下那页的阴影 /// + void drawBottomPageShadow(Canvas canvas) { + double left; + double right; + + Gradient shadowGradient; + if (mIsRTandLB) { + //左下及右上 + left = 0; + right = mTouchToCornerDis / 4; + + shadowGradient = new LinearGradient( + colors: [ + Color(0xAA000000), + Colors.transparent, + ], + ); + } else { + left = -mTouchToCornerDis / 4; + right = 0; + + shadowGradient = new LinearGradient( + colors: [ + Colors.transparent, + Color(0xAA000000), + ], + ); + } + + canvas.translate(mBezierStart1.dx, mBezierStart1.dy); + canvas.rotate(math.atan2( + mBezierControl1.dx - mCornerX, mBezierControl2.dy - mCornerY)); + + var shadowPaint = Paint() + ..isAntiAlias = false + ..style = PaintingStyle.fill //填充 + ..shader = shadowGradient + .createShader(Rect.fromLTRB(left, 0, right, mMaxLength)); + + canvas.drawRect(Rect.fromLTRB(left, 0, right, mMaxLength), shadowPaint); + } + + /// 画在最顶上的那页的翻转过来的部分 /// + /// 仿真翻页中性能损失最大的部分,注释掉drawTopPageBackArea能保证绘制会在16ms以内,但是去掉注释,部分情况甚至会到40+ + /// 盲猜是过于复杂的图层处理导致的(Flutter的图层处理性能还是不如原生啊……但是好像图层绘制性能很强大,好像甚至优于原生) + void drawTopPageBackArea(Canvas canvas) { + mBottomPagePath.reset(); + mBottomPagePath.moveTo(mCornerX, mCornerY); + mBottomPagePath.lineTo(mBezierStart1.dx, mBezierStart1.dy); + mBottomPagePath.quadraticBezierTo( + mBezierControl1.dx, mBezierControl1.dy, mBezierEnd1.dx, mBezierEnd1.dy); + mBottomPagePath.lineTo(mTouch.dx, mTouch.dy); + mBottomPagePath.lineTo(mBezierEnd2.dx, mBezierEnd2.dy); + mBottomPagePath.quadraticBezierTo(mBezierControl2.dx, mBezierControl2.dy, + mBezierStart2.dx, mBezierStart2.dy); + mBottomPagePath.close(); + + Path tempBackAreaPath = Path(); + + tempBackAreaPath.reset(); + tempBackAreaPath.moveTo(mBezierVertex1.dx, mBezierVertex1.dy); + tempBackAreaPath.lineTo(mBezierVertex2.dx, mBezierVertex2.dy); + tempBackAreaPath.lineTo(mTouch.dx, mTouch.dy); + tempBackAreaPath.close(); + + if (tempBackAreaPath == null || mBottomPagePath == null) { + return; + } + + /// 取path 相交部分 /// + mTopBackAreaPagePath = Path.combine( + PathOperation.intersect, tempBackAreaPath, mBottomPagePath); + + /// 去掉PATH圈在屏幕外的区域,减少GPU使用 + mTopBackAreaPagePath = Path.combine( + PathOperation.intersect, + Path() + ..moveTo(0, 0) + ..lineTo(currentSize.width, 0) + ..lineTo(currentSize.width, currentSize.height) + ..lineTo(0, currentSize.height) + ..close(), + mTopBackAreaPagePath); + + canvas.save(); + + canvas.clipPath(mTopBackAreaPagePath); + canvas.drawPaint(Paint()..color = readerViewModel.bgPaint.color); + + canvas.save(); + + mTopBackAreaPagePath.getBounds(); + + canvas.translate(mBezierControl1.dx, mBezierControl1.dy); + + /// 矩阵公式:α表示翻转页面和边的夹角 + /// https://juejin.im/post/5a32ade0f265da43252954b2 + /// + /// -(1-2sin(a)^2 ) 2sin(a)cos(a) 0 + /// 2sin(a)cos(a) 1-2sin(a)^2 0 + /// 0 0 1 + + double dis = math.sqrt(math.pow((mCornerX - mBezierControl1.dx), 2) + + math.pow((mBezierControl2.dy - mCornerY), 2)); + double sinAngle = (mCornerX - mBezierControl1.dx) / dis; + double cosAngle = (mBezierControl2.dy - mCornerY) / dis; + + Matrix4 matrix4 = Matrix4.columns( + v.Vector4( + -(1 - 2 * sinAngle * sinAngle), 2 * sinAngle * cosAngle, 0, 0), + v.Vector4(2 * sinAngle * cosAngle, (1 - 2 * sinAngle * sinAngle), 0, 0), + v.Vector4(0, 0, 1, 0), + v.Vector4(0, 0, 0, 1)); + + matrix4.translate(-mBezierControl1.dx, -mBezierControl1.dy); + canvas.transform(matrix4.storage); + + /// 用image处理有奇效……原因未知,好像是picture是保存了绘制信息的原因,所以像这种n次平移->翻转->半透明图层叠加->裁剪->加阴影 的复杂操作处理不过来 + /// image相对简单,就是张图片,处理了就处理了,不会留下需要保存的信息 + /// 反正是一个半透明处理的,所以对清晰度没要求,所以这里用image绘制 + /// 我个人的猜测……求精通底层的大佬解惑 + // canvas.drawImageRect( + // readerViewModel.cur(), + // Offset.zero & currentSize, + // Offset.zero & currentSize, + // Paint()..isAntiAlias = true); +// canvas.drawImage(configManager.currentPageImage, Offset.zero, Paint()..isAntiAlias=true); +// canvas.drawPicture(configManager.currentPagePicture); +// canvas.drawPaint(Paint()..color = Color(0xCCFFFFFF)); +// canvas.drawPaint(Paint()..color =Colors.blue); + canvas.drawPaint(Paint()..color = Color(readerViewModel.bgPaint.color.value& 0xAAFFFFFF)); +// canvas.drawPaint(Paint()..color = Color(0xAAfff2cc)); + + canvas.restore(); + + drawTopPageBackAreaShadow(canvas); + + canvas.restore(); + } + + /// 画翻起页的阴影 /// + void drawTopPageBackAreaShadow(Canvas canvas) { + double i = (mBezierStart1.dx + mBezierControl1.dx) / 2; + double f1 = (i - mBezierControl1.dx).abs(); + double i1 = (mBezierStart2.dy + mBezierControl2.dy) / 2; + double f2 = (i1 - mBezierControl2.dy).abs(); + double f3 = math.min(f1, f2); + + double left; + double right; + double width; + if (mIsRTandLB) { + left = (mBezierStart1.dx - 1); + right = (mBezierStart1.dx + f3 + 1); + width = right - left; + } else { + left = (mBezierStart1.dx - f3 - 1); + right = (mBezierStart1.dx + 1); + width = left - right; + } + + canvas.translate(mBezierStart1.dx, mBezierStart1.dy); + canvas.rotate(math.atan2( + mBezierControl1.dx - mCornerX, mBezierControl2.dy - mCornerY)); + + Gradient shadowGradient = new LinearGradient( + colors: [ + Colors.transparent, + Color(0xAA000000), + ], + ); + + var shadowPaint = Paint() + ..isAntiAlias = true + ..style = PaintingStyle.fill //填充 + ..shader = + shadowGradient.createShader(Rect.fromLTRB(0, 0, width, mMaxLength)); + + canvas.drawRect(Rect.fromLTRB(0, 0, width, mMaxLength), shadowPaint); + } + + @override + Animation getCancelAnimation( + AnimationController controller, GlobalKey canvasKey) { + if ((!isTurnToNext && !isCanGoPre()) || (isTurnToNext && !isCanGoNext())) { + return null; + } + isConfirmAnimation=false; + + if (currentAnimation == null) { + currentAnimationTween = Tween(begin: Offset.zero, end: Offset.zero); + + currentAnimation = currentAnimationTween.animate(controller); + } + + currentAnimationTween.begin = mTouch; + currentAnimationTween.end = Offset(mCornerX, mCornerY); + + return currentAnimation; + } + + @override + Animation getConfirmAnimation( + AnimationController controller, GlobalKey canvasKey) { + if ((!isTurnToNext && !isCanGoPre()) || (isTurnToNext && !isCanGoNext())) { + return null; + } + isConfirmAnimation=true; + + if (currentAnimation == null) { + currentAnimationTween = Tween(begin: Offset.zero, end: Offset.zero); + currentAnimation = currentAnimationTween.animate(controller); + } + + if(statusListener==null){ + statusListener=(status) { + switch (status) { + case AnimationStatus.dismissed: + break; + case AnimationStatus.completed: + if(isConfirmAnimation){ + if (isTurnToNext) { + // readerViewModel.nextPage(); + } else { + // readerViewModel.prePage(); + } + canvasKey.currentContext.findRenderObject().markNeedsPaint(); + } + break; + case AnimationStatus.forward: + case AnimationStatus.reverse: + break; + } + }; + + currentAnimation.addStatusListener(statusListener); + } + + if(statusListener!=null&&!(controller as AnimationControllerWithListenerNumber).statusListeners.contains(statusListener)){ + currentAnimation.addStatusListener(statusListener); + } + + currentAnimationTween.begin = mTouch; + currentAnimationTween.end = Offset( + mCornerX == 0 ? currentSize.width * 3 / 2 : 0 - currentSize.width / 2, + mCornerY == 0 ? 0 : currentSize.height); + +// if (!controller.isCompleted) { +// +// } + return currentAnimation; + } + + @override + Simulation getFlingAnimationSimulation( + AnimationController controller, DragEndDetails details) { + return null; + } + + @override + bool isCancelArea() { + + return isTurnToNext?(mTouch.dx).abs() > (currentSize.width / 4*3):(mTouch.dx).abs() < (currentSize.width / 4); + } + + @override + bool isConfirmArea() { + return isTurnToNext?(mTouch.dx).abs() < (currentSize.width / 4*3):(mTouch.dx).abs() > (currentSize.width / 4); + } +} diff --git a/lib/model/ReadModel.dart b/lib/model/ReadModel.dart index a6b16a4..7fe8894 100644 --- a/lib/model/ReadModel.dart +++ b/lib/model/ReadModel.dart @@ -36,6 +36,7 @@ class ReadModel with ChangeNotifier { TextComposition textComposition; Map widgets = Map(); Stack stackContent; + bool delay = true; Paint bgPaint = Paint(); ui.Image bgUI; GlobalKey canvasKey; @@ -304,23 +305,31 @@ class ReadModel with ChangeNotifier { var curWid = details.globalPosition.dx; var curH = details.globalPosition.dy; var location = details.localPosition; - - if ((curWid > 0 && curWid < space)) { - if (leftClickNext) { - clickPage(1, location); - return; - } - clickPage(-1, location); - } else if ((curWid > space) && - (curWid < 2 * space) && - (curH < hSpace * 3)) { + print(delay); + if ((curWid > space) && (curWid < 2 * space) && (curH < hSpace * 3)) { toggleShowMenu(); } else if ((curWid > space * 2)) { - if (leftClickNext) { - clickPage(1, location); - return; - } - clickPage(1, location); + delay = true; + Future.delayed(Duration(milliseconds: 50), () { + if (delay) { + if (leftClickNext) { + clickPage(1, location); + return; + } + clickPage(1, location); + } + }); + } else if ((curWid > 0 && curWid < space)) { + delay = true; + Future.delayed(Duration(milliseconds: 50), () { + if (delay) { + if (leftClickNext) { + clickPage(1, location); + return; + } + clickPage(-1, location); + } + }); } } @@ -578,7 +587,6 @@ class ReadModel with ChangeNotifier { textPainter.layout(); textPainter.paint( pageCanvas, Offset(Screen.width - contentPadding - 35, bottomTextH)); - return pageRecorder.endRecording(); } diff --git a/lib/view/book/Menu.dart b/lib/view/book/Menu.dart index d1e8a4f..c6a5845 100644 --- a/lib/view/book/Menu.dart +++ b/lib/view/book/Menu.dart @@ -28,7 +28,7 @@ class _MenuState extends State { ReadModel _readModel; ColorModel _colorModel; - double settingH = 420; + double settingH = 380; @override void initState() { @@ -386,9 +386,9 @@ class _MenuState extends State { children: bgThemes(), scrollDirection: Axis.horizontal, )), - Expanded( - child: flipType(), - ), + // Expanded( + // child: flipType(), + // ), SwitchListTile( contentPadding: EdgeInsets.only(left: 15), value: _readModel.leftClickNext, diff --git a/lib/view/book/PageContentRender.dart b/lib/view/book/PageContentRender.dart index 09b77df..c5ea53e 100644 --- a/lib/view/book/PageContentRender.dart +++ b/lib/view/book/PageContentRender.dart @@ -66,7 +66,8 @@ class _PageContentReaderState extends State instance ..onDown = (detail) { - if (true) { + print("down"); + if (currentTouchEvent.action != TouchEvent.ACTION_DOWN || currentTouchEvent.touchPos != detail.localPosition) { currentTouchEvent = TouchEvent( @@ -76,11 +77,11 @@ class _PageContentReaderState extends State .findRenderObject() .markNeedsPaint(); } - } }; instance ..onUpdate = (detail) { if (!viewModel.showMenu) { + viewModel.delay=false; if (currentTouchEvent.action != TouchEvent.ACTION_MOVE || currentTouchEvent.touchPos != detail.localPosition) { currentTouchEvent = TouchEvent( @@ -95,6 +96,7 @@ class _PageContentReaderState extends State instance ..onEnd = (detail) { if (!viewModel.showMenu) { + print("end"); if (currentTouchEvent.action != TouchEvent.ACTION_UP || currentTouchEvent.touchPos != Offset(0, 0)) { currentTouchEvent = TouchEvent( @@ -108,6 +110,8 @@ class _PageContentReaderState extends State } } }; + + }, ), }, diff --git a/lib/view/newBook/ReaderPageManager.dart b/lib/view/newBook/ReaderPageManager.dart index 070c143..83ff40f 100644 --- a/lib/view/newBook/ReaderPageManager.dart +++ b/lib/view/newBook/ReaderPageManager.dart @@ -1,6 +1,7 @@ import 'dart:ui'; import 'package:book/animation/BaseAnimationPage.dart'; +import 'package:book/animation/SimulationTurePageAnimation.dart'; import 'package:book/animation/turn_page_animation.dart'; import 'package:book/common/Screen.dart'; import 'package:book/model/ReadModel.dart'; @@ -78,7 +79,7 @@ class ReaderPageManager { currentAnimationType = animationType; switch (animationType) { case TYPE_ANIMATION_SIMULATION_TURN: - // currentAnimationPage = SimulationTurnPageAnimation(); + currentAnimationPage = SimulationTurnPageAnimation(); break; case TYPE_ANIMATION_COVER_TURN: currentAnimationPage = CoverPageAnimation(); diff --git a/lib/view/person/Me.dart b/lib/view/person/Me.dart index 6d25fc0..93261c4 100644 --- a/lib/view/person/Me.dart +++ b/lib/view/person/Me.dart @@ -3,7 +3,6 @@ import 'package:book/common/ReadSetting.dart'; import 'package:book/common/common.dart'; import 'package:book/entity/AppInfo.dart'; import 'package:book/main.dart'; -import 'package:book/model/ColorModel.dart'; import 'package:book/model/ShelfModel.dart'; import 'package:book/route/Routes.dart'; import 'package:book/service/TelAndSmsService.dart'; @@ -89,9 +88,9 @@ class Me extends StatelessWidget { @override Widget build(BuildContext context) { - Color c = - Color(!Store.value(context).dark ? 0x4D000000 : 0xFBFFFFFF); - // bool dark = SpUtil.getBool("dark"); + bool dark = SpUtil.getBool("dark"); + Color c = Color(dark ? 0x4D000000 : 0xFBFFFFFF); + return Padding( padding: const EdgeInsets.symmetric(horizontal: 10, vertical: kToolbarHeight), diff --git a/lib/view/route/empty_page_route.dart b/lib/view/route/empty_page_route.dart deleted file mode 100644 index c1d2b09..0000000 --- a/lib/view/route/empty_page_route.dart +++ /dev/null @@ -1,22 +0,0 @@ -import 'package:flutter/material.dart'; - -/// 无动画效果 -class EmptyPageRoute extends PageRouteBuilder { - final WidgetBuilder builder; - - EmptyPageRoute({this.builder}): super( - transitionDuration: const Duration(microseconds: 100), - pageBuilder: (context, ani1, ani2) { - return builder(context); - }, - transitionsBuilder: ( - BuildContext context, - Animation animation1, - Animation animation2, - Widget child) - { - return child; - } - ); - -} \ No newline at end of file diff --git a/lib/view/route/fade_page_route.dart b/lib/view/route/fade_page_route.dart deleted file mode 100644 index 8b093ad..0000000 --- a/lib/view/route/fade_page_route.dart +++ /dev/null @@ -1,27 +0,0 @@ -import 'package:flutter/material.dart'; - -/// 淡入淡出效果 -class FadePageRoute extends PageRouteBuilder { - final WidgetBuilder builder; - final int milliseconds; - final bool isNext; - - FadePageRoute({this.builder, this.milliseconds = 500, this.isNext}): super( - transitionDuration: Duration(milliseconds: milliseconds), - pageBuilder: (context, ani1, ani2) { - return builder(context); - }, - transitionsBuilder: ( - BuildContext context, - Animation animation1, - Animation animation2, - Widget child) - { - return FadeTransition(opacity: Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation( - parent: animation1, - curve: Curves.easeInOut - )), child: child); - } - ); - -} \ No newline at end of file diff --git a/lib/view/route/pop_route.dart b/lib/view/route/pop_route.dart deleted file mode 100644 index 3a45699..0000000 --- a/lib/view/route/pop_route.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:flutter/material.dart'; - -class PopRoute extends PageRouteBuilder { - final WidgetBuilder builder; - final int milliseconds; - bool isNext; - bool isPop; - - PopRoute({this.builder, this.milliseconds = 500, this.isNext, this.isPop}): super( - transitionDuration: Duration(milliseconds: milliseconds), - pageBuilder: (context, ani1, ani2) { - return builder(context); - }, - transitionsBuilder: ( - BuildContext context, - Animation animation1, - Animation animation2, - Widget child) - { - return SlideTransition(position: animation1.drive( - Tween(end: Offset(-1.0, 0.0), begin: Offset.zero) - .chain(CurveTween(curve: Curves.ease))), child: child); - } - ); - - @override - bool canTransitionFrom(TransitionRoute previousRoute) => false; - - @override - bool canTransitionTo(TransitionRoute previousRoute) => true; - -} diff --git a/lib/widgets/BooksWidget.dart b/lib/widgets/BooksWidget.dart index 30b7e91..2d0ef7b 100644 --- a/lib/widgets/BooksWidget.dart +++ b/lib/widgets/BooksWidget.dart @@ -28,7 +28,7 @@ class _BooksWidgetState extends State { ShelfModel _shelfModel; bool isShelf; - final double aspectRatioList = 0.7; + final double aspectRatioList = 0.65; final double aspectRatioCover = 0.75; double bookPicWidth = SpUtil.getDouble(Common.book_pic_width, defValue: .0); int spacingLen = 20;