iOS CorePlot点转换

时间:2016-08-13 20:42:01

标签: ios iphone core-plot graphing

我正在尝试使用Core Plot。我试图在x:2.0,y:50.0的图形上添加一个自定义的“目标”标签 - 基本上是y == 50的标签,它在一个单独的视图中,这意味着我需要将我的点从Core Plot转换为我的UIView界限。我没有找到适用于所有iPhone屏幕尺寸的图层/视图的点转换组合。在我的照片下面,iPhone 6s是最接近的。

iPhone 6s +:iphone 6s+

iPhone 6s:iphone 6s

iPhone 5s:iphone 5s

我的视图布局:  View layout

这是我的班级:

class BarChartViewController: UIViewController, CPTBarPlotDataSource
{
    private var barGraph : CPTXYGraph? = nil
    @IBOutlet weak var textBox: UILabel!
    @IBOutlet weak var graphHostingView: CPTGraphHostingView!
    @IBOutlet weak var textBoxView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationController?.setNavigationBarHidden(false, animated: false)

        self.title = "My results"

        let newGraph = CPTXYGraph(frame: CGRectZero)
        let theme = CPTTheme(named: kCPTPlainWhiteTheme)

        newGraph.applyTheme(theme)

        let hostingView = graphHostingView
        hostingView.hostedGraph = newGraph
        if let frameLayer = newGraph.plotAreaFrame
        {
            // Border
            frameLayer.borderLineStyle = nil
            frameLayer.cornerRadius = 0.0
            frameLayer.masksToBorder = false

            // Paddings
            newGraph.paddingLeft = 0.0
            newGraph.paddingRight = 0.0
            newGraph.paddingTop = 0.0
            newGraph.paddingBottom = 0.0

            frameLayer.paddingLeft = 70.0
            frameLayer.paddingTop = 20.0
            frameLayer.paddingRight = 20.0
            frameLayer.paddingBottom = 80.0
        }

        // Plot space
        let plotSpace = newGraph.defaultPlotSpace as? CPTXYPlotSpace
        plotSpace?.yRange = CPTPlotRange(location: 0.0, length: 100.0)
        plotSpace?.xRange = CPTPlotRange(location: 0.0, length: 4.0)

        let axisSet = newGraph.axisSet as? CPTXYAxisSet

        if let x = axisSet?.xAxis {
            x.axisLineStyle = nil
            x.majorTickLineStyle = nil
            x.minorTickLineStyle = nil
            x.majorIntervalLength = 5.0
            x.orthogonalPosition = 0.0
            x.title = "X Axis"
            x.titleLocation = 7.5
            x.titleOffset = 55.0

            // Custom labels
            x.labelRotation = CGFloat(M_PI_4)
            x.labelingPolicy = .None

            let customTickLocations = [0.5, 1.5, 2.5]
            let xAxisLabels = ["Label A", "Label B", "Label C"]

            var labelLocation = 0
            var customLabels = Set<CPTAxisLabel>()
            for tickLocation in customTickLocations
            {
                let newLabel = CPTAxisLabel(text: xAxisLabels[labelLocation], textStyle: x.labelTextStyle)
                labelLocation += 1
                newLabel.tickLocation = tickLocation
                newLabel.offset = x.labelOffset + x.majorTickLength
                newLabel.rotation = 0 //CGFloat(M_PI_4)
                customLabels.insert(newLabel)
            }

            x.axisLabels = customLabels
        }

        if let y = axisSet?.yAxis
        {
            y.axisLineStyle = nil
            y.majorGridLineStyle = CPTMutableLineStyle()
            var style = y.majorTickLineStyle?.mutableCopy() as? CPTMutableLineStyle
            //style!.lineColor = CPTColor(CGColor: UIColor.blackColor())   //UIColor.blackColor())
            style!.lineWidth = 10.0
            y.minorGridLineStyle = CPTMutableLineStyle()
            style = y.minorTickLineStyle?.mutableCopy() as? CPTMutableLineStyle
            //style.lineColor = UIColor.redColor()
            style!.lineWidth = 10.0
            style!.lineCap = .Round
            y.majorTickLength = 10.0
            y.majorIntervalLength = 50.0
            y.orthogonalPosition = 0.0
            y.title = "Y Axis"
            y.titleOffset = 45.0
            y.titleLocation = 150.0

            y.labelRotation = 0
            y.labelingPolicy = .None


            let customTickLocations = [50, 100]
            let yAxisLabels = ["50", "100"]

            var labelLocation = 0
            var customLabels = Set<CPTAxisLabel>()
            for tickLocation in customTickLocations
            {
                let newLabel = CPTAxisLabel(text: yAxisLabels[labelLocation], textStyle: y.labelTextStyle)
                labelLocation += 1
                newLabel.tickLocation = tickLocation
                newLabel.offset = y.labelOffset + y.majorTickLength
                newLabel.rotation = 0 //CGFloat(M_PI_4)
                customLabels.insert(newLabel)
            }

            y.axisLabels = customLabels
            var nums = Set<NSNumber>()
            nums.insert(NSNumber(double: 50.0))
            y.majorTickLocations = nums
        }

        // First bar plot
        let barPlot1 = CPTBarPlot.tubularBarPlotWithColor(CPTColor.yellowColor(), horizontalBars: false)
        barPlot1.baseValue = 0.0
        barPlot1.dataSource = self
        //barPlot1.barOffset = 0.5
        barPlot1.identifier = "Bar Plot 1"
        let textStyle = CPTMutableTextStyle()
        textStyle.color = CPTColor.redColor()
        textStyle.fontSize = 10.0
        barPlot1.labelTextStyle = textStyle
        newGraph.addPlot(barPlot1, toPlotSpace: plotSpace)

        self.barGraph = newGraph
    }

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)

        self.view.layoutIfNeeded()

        let point: [Double] = [2.0, 50.0]
        let plotPoint = UnsafeMutablePointer<Double>(point)
        var dataPoint = self.barGraph?.defaultPlotSpace?.plotAreaViewPointForDoublePrecisionPlotPoint(plotPoint, numberOfCoordinates: 2)
        //dataPoint = graphHostingView.layer.convertPoint(dataPoint!, fromLayer: self.barGraph!.plotAreaFrame!.plotArea)
        dataPoint = graphHostingView.layer.convertPoint(dataPoint!, toLayer: graphHostingView.layer.superlayer)
        //dataPoint = barGraph?.convertPoint(dataPoint!, fromLayer: graphHostingView.layer)
        dataPoint = self.textBoxView.convertPoint(dataPoint!, fromView: graphHostingView)

        print(dataPoint!)
        for item in (self.textBoxView?.constraints)!
        {
            if let id = item.identifier
            {
                if id == "goalX"
                {
                    print(item.constant)
                    item.constant = CGFloat((dataPoint?.x)!) - item.constant
                }
                else if id == "goalY"
                {
                    print(item.constant)
                    item.constant = CGFloat((dataPoint?.y)!) - item.constant
                }
            }
        }
        barGraph?.titleDisplacement = CGPoint(x: dataPoint!.x * -1, y: dataPoint!.y * -1)
        barGraph?.titlePlotAreaFrameAnchor = .TopLeft
        self.textBoxView?.layoutIfNeeded()
   }
}

根据我在CorePlot上看到的其他一些问题,我知道我需要将它从CorePlot层转换为我的新视图。我在viewWillAppear()中留下了一些实验,看看我尝试了什么。 SO上的解决方案似乎都没有用,我是iOS的新手,所以可能会遗漏一些东西。我需要做些什么转换才能让我的标签在所有屏幕尺寸中正确显示?

1 个答案:

答案 0 :(得分:1)

你在点转换的正确轨道上。我就是这样做的:

// Update layer layout if needed
self.view.layoutIfNeeded()
graphHostingView.layer.layoutIfNeeded()

// Point in data coordinates
let point: [Double] = [2.0, 50.0]

// Data point in plot area layer coordinates
var dataPoint = self.barGraph?.defaultPlotSpace?.plotAreaViewPointForPlotPoint(point)

// Convert data point to graph hosting view coordinates
dataPoint = graphHostingView.layer.convertPoint(dataPoint!, fromLayer: self.barGraph!.plotAreaFrame!.plotArea)

使用此选项更新文本框相对于图表托管视图的约束。