在地图上逐渐将颜色更改为 PIN(标记位置)

Gradually change color to PIN (Mark Location) on the map

我有一个使用 iOS UIMap 地图的应用程序屏幕。地图上有指示地震仪的 PIN(Apple 人机界面的标记位置),地图每 6 秒更新一次,其中一些地震仪会振动并变成红色。我必须给地图上的 PIN 设置淡入淡出效果,从亮红色变为非常浅的红色。

if annotation.identifier == "redpin" {
   view.pinTintColor = .red
   DispatchQueue.main.asyncAfter(deadline: .now()+2.0 ) {
      view.pinTintColor = UIColor(red: 255/255, green: 110/255, blue: 110/255, alpha: 1)
   }
   DispatchQueue.main.asyncAfter(deadline: .now()+2.0 ) {
      view.pinTintColor = UIColor(red: 255/255, green: 180/255, blue: 180/255, alpha: 1)
   }
   DispatchQueue.main.asyncAfter(deadline: .now()+2.0 ) {
      view.pinTintColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1)
   }
}

我使用了这个方法,使用一个定时器改变每 2 秒振动一次的 PIN 码的颜色,手动给出这种淡入淡出的效果。对于第一次更新时振动的第一个,这很好,但是之后的那些保持最后的颜色(白色)而不是红-红-浅-白。 谁能帮帮我?

DispatchQueue.main.asyncAfter(deadline: .now()+2.0)块的调用不会等到完成...下一行代码将立即执行。

因此,在您发布的代码中,您实际上是在说:

set the pin to Red
wait 2 seconds
set the pin to Medium Red    
set the pin to Light Red
set the pin to White

您可以使用以下方法解决此问题:

.now()+0.25 // wait 1/4 second
.now()+0.50 // wait 1/2 second
.now()+0.75 // wait 3/4 second

因此每个块将在前一个块之后执行 1/4 秒。

Tint Color 无法设置动画,因此您不能在 UIView.animate() 块中使用它。

但是,red-white-red 细色调颜色发生变化 看起来有点“褪色”,因此您可能会满意:

func animPinColor(_ v: MKPinAnnotationView) -> Void {
    // set pin to white
    v.pinTintColor = .white
    // wait 0.25 seconds ... adjust as desired
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.25) {
        // set pin back to red
        v.pinTintColor = .red
    }
}

或者,如果您想要更多的控制权:

func animPinColor(_ v: MKPinAnnotationView) -> Void {

    // verbose, for clarity
    let red       = UIColor(red: 255/255, green:       0, blue:       0, alpha: 1)
    let mediumRed = UIColor(red: 255/255, green: 110/255, blue: 110/255, alpha: 1)
    let lightRed  = UIColor(red: 255/255, green: 180/255, blue: 180/255, alpha: 1)
    let white     = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 1)

    let colors: [UIColor] = [
        mediumRed,
        lightRed,
        white,
        lightRed,
        mediumRed,
        red,
    ]

    // 1/2 second color animation ... adjust as desired
    let totalDuration: Double = 0.5
    // each step will take totalDuration divided by total steps
    let relativeDuration = totalDuration / Double(colors.count)
    for i in 0..<colors.count {
        DispatchQueue.main.asyncAfter(deadline: .now() + Double(i) * relativeDuration) {
            v.pinTintColor = colors[i]
        }
    }
    
}

您可以调整持续时间/时间,甚至可以添加更多“红色阴影”以获得更平滑的淡入淡出。


编辑

根据您发布的代码,我假设您参考了 MKPinAnnotationView?

如果是这样,用法为:

if annotation.identifier == "redpin" {
    //view.pinTintColor = .red
    animPinColor(view)
}