         otherSidePath.addLine(to: CGPoint(x: containerFrame.minX, y: containerFrame.minY))
         otherSidePath.close()
         
-        let otherSideLayer = CAShapeLayer()
-        otherSideLayer.path = otherSidePath.cgPath
-        
-        return (oneSideLayer, otherSideLayer)
-    }
-    
-}
+        return otherSidePath
+    }
+    
+}
+
+extension SamuraiTransition: CAAnimationDelegate {
+    
+    public func animationDidStop(_ anim: CAAnimation, finished flag: Bool) {
+        if let layer = anim.value(forKey: "LineLayer") as? CAShapeLayer {
+            layer.removeFromSuperlayer()
+        }
+    }
+    
+}
+

    public var isAffineTransform: Bool = true
    public var zanPosition: CGPoint?
    public var zanLineColor = UIColor.black
    public var zanLineWidth: CGFloat = 1.0
    
    fileprivate weak var transitionContext: UIViewControllerContextTransitioning!
    fileprivate var containerView: UIView!

        
    }
    
}

extension SamuraiTransition {
    
    fileprivate func lineLayerAnimation(lineLayer: CAShapeLayer) -> CABasicAnimation {
        
        let lineAnimation = CABasicAnimation(keyPath: "strokeEnd")
        lineAnimation.duration = zanLineDuration
        lineAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn)
        lineAnimation.fromValue = 0.0
        lineAnimation.toValue = 1.0
        lineAnimation.delegate = self
        lineAnimation.setValue(lineLayer, forKey: "LineLayer")
        
        return lineAnimation
    }
    
    fileprivate func zanLineLayer(from start: CGPoint, end: CGPoint) -> CAShapeLayer {
        
        let zanLineLayer = CAShapeLayer()
        let path = UIBezierPath()
        path.move(to: start)
        path.addLine(to: end)
        path.close()
        zanLineLayer.path = path.cgPath
        zanLineLayer.fillColor = nil
        zanLineLayer.strokeColor = zanLineColor.cgColor
        zanLineLayer.lineWidth = zanLineWidth
        return zanLineLayer
        
    }
    
    fileprivate func diagnoallyBottomX(zanPosition: CGPoint) -> CGFloat {
        
        let ratio = containerFrame.maxY / zanPosition.y
        if ratio.isInfinite {
            fatalError("zanPosition.y is not 0. It will be infinite.")
        }
        let width = (containerFrame.maxX - zanPosition.x) * ratio
        let bottomX = containerFrame.maxX - width
        
        return bottomX
    }
    
    fileprivate func maskLayer(zanPosition: CGPoint) -> (oneSide: CAShapeLayer, otherSide: CAShapeLayer) {
        let bottomX = diagnoallyBottomX(zanPosition: zanPosition)
        
        let oneSidePath = oneSideBezierPath(zanPosition: zanPosition, bottomX: bottomX)
        let oneSideLayer = CAShapeLayer()
        oneSideLayer.path = oneSidePath.cgPath
        
        let otherSidePath = otherSideBezierPath(zanPosition: zanPosition, bottomX: bottomX)
        let otherSideLayer = CAShapeLayer()
        otherSideLayer.path = otherSidePath.cgPath
        
        return (oneSideLayer, otherSideLayer)
    }
    
    private func oneSideBezierPath(zanPosition: CGPoint, bottomX: CGFloat) -> UIBezierPath {
        let oneSidePath = UIBezierPath()
        oneSidePath.move(to: CGPoint(x: containerFrame.maxX, y: containerFrame.minY))
        oneSidePath.addLine(to: zanPosition)
        oneSidePath.addLine(to: CGPoint(x: bottomX, y: containerFrame.maxY))
        oneSidePath.addLine(to: CGPoint(x: containerFrame.maxX, y: containerFrame.maxY))
        oneSidePath.addLine(to: CGPoint(x: containerFrame.maxX, y: containerFrame.minY))
        oneSidePath.close()
        
        return oneSidePath
    }
    
    private func otherSideBezierPath(zanPosition: CGPoint, bottomX: CGFloat) -> UIBezierPath {
        let otherSidePath = UIBezierPath()
        otherSidePath.move(to: CGPoint(x: containerFrame.minX, y: containerFrame.minY))
        otherSidePath.addLine(to: CGPoint(x: containerFrame.maxX, y: containerFrame.minY))
