我想在 floor(floorState) 改变时重新组合 floorMap。将所有路径加起来并给这条路径一个状态的变体是不好的,因为在下一步中我想让每个 roomPath 和对象都可以点击。
这是我的 Jetpack compose 代码,用于转换输入数据和绘制地图:
fun initMap(
pointsList: List<Point>,
pathsList: List<PathModel>,
width: Float,
height: Float
): PathsAndObjectsHolderForDrawing {
val pathsAndObjects = PathsAndObjectsHolderForDrawing()
clearPathsAndObjectsHolder(pathsAndObjects)
val requiredPoints = pointsList.filter { isPointObject(it) || pathsList.any { path -> path.pathId == it.pathId } }.toSet()
for (pathType in enumValues<PathType>()) {
val pathsOfType = pathsList.filter { it.pathType == pathType }
val paths = pathsOfType.map { pathModel ->
val pointsForPath = requiredPoints.filter { it.pathId == pathModel.pathId }.sortedBy { it.inPathId }
makePathFromPoints(pointsForPath, width, height)
}
when (pathType) {
PathType.ELEVATOR -> pathsAndObjects.elevatorsPath.paths.addAll(paths)
PathType.STAIRS -> pathsAndObjects.stairsPath.paths.addAll(paths)
PathType.ROOM -> pathsAndObjects.roomsPath.paths.addAll(paths)
PathType.OUTER_WALL -> pathsAndObjects.outerWallPath.paths.addAll(paths)
PathType.INTERNAL_WALL -> pathsAndObjects.internalWallsPath.paths.addAll(paths)
PathType.OTHER -> pathsAndObjects.othersPath.paths.addAll(paths)
}
}
return pathsAndObjects
}
fun clearPathsAndObjectsHolder(paths: PathsAndObjectsHolderForDrawing) {
paths.elevatorsPath.paths.clear()
paths.stairsPath.paths.clear()
paths.roomsPath.paths.clear()
paths.outerWallPath.paths.clear()
paths.internalWallsPath.paths.clear()
paths.othersPath.paths.clear()
paths.objects.objects.clear()
}
fun makePathFromPoints(points: List<Point>, width: Float, height: Float): Path {
val path = Path()
for ((index, point) in points.withIndex()){
if (index == 0) path.moveTo(point.x * width, point.y * height)
else {
when (point.pointParameter) {
PointParameter.LINE -> path.lineTo(point.x * width, point.y * height)
PointParameter.BEZIER3 -> cubicBezierForThreePoints(listOf(points[index - 2], points[index - 1], points[index]), path, width, height)
else -> Unit
}
}
}
return path
}
fun cubicBezierForThreePoints(points: List<Point>, path: Path, width: Float, height: Float){
val secondPoint = Pair(points[0].x * width, ((points[1].y - points[0].y) * 4 / 3 + points[0].y) * height)
val thirdPoint = Pair(points[2].x * width, ((points[1].y - points[2].y) * 4 / 3 + points[2].y) * height)
val fourthPoint = Pair(points[2].x * width, points[2].y * height)
path.cubicTo(secondPoint.first, secondPoint.second, thirdPoint.first, thirdPoint.second, fourthPoint.first, fourthPoint.second)
}
fun isPointObject(point: Point): Boolean = point.pointType == PointType.OBJECT
这里是让路。这是工作,但重组可能不会发生或可能会延迟发生。
@Composable
fun Map3(modifier: Modifier = Modifier,
floorState: StateFlow<FloorState>
) {
var pathsAndObjects: PathsAndObjectsHolderForDrawing = remember { PathsAndObjectsHolderForDrawing() }
// val coroutineScope = CoroutineScope(Dispatchers.Default)
val paint = Paint()
paint.color = Color.Red
paint.strokeWidth = 10f
Canvas(
modifier = modifier
.aspectRatio(3 / 2f)
.fillMaxSize()
) {
val height = size.height
val width = size.width
Log.d("height", height.toString())
floorState.let {
pathsAndObjects = initMap(it.value.points, it.value.paths, width, height)
Log.d("let", pathsAndObjects.objects.objects.size.toString())
drawPoints(pathsAndObjects.objects.objects, PointMode.Points, Color.Red, 10f)
}
}
}
这里是 coroutineScope 内部可与 StateFlow.collectAsState 组合的方式。这是行不通的。
@Composable
fun Map(modifier: Modifier = Modifier,
floorState: StateFlow<FloorState>
) {
var pathsAndObjects = remember { PathsAndObjectsHolderForDrawing() }
val coroutineScope = rememberCoroutineScope()
// val floorState by floorState.collectAsState()
val paint = Paint()
paint.color = Color.Red
paint.strokeWidth = 10f
val block: MutableState<Canvas.() -> Unit> =
remember { mutableStateOf( {drawPoints(PointMode.Points, listOf(Offset(450f, 450f)), paint) } ) }
Canvas(
modifier = modifier
.aspectRatio(3 / 2f)
.fillMaxSize()
) {
val height = size.height
val width = size.width
val paint = Paint().apply {
style = PaintingStyle.Stroke
strokeWidth = 5f
color = Color.Black
}
drawIntoCanvas{
coroutineScope.launch {
floorState.collect {floorState ->
block.value = {
initMap(floorState.points, floorState.paths, width, height).also {pathsAndObjects ->
pathsAndObjects.roomsPath.paths.forEach{ path ->
drawPath(path, Color.Red)
}
drawPoints(pathsAndObjects.objects.objects,
PointMode.Points,
pathsAndObjects.objects.color
)
}
}
}
}
val a = block.value
it.a()
}
}
}
还在 drawIntoCanvas 中用 flow 尝试过。这是行不通的。
coroutineScope.launch {
floorState.collect {State ->
initMap(floorState.value.points, floorState.value.paths, width, height)
}
}
pathsAndObjects = initMap(floorState.value.points, floorState.value.paths, width, height)
if (pathsAndObjects.elevatorsPath.paths.isNotEmpty()) {
for (item in pathsAndObjects.elevatorsPath.paths) {
drawPath(item, Color.Green, style = Stroke(2.dp.toPx()))
}
}
if (pathsAndObjects.stairsPath.paths.isNotEmpty()) {
for (item in pathsAndObjects.stairsPath.paths) {
drawPath(item, Color.Green, style = Stroke(2.dp.toPx()))
}
}
if (pathsAndObjects.roomsPath.paths.isNotEmpty()) {
for (item in pathsAndObjects.roomsPath.paths) {
drawPath(item, Color.Green, style = Stroke(2.dp.toPx()))
}
}
if (pathsAndObjects.outerWallPath.paths.isNotEmpty()) {
for (item in pathsAndObjects.outerWallPath.paths) {
drawPath(item, Color.Green, style = Stroke(2.dp.toPx()))
}
}
if (pathsAndObjects.internalWallsPath.paths.isNotEmpty()) {
for (item in pathsAndObjects.internalWallsPath.paths) {
drawPath(item, Color.Green, style = Stroke(2.dp.toPx()))
}
}
if (pathsAndObjects.othersPath.paths.isNotEmpty()) {
for (item in pathsAndObjects.othersPath.paths) {
drawPath(item, Color.Green, style = Stroke(2.dp.toPx()))
}
}
if (pathsAndObjects.objects.objects.isNotEmpty()) {
Log.d("pointShouldBeDraw", "whyNot?")
drawPoints(
pathsAndObjects.objects.objects,
pointMode = PointMode.Points,
color = Color.Red,
strokeWidth = 10f
)
}
这里是发射效果。这是行不通的。
@Composable
fun Map(modifier: Modifier = Modifier,
floorState: StateFlow<FloorState>,
configuration: Configuration,
density: Density
) {
val floorState = floorState.collectAsState()
var pathsAndObjects: PathsAndObjectsHolderForDrawing = remember { initMap(floorState.value.points, floorState.value.paths,
configuration.screenWidthDp.toFloat() * density.density,
configuration.screenWidthDp.toFloat() * density.density
) }
LaunchedEffect(floorState.value) {
val floor = floorState.value
pathsAndObjects = withContext(Dispatchers.Default) {
initMap(floor.points, floor.paths,
configuration.screenWidthDp.toFloat() * density.density,
configuration.screenWidthDp.toFloat() * density.density
)
}
}
val paint = Paint()
paint.color = Color.Red
paint.strokeWidth = 10f
val block: MutableState<Canvas.() -> Unit> =
remember { mutableStateOf( {drawPoints(PointMode.Points, listOf(Offset(450f, 450f)), paint) } ) }
Canvas(
modifier = modifier
.aspectRatio(3 / 2f)
.fillMaxSize()
) {
val height = size.height
val width = size.width
floorState.value.let {
drawPoints(pathsAndObjects.objects.objects, PointMode.Points, Color.Red, 10f)
}
}
}
请建议我可以重构 Canvas 的方法,或者其他让我的逻辑正常工作的方法。