├── LICENSE ├── README.md ├── moo.swift ├── moo_iphone.png ├── moo_sketch.png ├── moo_storyboard.png └── pathExporter.sketchplugin └── Contents └── Sketch ├── library.cocoascript ├── manifest.json └── script.cocoascript /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Charimon 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | iosViews 2 | ======== 3 | 4 | Sketch plugin to generate ios view code 5 | 6 | ### pathExporter.sketchplugin (finally fixed) 7 | exports your views as UIBezierPath as swift code 8 | so you'll have something like 9 | 10 | let path = UIBezierPath() 11 | path.moveToPoint(...) 12 | ... 13 | 14 | #### Why? 15 | It's very annoying to draw in ios in code. But it's annoying to draw in sketch and export it as a picture because you can no longer use the CGRect dimensions from ios. You're stuck with whatever dimensions you picked in sketch. 16 | 17 | This will generate a bunch of swift functions, with 1 main function which takes in a CGRect so you can put it in layoutSubviews. All your shapes will be relative to how you depict them in sketch and the CGRect. Also you can edit the code and add your own transformations or animations, instead of having to create a ton of assets and load them dynamically. 18 | 19 | For instance, if in sketch you offset your creation 20px from the left, and your arboard is 200px in width. Then at runtime of the ios application your creation will be offset 20*(width/200) where width is the width of the ios CGRect at runtime. This of course works with y offset, width, and height. 20 | 21 | When you run the plugin it puts the generated code into your artboard, so if you have a very complex shape (or groups of shapes) pasting the code might be slow or even crash sketch. If it is complex and hasn't crashed, it might take minutes (spinning beachball) but it will work. 22 | 23 | 24 | #### How does it work? 25 | 1. create an artboard (let's say iphone sized) 26 | 1. create some shape you want that you'd have to do in code otherwise 27 | 1. select the artboard (make sure it's only the artboard, this is very important) 28 | 1. SAVE, because sketch might might crash if you have weirdly intercepting paths in your shape (flatten them, and try to simplify them) 29 | 1. run the pathExporter.sketchplugin 30 | - anything hidden will be ignored 31 | - you will get code where everything is relative to the artboard 32 | - NOTE: for complex shapes the export might be slow (take minutes) 33 | 34 | #### Unfortunatelly this doesn't work with: 35 | 1. boolean operations (union, subtract, intersect, difference) 36 | 1. radius on object (set the radius on individual path instead of object... click enter > highlight points > set radius) 37 | 1. opacity on object (set your opacity on the color directly, and it will work) 38 | 1. transformation on the object (flatten them all, if you have a rotated group, ungroup it then flatten it, that way your rotation will be preserved) 39 | 1. for fills only solid and linear gradients work, others don't 40 | 1. for stroke, only solid color works, others don't 41 | 1. more than 1 border or fill (only the last valid border and last valid fill are set, valid = center borders with solid color) 42 | 1. inside, outside borders don't work and are ignored (only center border works) 43 | 1. blending (will always be treated as "normal") 44 | 1. shadows, inner shadows, blurs, reflections are ignored 45 | 1. character spacing, line height, paragraph spacing are ignored 46 | 1. justified alignment is ignored 47 | 1. text layers are ignored 48 | 1. even/odd setting on fill is ignored (it uses whatever ios uses, I don't know if it's even/odd or non zero by default) 49 | 1. border arrow settings 50 | 51 | #### TODO: 52 | - fix a lot of the things that don't work 53 | - settle on a good shortcut 54 | - add this to sketch toolbox 55 | 56 | #### Example 57 | ##### Sketch File 58 | ![moo png](https://github.com/Charimon/iosViews/blob/master/moo_sketch.png?raw=true "moo_sketch.png") 59 | 60 | ##### Generated Code 61 | ```swift 62 | lazy var outline: CAShapeLayer = { 63 | let l = CAShapeLayer() 64 | l.lineWidth = 28 65 | l.strokeColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 66 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 67 | self.layer.addSublayer(l) 68 | return l 69 | }() 70 | ... 71 | func moo(bounds: CGRect) { 72 | outline.frame = bounds 73 | outline.path = outline_path(outline.frame) 74 | body.frame = bounds 75 | body.path = body_path(body.frame) 76 | spot2.frame = bounds 77 | spot2.path = spot2_path(spot2.frame) 78 | spot.frame = bounds 79 | spot.path = spot_path(spot.frame) 80 | armLeft.frame = bounds 81 | armLeft.path = armLeft_path(armLeft.frame) 82 | armRight.frame = bounds 83 | armRight.path = armRight_path(armRight.frame) 84 | head.frame = bounds 85 | head.path = head_path(head.frame) 86 | snout.frame = bounds 87 | snout.path = snout_path(snout.frame) 88 | nostrilLeft.frame = bounds 89 | nostrilLeft.path = nostrilLeft_path(nostrilLeft.frame) 90 | nostrilRight.frame = bounds 91 | nostrilRight.path = nostrilRight_path(nostrilRight.frame) 92 | eyeLeft.frame = bounds 93 | eyeLeft.path = eyeLeft_path(eyeLeft.frame) 94 | eyeBallLeft.frame = bounds 95 | eyeBallLeft.path = eyeBallLeft_path(eyeBallLeft.frame) 96 | eyeRight.frame = bounds 97 | eyeRight.path = eyeRight_path(eyeRight.frame) 98 | eyeBallRight.frame = bounds 99 | eyeBallRight.path = eyeBallRight_path(eyeBallRight.frame) 100 | } 101 | ``` 102 | [full swift file](../moo.swift) 103 | 104 | ##### ios 105 | after adding the following to some UIView 106 | ```swift 107 | override func layoutSubviews() { 108 | moo(self.bounds) 109 | } 110 | ``` 111 | you should see 112 | ![moo_ios png](https://github.com/Charimon/iosViews/blob/master/moo_iphone.png?raw=true "moo_iphone.png") 113 | 114 | -------------------------------------------------------------------------------- /moo.swift: -------------------------------------------------------------------------------- 1 | lazy var outline: CAShapeLayer = { 2 | let l = CAShapeLayer() 3 | l.lineWidth = 28 4 | l.strokeColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 5 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 6 | self.layer.addSublayer(l) 7 | return l 8 | }() 9 | func outline_path(bounds: CGRect) -> CGPath { 10 | let path = UIBezierPath() 11 | path.moveToPoint(CGPoint(x: 274.37*bounds.width/320 , y: 253*bounds.height/320)) 12 | path.addCurveToPoint(CGPoint(x: 244.93*bounds.width/320 , y: 304.5*bounds.height/320), controlPoint1: CGPoint(x: 263.14*bounds.width/320 , y: 284.46*bounds.height/320), controlPoint2:CGPoint(x: 244.93*bounds.width/320 , y: 304.5*bounds.height/320)) 13 | path.addLineToPoint(CGPoint(x: 160*bounds.width/320 , y: 304.5*bounds.height/320)) 14 | path.addLineToPoint(CGPoint(x: 74*bounds.width/320 , y: 304.5*bounds.height/320)) 15 | path.addCurveToPoint(CGPoint(x: 44.54*bounds.width/320 , y: 252.96*bounds.height/320), controlPoint1: CGPoint(x: 74*bounds.width/320 , y: 304.5*bounds.height/320), controlPoint2:CGPoint(x: 55.77*bounds.width/320 , y: 284.45*bounds.height/320)) 16 | path.addLineToPoint(CGPoint(x: 44.54*bounds.width/320 , y: 252.96*bounds.height/320)) 17 | path.addCurveToPoint(CGPoint(x: 20*bounds.width/320 , y: 227*bounds.height/320), controlPoint1: CGPoint(x: 30.86*bounds.width/320 , y: 252.2*bounds.height/320), controlPoint2:CGPoint(x: 20*bounds.width/320 , y: 240.87*bounds.height/320)) 18 | path.addCurveToPoint(CGPoint(x: 35.94*bounds.width/320 , y: 203.02*bounds.height/320), controlPoint1: CGPoint(x: 20*bounds.width/320 , y: 216.21*bounds.height/320), controlPoint2:CGPoint(x: 26.58*bounds.width/320 , y: 206.95*bounds.height/320)) 19 | path.addCurveToPoint(CGPoint(x: 36*bounds.width/320 , y: 200.5*bounds.height/320), controlPoint1: CGPoint(x: 35.95*bounds.width/320 , y: 202.18*bounds.height/320), controlPoint2:CGPoint(x: 35.97*bounds.width/320 , y: 201.34*bounds.height/320)) 20 | path.addCurveToPoint(CGPoint(x: 61.46*bounds.width/320 , y: 134.08*bounds.height/320), controlPoint1: CGPoint(x: 36.77*bounds.width/320 , y: 177.44*bounds.height/320), controlPoint2:CGPoint(x: 46.48*bounds.width/320 , y: 154.09*bounds.height/320)) 21 | path.addCurveToPoint(CGPoint(x: 60*bounds.width/320 , y: 119*bounds.height/320), controlPoint1: CGPoint(x: 60.5*bounds.width/320 , y: 129.28*bounds.height/320), controlPoint2:CGPoint(x: 60*bounds.width/320 , y: 124.25*bounds.height/320)) 22 | path.addCurveToPoint(CGPoint(x: 61.69*bounds.width/320 , y: 102.78*bounds.height/320), controlPoint1: CGPoint(x: 60*bounds.width/320 , y: 113.33*bounds.height/320), controlPoint2:CGPoint(x: 60.58*bounds.width/320 , y: 107.92*bounds.height/320)) 23 | path.addCurveToPoint(CGPoint(x: 20*bounds.width/320 , y: 75*bounds.height/320), controlPoint1: CGPoint(x: 40.16*bounds.width/320 , y: 102.92*bounds.height/320), controlPoint2:CGPoint(x: 20*bounds.width/320 , y: 90.46*bounds.height/320)) 24 | path.addCurveToPoint(CGPoint(x: 57*bounds.width/320 , y: 47*bounds.height/320), controlPoint1: CGPoint(x: 20*bounds.width/320 , y: 59.54*bounds.height/320), controlPoint2:CGPoint(x: 36.57*bounds.width/320 , y: 47*bounds.height/320)) 25 | path.addCurveToPoint(CGPoint(x: 88.83*bounds.width/320 , y: 60.71*bounds.height/320), controlPoint1: CGPoint(x: 70.54*bounds.width/320 , y: 47*bounds.height/320), controlPoint2:CGPoint(x: 82.38*bounds.width/320 , y: 52.5*bounds.height/320)) 26 | path.addCurveToPoint(CGPoint(x: 96.08*bounds.width/320 , y: 55.68*bounds.height/320), controlPoint1: CGPoint(x: 91.13*bounds.width/320 , y: 58.93*bounds.height/320), controlPoint2:CGPoint(x: 93.56*bounds.width/320 , y: 57.25*bounds.height/320)) 27 | path.addCurveToPoint(CGPoint(x: 111*bounds.width/320 , y: 20*bounds.height/320), controlPoint1: CGPoint(x: 94.28*bounds.width/320 , y: 35.75*bounds.height/320), controlPoint2:CGPoint(x: 111*bounds.width/320 , y: 20*bounds.height/320)) 28 | path.addCurveToPoint(CGPoint(x: 124.92*bounds.width/320 , y: 43.42*bounds.height/320), controlPoint1: CGPoint(x: 111*bounds.width/320 , y: 20*bounds.height/320), controlPoint2:CGPoint(x: 123.8*bounds.width/320 , y: 31.9*bounds.height/320)) 29 | path.addCurveToPoint(CGPoint(x: 160*bounds.width/320 , y: 39*bounds.height/320), controlPoint1: CGPoint(x: 135.84*bounds.width/320 , y: 40.51*bounds.height/320), controlPoint2:CGPoint(x: 147.66*bounds.width/320 , y: 39*bounds.height/320)) 30 | path.addCurveToPoint(CGPoint(x: 195.08*bounds.width/320 , y: 43.42*bounds.height/320), controlPoint1: CGPoint(x: 172.34*bounds.width/320 , y: 39*bounds.height/320), controlPoint2:CGPoint(x: 184.16*bounds.width/320 , y: 40.51*bounds.height/320)) 31 | path.addCurveToPoint(CGPoint(x: 209*bounds.width/320 , y: 20*bounds.height/320), controlPoint1: CGPoint(x: 196.2*bounds.width/320 , y: 31.9*bounds.height/320), controlPoint2:CGPoint(x: 209*bounds.width/320 , y: 20*bounds.height/320)) 32 | path.addCurveToPoint(CGPoint(x: 223.92*bounds.width/320 , y: 55.68*bounds.height/320), controlPoint1: CGPoint(x: 209*bounds.width/320 , y: 20*bounds.height/320), controlPoint2:CGPoint(x: 225.72*bounds.width/320 , y: 35.75*bounds.height/320)) 33 | path.addCurveToPoint(CGPoint(x: 231.17*bounds.width/320 , y: 60.71*bounds.height/320), controlPoint1: CGPoint(x: 226.44*bounds.width/320 , y: 57.25*bounds.height/320), controlPoint2:CGPoint(x: 228.87*bounds.width/320 , y: 58.93*bounds.height/320)) 34 | path.addCurveToPoint(CGPoint(x: 263*bounds.width/320 , y: 47*bounds.height/320), controlPoint1: CGPoint(x: 237.62*bounds.width/320 , y: 52.5*bounds.height/320), controlPoint2:CGPoint(x: 249.46*bounds.width/320 , y: 47*bounds.height/320)) 35 | path.addCurveToPoint(CGPoint(x: 300*bounds.width/320 , y: 75*bounds.height/320), controlPoint1: CGPoint(x: 283.43*bounds.width/320 , y: 47*bounds.height/320), controlPoint2:CGPoint(x: 300*bounds.width/320 , y: 59.54*bounds.height/320)) 36 | path.addCurveToPoint(CGPoint(x: 258.31*bounds.width/320 , y: 102.78*bounds.height/320), controlPoint1: CGPoint(x: 300*bounds.width/320 , y: 90.46*bounds.height/320), controlPoint2:CGPoint(x: 279.84*bounds.width/320 , y: 102.92*bounds.height/320)) 37 | path.addCurveToPoint(CGPoint(x: 260*bounds.width/320 , y: 119*bounds.height/320), controlPoint1: CGPoint(x: 259.42*bounds.width/320 , y: 107.92*bounds.height/320), controlPoint2:CGPoint(x: 260*bounds.width/320 , y: 113.33*bounds.height/320)) 38 | path.addCurveToPoint(CGPoint(x: 258.23*bounds.width/320 , y: 135.56*bounds.height/320), controlPoint1: CGPoint(x: 260*bounds.width/320 , y: 124.79*bounds.height/320), controlPoint2:CGPoint(x: 259.39*bounds.width/320 , y: 130.32*bounds.height/320)) 39 | path.addLineToPoint(CGPoint(x: 258.23*bounds.width/320 , y: 135.56*bounds.height/320)) 40 | path.addCurveToPoint(CGPoint(x: 282.93*bounds.width/320 , y: 200.5*bounds.height/320), controlPoint1: CGPoint(x: 272.77*bounds.width/320 , y: 155.24*bounds.height/320), controlPoint2:CGPoint(x: 282.18*bounds.width/320 , y: 178.01*bounds.height/320)) 41 | path.addCurveToPoint(CGPoint(x: 282.98*bounds.width/320 , y: 202.59*bounds.height/320), controlPoint1: CGPoint(x: 282.95*bounds.width/320 , y: 201.2*bounds.height/320), controlPoint2:CGPoint(x: 282.97*bounds.width/320 , y: 201.9*bounds.height/320)) 42 | path.addCurveToPoint(CGPoint(x: 300*bounds.width/320 , y: 227*bounds.height/320), controlPoint1: CGPoint(x: 292.91*bounds.width/320 , y: 206.25*bounds.height/320), controlPoint2:CGPoint(x: 300*bounds.width/320 , y: 215.8*bounds.height/320)) 43 | path.addCurveToPoint(CGPoint(x: 274.37*bounds.width/320 , y: 253*bounds.height/320), controlPoint1: CGPoint(x: 300*bounds.width/320 , y: 241.23*bounds.height/320), controlPoint2:CGPoint(x: 288.56*bounds.width/320 , y: 252.8*bounds.height/320)) 44 | path.addLineToPoint(CGPoint(x: 274.37*bounds.width/320 , y: 253*bounds.height/320)) 45 | return path.CGPath 46 | } 47 | lazy var body: CAShapeLayer = { 48 | let l = CAShapeLayer() 49 | l.lineWidth = 10 50 | l.strokeColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 51 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 52 | self.layer.addSublayer(l) 53 | return l 54 | }() 55 | func body_path(bounds: CGRect) -> CGPath { 56 | let path = UIBezierPath() 57 | path.moveToPoint(CGPoint(x: 36*bounds.width/320 , y: 200.5*bounds.height/320)) 58 | path.addCurveToPoint(CGPoint(x: 74*bounds.width/320 , y: 304.5*bounds.height/320), controlPoint1: CGPoint(x: 34*bounds.width/320 , y: 260.5*bounds.height/320), controlPoint2:CGPoint(x: 74*bounds.width/320 , y: 304.5*bounds.height/320)) 59 | path.addLineToPoint(CGPoint(x: 160*bounds.width/320 , y: 304.5*bounds.height/320)) 60 | path.addLineToPoint(CGPoint(x: 244.93*bounds.width/320 , y: 304.5*bounds.height/320)) 61 | path.addCurveToPoint(CGPoint(x: 282.93*bounds.width/320 , y: 200.5*bounds.height/320), controlPoint1: CGPoint(x: 244.93*bounds.width/320 , y: 304.5*bounds.height/320), controlPoint2:CGPoint(x: 284.93*bounds.width/320 , y: 260.5*bounds.height/320)) 62 | path.addCurveToPoint(CGPoint(x: 158.93*bounds.width/320 , y: 78.5*bounds.height/320), controlPoint1: CGPoint(x: 280.93*bounds.width/320 , y: 140.5*bounds.height/320), controlPoint2:CGPoint(x: 217.31*bounds.width/320 , y: 78.5*bounds.height/320)) 63 | path.addCurveToPoint(CGPoint(x: 36*bounds.width/320 , y: 200.5*bounds.height/320), controlPoint1: CGPoint(x: 100.55*bounds.width/320 , y: 78.5*bounds.height/320), controlPoint2:CGPoint(x: 38*bounds.width/320 , y: 140.5*bounds.height/320)) 64 | return path.CGPath 65 | } 66 | lazy var spot2: CAShapeLayer = { 67 | let l = CAShapeLayer() 68 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 69 | self.layer.addSublayer(l) 70 | return l 71 | }() 72 | func spot2_path(bounds: CGRect) -> CGPath { 73 | let path = UIBezierPath() 74 | path.moveToPoint(CGPoint(x: 45.06*bounds.width/320 , y: 262.63*bounds.height/320)) 75 | path.addQuadCurveToPoint(CGPoint(x: 84.15*bounds.width/320 , y: 260.89*bounds.height/320), controlPoint: CGPoint(x: 84.15*bounds.width/320 , y: 275.09*bounds.height/320)) 76 | path.addCurveToPoint(CGPoint(x: 89.32*bounds.width/320 , y: 218.57*bounds.height/320), controlPoint1: CGPoint(x: 84.15*bounds.width/320 , y: 246.7*bounds.height/320), controlPoint2:CGPoint(x: 64.66*bounds.width/320 , y: 218.57*bounds.height/320)) 77 | path.addCurveToPoint(CGPoint(x: 44.51*bounds.width/320 , y: 173.89*bounds.height/320), controlPoint1: CGPoint(x: 113.98*bounds.width/320 , y: 218.57*bounds.height/320), controlPoint2:CGPoint(x: 63.15*bounds.width/320 , y: 174.52*bounds.height/320)) 78 | path.addQuadCurveToPoint(CGPoint(x: 37.81*bounds.width/320 , y: 215.83*bounds.height/320), controlPoint: CGPoint(x: 25.86*bounds.width/320 , y: 173.26*bounds.height/320)) 79 | path.addLineToPoint(CGPoint(x: 45.06*bounds.width/320 , y: 262.63*bounds.height/320)) 80 | return path.CGPath 81 | } 82 | lazy var spot: CAShapeLayer = { 83 | let l = CAShapeLayer() 84 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 85 | self.layer.addSublayer(l) 86 | return l 87 | }() 88 | func spot_path(bounds: CGRect) -> CGPath { 89 | let path = UIBezierPath() 90 | path.moveToPoint(CGPoint(x: 174.17*bounds.width/320 , y: 237.78*bounds.height/320)) 91 | path.addCurveToPoint(CGPoint(x: 208.46*bounds.width/320 , y: 223.23*bounds.height/320), controlPoint1: CGPoint(x: 183.89*bounds.width/320 , y: 237.78*bounds.height/320), controlPoint2:CGPoint(x: 196.74*bounds.width/320 , y: 215.98*bounds.height/320)) 92 | path.addCurveToPoint(CGPoint(x: 234.73*bounds.width/320 , y: 244.72*bounds.height/320), controlPoint1: CGPoint(x: 220.19*bounds.width/320 , y: 230.48*bounds.height/320), controlPoint2:CGPoint(x: 234.73*bounds.width/320 , y: 230.83*bounds.height/320)) 93 | path.addCurveToPoint(CGPoint(x: 218.19*bounds.width/320 , y: 281.88*bounds.height/320), controlPoint1: CGPoint(x: 234.73*bounds.width/320 , y: 258.61*bounds.height/320), controlPoint2:CGPoint(x: 227.91*bounds.width/320 , y: 276.02*bounds.height/320)) 94 | path.addCurveToPoint(CGPoint(x: 162.79*bounds.width/320 , y: 283.96*bounds.height/320), controlPoint1: CGPoint(x: 208.46*bounds.width/320 , y: 287.74*bounds.height/320), controlPoint2:CGPoint(x: 174.17*bounds.width/320 , y: 295.73*bounds.height/320)) 95 | path.addCurveToPoint(CGPoint(x: 174.17*bounds.width/320 , y: 237.78*bounds.height/320), controlPoint1: CGPoint(x: 151.41*bounds.width/320 , y: 272.2*bounds.height/320), controlPoint2:CGPoint(x: 164.45*bounds.width/320 , y: 237.78*bounds.height/320)) 96 | return path.CGPath 97 | } 98 | lazy var armLeft: CAShapeLayer = { 99 | let l = CAShapeLayer() 100 | l.lineWidth = 8 101 | l.strokeColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 102 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 103 | self.layer.addSublayer(l) 104 | return l 105 | }() 106 | func armLeft_path(bounds: CGRect) -> CGPath { 107 | let path = UIBezierPath() 108 | path.moveToPoint(CGPoint(x: 46*bounds.width/320 , y: 253*bounds.height/320)) 109 | path.addCurveToPoint(CGPoint(x: 72*bounds.width/320 , y: 227*bounds.height/320), controlPoint1: CGPoint(x: 60.36*bounds.width/320 , y: 253*bounds.height/320), controlPoint2:CGPoint(x: 72*bounds.width/320 , y: 241.36*bounds.height/320)) 110 | path.addCurveToPoint(CGPoint(x: 46*bounds.width/320 , y: 201*bounds.height/320), controlPoint1: CGPoint(x: 72*bounds.width/320 , y: 212.64*bounds.height/320), controlPoint2:CGPoint(x: 60.36*bounds.width/320 , y: 201*bounds.height/320)) 111 | path.addCurveToPoint(CGPoint(x: 20*bounds.width/320 , y: 227*bounds.height/320), controlPoint1: CGPoint(x: 31.64*bounds.width/320 , y: 201*bounds.height/320), controlPoint2:CGPoint(x: 20*bounds.width/320 , y: 212.64*bounds.height/320)) 112 | path.addCurveToPoint(CGPoint(x: 46*bounds.width/320 , y: 253*bounds.height/320), controlPoint1: CGPoint(x: 20*bounds.width/320 , y: 241.36*bounds.height/320), controlPoint2:CGPoint(x: 31.64*bounds.width/320 , y: 253*bounds.height/320)) 113 | return path.CGPath 114 | } 115 | lazy var armRight: CAShapeLayer = { 116 | let l = CAShapeLayer() 117 | l.lineWidth = 8 118 | l.strokeColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 119 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 120 | self.layer.addSublayer(l) 121 | return l 122 | }() 123 | func armRight_path(bounds: CGRect) -> CGPath { 124 | let path = UIBezierPath() 125 | path.moveToPoint(CGPoint(x: 274*bounds.width/320 , y: 253*bounds.height/320)) 126 | path.addCurveToPoint(CGPoint(x: 300*bounds.width/320 , y: 227*bounds.height/320), controlPoint1: CGPoint(x: 288.36*bounds.width/320 , y: 253*bounds.height/320), controlPoint2:CGPoint(x: 300*bounds.width/320 , y: 241.36*bounds.height/320)) 127 | path.addCurveToPoint(CGPoint(x: 274*bounds.width/320 , y: 201*bounds.height/320), controlPoint1: CGPoint(x: 300*bounds.width/320 , y: 212.64*bounds.height/320), controlPoint2:CGPoint(x: 288.36*bounds.width/320 , y: 201*bounds.height/320)) 128 | path.addCurveToPoint(CGPoint(x: 248*bounds.width/320 , y: 227*bounds.height/320), controlPoint1: CGPoint(x: 259.64*bounds.width/320 , y: 201*bounds.height/320), controlPoint2:CGPoint(x: 248*bounds.width/320 , y: 212.64*bounds.height/320)) 129 | path.addCurveToPoint(CGPoint(x: 274*bounds.width/320 , y: 253*bounds.height/320), controlPoint1: CGPoint(x: 248*bounds.width/320 , y: 241.36*bounds.height/320), controlPoint2:CGPoint(x: 259.64*bounds.width/320 , y: 253*bounds.height/320)) 130 | return path.CGPath 131 | } 132 | lazy var head: CAShapeLayer = { 133 | let l = CAShapeLayer() 134 | l.lineWidth = 10 135 | l.strokeColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 136 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 137 | self.layer.addSublayer(l) 138 | return l 139 | }() 140 | func head_path(bounds: CGRect) -> CGPath { 141 | let path = UIBezierPath() 142 | path.moveToPoint(CGPoint(x: 60*bounds.width/320 , y: 119*bounds.height/320)) 143 | path.addCurveToPoint(CGPoint(x: 61.69*bounds.width/320 , y: 102.78*bounds.height/320), controlPoint1: CGPoint(x: 60*bounds.width/320 , y: 113.33*bounds.height/320), controlPoint2:CGPoint(x: 60.58*bounds.width/320 , y: 107.92*bounds.height/320)) 144 | path.addCurveToPoint(CGPoint(x: 20*bounds.width/320 , y: 75*bounds.height/320), controlPoint1: CGPoint(x: 40.16*bounds.width/320 , y: 102.92*bounds.height/320), controlPoint2:CGPoint(x: 20*bounds.width/320 , y: 90.46*bounds.height/320)) 145 | path.addCurveToPoint(CGPoint(x: 57*bounds.width/320 , y: 47*bounds.height/320), controlPoint1: CGPoint(x: 20*bounds.width/320 , y: 59.54*bounds.height/320), controlPoint2:CGPoint(x: 36.57*bounds.width/320 , y: 47*bounds.height/320)) 146 | path.addCurveToPoint(CGPoint(x: 88.83*bounds.width/320 , y: 60.71*bounds.height/320), controlPoint1: CGPoint(x: 70.54*bounds.width/320 , y: 47*bounds.height/320), controlPoint2:CGPoint(x: 82.38*bounds.width/320 , y: 52.5*bounds.height/320)) 147 | path.addCurveToPoint(CGPoint(x: 96.08*bounds.width/320 , y: 55.68*bounds.height/320), controlPoint1: CGPoint(x: 91.13*bounds.width/320 , y: 58.93*bounds.height/320), controlPoint2:CGPoint(x: 93.56*bounds.width/320 , y: 57.25*bounds.height/320)) 148 | path.addCurveToPoint(CGPoint(x: 111*bounds.width/320 , y: 20*bounds.height/320), controlPoint1: CGPoint(x: 94.28*bounds.width/320 , y: 35.75*bounds.height/320), controlPoint2:CGPoint(x: 111*bounds.width/320 , y: 20*bounds.height/320)) 149 | path.addCurveToPoint(CGPoint(x: 124.92*bounds.width/320 , y: 43.42*bounds.height/320), controlPoint1: CGPoint(x: 111*bounds.width/320 , y: 20*bounds.height/320), controlPoint2:CGPoint(x: 123.8*bounds.width/320 , y: 31.9*bounds.height/320)) 150 | path.addCurveToPoint(CGPoint(x: 160*bounds.width/320 , y: 39*bounds.height/320), controlPoint1: CGPoint(x: 135.84*bounds.width/320 , y: 40.51*bounds.height/320), controlPoint2:CGPoint(x: 147.66*bounds.width/320 , y: 39*bounds.height/320)) 151 | path.addCurveToPoint(CGPoint(x: 195.08*bounds.width/320 , y: 43.42*bounds.height/320), controlPoint1: CGPoint(x: 172.34*bounds.width/320 , y: 39*bounds.height/320), controlPoint2:CGPoint(x: 184.16*bounds.width/320 , y: 40.51*bounds.height/320)) 152 | path.addCurveToPoint(CGPoint(x: 209*bounds.width/320 , y: 20*bounds.height/320), controlPoint1: CGPoint(x: 196.2*bounds.width/320 , y: 31.9*bounds.height/320), controlPoint2:CGPoint(x: 209*bounds.width/320 , y: 20*bounds.height/320)) 153 | path.addCurveToPoint(CGPoint(x: 223.92*bounds.width/320 , y: 55.68*bounds.height/320), controlPoint1: CGPoint(x: 209*bounds.width/320 , y: 20*bounds.height/320), controlPoint2:CGPoint(x: 225.72*bounds.width/320 , y: 35.75*bounds.height/320)) 154 | path.addCurveToPoint(CGPoint(x: 231.17*bounds.width/320 , y: 60.71*bounds.height/320), controlPoint1: CGPoint(x: 226.44*bounds.width/320 , y: 57.25*bounds.height/320), controlPoint2:CGPoint(x: 228.87*bounds.width/320 , y: 58.93*bounds.height/320)) 155 | path.addCurveToPoint(CGPoint(x: 263*bounds.width/320 , y: 47*bounds.height/320), controlPoint1: CGPoint(x: 237.62*bounds.width/320 , y: 52.5*bounds.height/320), controlPoint2:CGPoint(x: 249.46*bounds.width/320 , y: 47*bounds.height/320)) 156 | path.addCurveToPoint(CGPoint(x: 300*bounds.width/320 , y: 75*bounds.height/320), controlPoint1: CGPoint(x: 283.43*bounds.width/320 , y: 47*bounds.height/320), controlPoint2:CGPoint(x: 300*bounds.width/320 , y: 59.54*bounds.height/320)) 157 | path.addCurveToPoint(CGPoint(x: 258.31*bounds.width/320 , y: 102.78*bounds.height/320), controlPoint1: CGPoint(x: 300*bounds.width/320 , y: 90.46*bounds.height/320), controlPoint2:CGPoint(x: 279.84*bounds.width/320 , y: 102.92*bounds.height/320)) 158 | path.addCurveToPoint(CGPoint(x: 260*bounds.width/320 , y: 119*bounds.height/320), controlPoint1: CGPoint(x: 259.42*bounds.width/320 , y: 107.92*bounds.height/320), controlPoint2:CGPoint(x: 260*bounds.width/320 , y: 113.33*bounds.height/320)) 159 | path.addCurveToPoint(CGPoint(x: 160*bounds.width/320 , y: 199*bounds.height/320), controlPoint1: CGPoint(x: 260*bounds.width/320 , y: 168.71*bounds.height/320), controlPoint2:CGPoint(x: 215.23*bounds.width/320 , y: 199*bounds.height/320)) 160 | path.addCurveToPoint(CGPoint(x: 60*bounds.width/320 , y: 119*bounds.height/320), controlPoint1: CGPoint(x: 104.77*bounds.width/320 , y: 199*bounds.height/320), controlPoint2:CGPoint(x: 60*bounds.width/320 , y: 168.71*bounds.height/320)) 161 | return path.CGPath 162 | } 163 | lazy var snout: CAShapeLayer = { 164 | let l = CAShapeLayer() 165 | l.lineWidth = 6 166 | l.strokeColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 167 | l.fillColor = UIColor(hue: 0.94, saturation: 0.21, brightness: 0.92, alpha: 1).CGColor 168 | self.layer.addSublayer(l) 169 | return l 170 | }() 171 | func snout_path(bounds: CGRect) -> CGPath { 172 | let path = UIBezierPath() 173 | path.moveToPoint(CGPoint(x: 142*bounds.width/320 , y: 163*bounds.height/320)) 174 | path.addCurveToPoint(CGPoint(x: 112*bounds.width/320 , y: 187.5*bounds.height/320), controlPoint1: CGPoint(x: 125.43*bounds.width/320 , y: 163*bounds.height/320), controlPoint2:CGPoint(x: 112*bounds.width/320 , y: 173.97*bounds.height/320)) 175 | path.addCurveToPoint(CGPoint(x: 142*bounds.width/320 , y: 212*bounds.height/320), controlPoint1: CGPoint(x: 112*bounds.width/320 , y: 201.03*bounds.height/320), controlPoint2:CGPoint(x: 125.43*bounds.width/320 , y: 212*bounds.height/320)) 176 | path.addCurveToPoint(CGPoint(x: 160*bounds.width/320 , y: 207.1*bounds.height/320), controlPoint1: CGPoint(x: 148.75*bounds.width/320 , y: 212*bounds.height/320), controlPoint2:CGPoint(x: 154.99*bounds.width/320 , y: 210.18*bounds.height/320)) 177 | path.addCurveToPoint(CGPoint(x: 178*bounds.width/320 , y: 212*bounds.height/320), controlPoint1: CGPoint(x: 165.01*bounds.width/320 , y: 210.18*bounds.height/320), controlPoint2:CGPoint(x: 171.25*bounds.width/320 , y: 212*bounds.height/320)) 178 | path.addCurveToPoint(CGPoint(x: 208*bounds.width/320 , y: 187.5*bounds.height/320), controlPoint1: CGPoint(x: 194.57*bounds.width/320 , y: 212*bounds.height/320), controlPoint2:CGPoint(x: 208*bounds.width/320 , y: 201.03*bounds.height/320)) 179 | path.addCurveToPoint(CGPoint(x: 178*bounds.width/320 , y: 163*bounds.height/320), controlPoint1: CGPoint(x: 208*bounds.width/320 , y: 173.97*bounds.height/320), controlPoint2:CGPoint(x: 194.57*bounds.width/320 , y: 163*bounds.height/320)) 180 | path.addCurveToPoint(CGPoint(x: 160*bounds.width/320 , y: 167.9*bounds.height/320), controlPoint1: CGPoint(x: 171.25*bounds.width/320 , y: 163*bounds.height/320), controlPoint2:CGPoint(x: 165.01*bounds.width/320 , y: 164.82*bounds.height/320)) 181 | path.addCurveToPoint(CGPoint(x: 142*bounds.width/320 , y: 163*bounds.height/320), controlPoint1: CGPoint(x: 154.99*bounds.width/320 , y: 164.82*bounds.height/320), controlPoint2:CGPoint(x: 148.75*bounds.width/320 , y: 163*bounds.height/320)) 182 | return path.CGPath 183 | } 184 | lazy var nostrilLeft: CAShapeLayer = { 185 | let l = CAShapeLayer() 186 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 187 | self.layer.addSublayer(l) 188 | return l 189 | }() 190 | func nostrilLeft_path(bounds: CGRect) -> CGPath { 191 | let path = UIBezierPath() 192 | path.moveToPoint(CGPoint(x: 147*bounds.width/320 , y: 196*bounds.height/320)) 193 | path.addCurveToPoint(CGPoint(x: 156*bounds.width/320 , y: 187*bounds.height/320), controlPoint1: CGPoint(x: 151.97*bounds.width/320 , y: 196*bounds.height/320), controlPoint2:CGPoint(x: 156*bounds.width/320 , y: 191.97*bounds.height/320)) 194 | path.addCurveToPoint(CGPoint(x: 147*bounds.width/320 , y: 178*bounds.height/320), controlPoint1: CGPoint(x: 156*bounds.width/320 , y: 182.03*bounds.height/320), controlPoint2:CGPoint(x: 151.97*bounds.width/320 , y: 178*bounds.height/320)) 195 | path.addCurveToPoint(CGPoint(x: 138*bounds.width/320 , y: 187*bounds.height/320), controlPoint1: CGPoint(x: 142.03*bounds.width/320 , y: 178*bounds.height/320), controlPoint2:CGPoint(x: 138*bounds.width/320 , y: 182.03*bounds.height/320)) 196 | path.addCurveToPoint(CGPoint(x: 147*bounds.width/320 , y: 196*bounds.height/320), controlPoint1: CGPoint(x: 138*bounds.width/320 , y: 191.97*bounds.height/320), controlPoint2:CGPoint(x: 142.03*bounds.width/320 , y: 196*bounds.height/320)) 197 | return path.CGPath 198 | } 199 | lazy var nostrilRight: CAShapeLayer = { 200 | let l = CAShapeLayer() 201 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 202 | self.layer.addSublayer(l) 203 | return l 204 | }() 205 | func nostrilRight_path(bounds: CGRect) -> CGPath { 206 | let path = UIBezierPath() 207 | path.moveToPoint(CGPoint(x: 173*bounds.width/320 , y: 196*bounds.height/320)) 208 | path.addCurveToPoint(CGPoint(x: 182*bounds.width/320 , y: 187*bounds.height/320), controlPoint1: CGPoint(x: 177.97*bounds.width/320 , y: 196*bounds.height/320), controlPoint2:CGPoint(x: 182*bounds.width/320 , y: 191.97*bounds.height/320)) 209 | path.addCurveToPoint(CGPoint(x: 173*bounds.width/320 , y: 178*bounds.height/320), controlPoint1: CGPoint(x: 182*bounds.width/320 , y: 182.03*bounds.height/320), controlPoint2:CGPoint(x: 177.97*bounds.width/320 , y: 178*bounds.height/320)) 210 | path.addCurveToPoint(CGPoint(x: 164*bounds.width/320 , y: 187*bounds.height/320), controlPoint1: CGPoint(x: 168.03*bounds.width/320 , y: 178*bounds.height/320), controlPoint2:CGPoint(x: 164*bounds.width/320 , y: 182.03*bounds.height/320)) 211 | path.addCurveToPoint(CGPoint(x: 173*bounds.width/320 , y: 196*bounds.height/320), controlPoint1: CGPoint(x: 164*bounds.width/320 , y: 191.97*bounds.height/320), controlPoint2:CGPoint(x: 168.03*bounds.width/320 , y: 196*bounds.height/320)) 212 | return path.CGPath 213 | } 214 | lazy var eyeLeft: CAShapeLayer = { 215 | let l = CAShapeLayer() 216 | l.lineWidth = 6 217 | l.strokeColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 218 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 219 | self.layer.addSublayer(l) 220 | return l 221 | }() 222 | func eyeLeft_path(bounds: CGRect) -> CGPath { 223 | let path = UIBezierPath() 224 | path.moveToPoint(CGPoint(x: 128*bounds.width/320 , y: 153*bounds.height/320)) 225 | path.addCurveToPoint(CGPoint(x: 147*bounds.width/320 , y: 123.5*bounds.height/320), controlPoint1: CGPoint(x: 138.49*bounds.width/320 , y: 153*bounds.height/320), controlPoint2:CGPoint(x: 147*bounds.width/320 , y: 139.79*bounds.height/320)) 226 | path.addCurveToPoint(CGPoint(x: 128*bounds.width/320 , y: 94*bounds.height/320), controlPoint1: CGPoint(x: 147*bounds.width/320 , y: 107.21*bounds.height/320), controlPoint2:CGPoint(x: 138.49*bounds.width/320 , y: 94*bounds.height/320)) 227 | path.addCurveToPoint(CGPoint(x: 109*bounds.width/320 , y: 123.5*bounds.height/320), controlPoint1: CGPoint(x: 117.51*bounds.width/320 , y: 94*bounds.height/320), controlPoint2:CGPoint(x: 109*bounds.width/320 , y: 107.21*bounds.height/320)) 228 | path.addCurveToPoint(CGPoint(x: 128*bounds.width/320 , y: 153*bounds.height/320), controlPoint1: CGPoint(x: 109*bounds.width/320 , y: 139.79*bounds.height/320), controlPoint2:CGPoint(x: 117.51*bounds.width/320 , y: 153*bounds.height/320)) 229 | return path.CGPath 230 | } 231 | lazy var eyeBallLeft: CAShapeLayer = { 232 | let l = CAShapeLayer() 233 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 234 | self.layer.addSublayer(l) 235 | return l 236 | }() 237 | func eyeBallLeft_path(bounds: CGRect) -> CGPath { 238 | let path = UIBezierPath() 239 | path.moveToPoint(CGPoint(x: 128*bounds.width/320 , y: 151*bounds.height/320)) 240 | path.addCurveToPoint(CGPoint(x: 142*bounds.width/320 , y: 137*bounds.height/320), controlPoint1: CGPoint(x: 135.73*bounds.width/320 , y: 151*bounds.height/320), controlPoint2:CGPoint(x: 142*bounds.width/320 , y: 144.73*bounds.height/320)) 241 | path.addCurveToPoint(CGPoint(x: 128*bounds.width/320 , y: 123*bounds.height/320), controlPoint1: CGPoint(x: 142*bounds.width/320 , y: 129.27*bounds.height/320), controlPoint2:CGPoint(x: 135.73*bounds.width/320 , y: 123*bounds.height/320)) 242 | path.addCurveToPoint(CGPoint(x: 114*bounds.width/320 , y: 137*bounds.height/320), controlPoint1: CGPoint(x: 120.27*bounds.width/320 , y: 123*bounds.height/320), controlPoint2:CGPoint(x: 114*bounds.width/320 , y: 129.27*bounds.height/320)) 243 | path.addCurveToPoint(CGPoint(x: 128*bounds.width/320 , y: 151*bounds.height/320), controlPoint1: CGPoint(x: 114*bounds.width/320 , y: 144.73*bounds.height/320), controlPoint2:CGPoint(x: 120.27*bounds.width/320 , y: 151*bounds.height/320)) 244 | return path.CGPath 245 | } 246 | lazy var eyeRight: CAShapeLayer = { 247 | let l = CAShapeLayer() 248 | l.lineWidth = 6 249 | l.strokeColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 250 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 1, alpha: 1).CGColor 251 | self.layer.addSublayer(l) 252 | return l 253 | }() 254 | func eyeRight_path(bounds: CGRect) -> CGPath { 255 | let path = UIBezierPath() 256 | path.moveToPoint(CGPoint(x: 192*bounds.width/320 , y: 153*bounds.height/320)) 257 | path.addCurveToPoint(CGPoint(x: 211*bounds.width/320 , y: 123.5*bounds.height/320), controlPoint1: CGPoint(x: 202.49*bounds.width/320 , y: 153*bounds.height/320), controlPoint2:CGPoint(x: 211*bounds.width/320 , y: 139.79*bounds.height/320)) 258 | path.addCurveToPoint(CGPoint(x: 192*bounds.width/320 , y: 94*bounds.height/320), controlPoint1: CGPoint(x: 211*bounds.width/320 , y: 107.21*bounds.height/320), controlPoint2:CGPoint(x: 202.49*bounds.width/320 , y: 94*bounds.height/320)) 259 | path.addCurveToPoint(CGPoint(x: 173*bounds.width/320 , y: 123.5*bounds.height/320), controlPoint1: CGPoint(x: 181.51*bounds.width/320 , y: 94*bounds.height/320), controlPoint2:CGPoint(x: 173*bounds.width/320 , y: 107.21*bounds.height/320)) 260 | path.addCurveToPoint(CGPoint(x: 192*bounds.width/320 , y: 153*bounds.height/320), controlPoint1: CGPoint(x: 173*bounds.width/320 , y: 139.79*bounds.height/320), controlPoint2:CGPoint(x: 181.51*bounds.width/320 , y: 153*bounds.height/320)) 261 | return path.CGPath 262 | } 263 | lazy var eyeBallRight: CAShapeLayer = { 264 | let l = CAShapeLayer() 265 | l.fillColor = UIColor(hue: 0, saturation: 0, brightness: 0, alpha: 1).CGColor 266 | self.layer.addSublayer(l) 267 | return l 268 | }() 269 | func eyeBallRight_path(bounds: CGRect) -> CGPath { 270 | let path = UIBezierPath() 271 | path.moveToPoint(CGPoint(x: 192*bounds.width/320 , y: 151*bounds.height/320)) 272 | path.addCurveToPoint(CGPoint(x: 206*bounds.width/320 , y: 137*bounds.height/320), controlPoint1: CGPoint(x: 199.73*bounds.width/320 , y: 151*bounds.height/320), controlPoint2:CGPoint(x: 206*bounds.width/320 , y: 144.73*bounds.height/320)) 273 | path.addCurveToPoint(CGPoint(x: 192*bounds.width/320 , y: 123*bounds.height/320), controlPoint1: CGPoint(x: 206*bounds.width/320 , y: 129.27*bounds.height/320), controlPoint2:CGPoint(x: 199.73*bounds.width/320 , y: 123*bounds.height/320)) 274 | path.addCurveToPoint(CGPoint(x: 178*bounds.width/320 , y: 137*bounds.height/320), controlPoint1: CGPoint(x: 184.27*bounds.width/320 , y: 123*bounds.height/320), controlPoint2:CGPoint(x: 178*bounds.width/320 , y: 129.27*bounds.height/320)) 275 | path.addCurveToPoint(CGPoint(x: 192*bounds.width/320 , y: 151*bounds.height/320), controlPoint1: CGPoint(x: 178*bounds.width/320 , y: 144.73*bounds.height/320), controlPoint2:CGPoint(x: 184.27*bounds.width/320 , y: 151*bounds.height/320)) 276 | return path.CGPath 277 | } 278 | func moo(bounds: CGRect) { 279 | outline.frame = bounds 280 | outline.path = outline_path(outline.frame) 281 | body.frame = bounds 282 | body.path = body_path(body.frame) 283 | spot2.frame = bounds 284 | spot2.path = spot2_path(spot2.frame) 285 | spot.frame = bounds 286 | spot.path = spot_path(spot.frame) 287 | armLeft.frame = bounds 288 | armLeft.path = armLeft_path(armLeft.frame) 289 | armRight.frame = bounds 290 | armRight.path = armRight_path(armRight.frame) 291 | head.frame = bounds 292 | head.path = head_path(head.frame) 293 | snout.frame = bounds 294 | snout.path = snout_path(snout.frame) 295 | nostrilLeft.frame = bounds 296 | nostrilLeft.path = nostrilLeft_path(nostrilLeft.frame) 297 | nostrilRight.frame = bounds 298 | nostrilRight.path = nostrilRight_path(nostrilRight.frame) 299 | eyeLeft.frame = bounds 300 | eyeLeft.path = eyeLeft_path(eyeLeft.frame) 301 | eyeBallLeft.frame = bounds 302 | eyeBallLeft.path = eyeBallLeft_path(eyeBallLeft.frame) 303 | eyeRight.frame = bounds 304 | eyeRight.path = eyeRight_path(eyeRight.frame) 305 | eyeBallRight.frame = bounds 306 | eyeBallRight.path = eyeBallRight_path(eyeBallRight.frame) 307 | } 308 | -------------------------------------------------------------------------------- /moo_iphone.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charimon/iosViews/5c0d8c4b12b9cacdcdc2483e67fa4eead110dbf0/moo_iphone.png -------------------------------------------------------------------------------- /moo_sketch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charimon/iosViews/5c0d8c4b12b9cacdcdc2483e67fa4eead110dbf0/moo_sketch.png -------------------------------------------------------------------------------- /moo_storyboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Charimon/iosViews/5c0d8c4b12b9cacdcdc2483e67fa4eead110dbf0/moo_storyboard.png -------------------------------------------------------------------------------- /pathExporter.sketchplugin/Contents/Sketch/library.cocoascript: -------------------------------------------------------------------------------- 1 | String.prototype.repeat = function( num ) { 2 | return new Array( num + 1 ).join( this ); 3 | } 4 | String.prototype.replaceAll = function(search, replace){ 5 | if(!search || !replace){return this;} 6 | return this.replace(new RegExp('[' + search + ']', 'g'), replace); 7 | }; 8 | 9 | var Lib = { 10 | alert: function(message) { 11 | var app = [NSApplication sharedApplication]; 12 | 13 | [app displayDialog:message]; 14 | }, 15 | 16 | isArray: function(anything) { 17 | if( Object.prototype.toString.call( anything ) === '[object Array]' ) { 18 | return true 19 | } 20 | return false 21 | }, 22 | //rectangle, circle, vector, etc 23 | isShape: function(item) {return [item isMemberOfClass:[MSShapeGroup class]]; }, 24 | 25 | //normal sketch group 26 | isGroup: function(item) {return [item isMemberOfClass:[MSLayerGroup class]]; }, 27 | 28 | isArtboard: function(item) { return [item isMemberOfClass:[MSArtboardGroup class]]; }, 29 | 30 | paste: function(value) { 31 | var pasteBoard = [NSPasteboard generalPasteboard]; 32 | [pasteBoard declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil]; 33 | [pasteBoard setString:value forType: NSStringPboardType]; 34 | }, 35 | 36 | save: function(name, value) { 37 | var panel = [NSSavePanel savePanel]; 38 | 39 | [panel setMessage:"Where do you want to place the class?"]; 40 | [panel setRequiredFileType: "swift"]; 41 | [panel setCanCreateDirectories: true]; 42 | if (name != null) { 43 | [panel setNameFieldStringValue: name]; 44 | } 45 | 46 | if ([panel runModal] == NSOKButton) { 47 | var filePath = [panel filename]; 48 | var stringValue = [NSString stringWithFormat: @"%@", value]; 49 | 50 | [stringValue writeToFile: filePath atomically: true encoding: NSUTF8StringEncoding error: null]; 51 | } 52 | }, 53 | 54 | toFixed: function(number, precision) { 55 | var power = Math.pow(10, precision || 0); 56 | return String(Math.round(number * power)/power); 57 | } 58 | } 59 | 60 | var Swift = { 61 | safeName: function(name) { return name.replaceAll(" ", "_") }, 62 | 63 | wrapInFrameMethod: function(array, methodName) { 64 | return ["\tfunc " + methodName + "(bounds: CGRect) -> CGPath {", array, "\t}\n"] 65 | }, 66 | 67 | wrapInFrameMethodNoReturn: function(array, methodName) { 68 | return ["\tfunc " + methodName + "(bounds: CGRect) {", array, "\t}"] 69 | }, 70 | 71 | wrapInLazyVariable: function(name, array, type) { 72 | if(type == null) type = "CAShapeLayer" 73 | return ["\tlazy var "+name+": " + type + " = {", array, "\t}()"] 74 | }, 75 | 76 | _flattenArray: function(acc, value, index) { 77 | if(Lib.isArray(value)) { 78 | for(var i=0; i 1) { 135 | log("Unsupported fill type: " + fill.fillType()); 136 | } 137 | } 138 | 139 | swiftCode = swiftCode.concat(Swift.wrapInFrameMethod(processShapePath(thing, artboardFrame), shapePathName ) ) 140 | 141 | return swiftCode 142 | } 143 | 144 | var getFill = function(thing) { 145 | var style = thing.style(); 146 | var fills = style.fills() 147 | 148 | for(var i = fills.count() - 1; i >= 0; i--) { 149 | if(fills[i].isEnabled() && [0, 1].indexOf(fills[i].fillType()) >= 0 ) { 150 | return fills[i] 151 | } 152 | } 153 | 154 | return null; 155 | } 156 | 157 | //MSStyleFill 158 | var extractFill = function(styleFill) { 159 | // Default fillColor is opaque black, so we've to specify an empty fill explicitly 160 | if(styleFill == null) return ["l.fillColor = nil"]; 161 | 162 | var color = styleFill.color(); 163 | var fillType = styleFill.fillType(); 164 | if(fillType == 0) { 165 | return ["l.fillColor = UIColor(hue: " + Lib.toFixed(color.hue(), 2) +", saturation: " + Lib.toFixed(color.saturation(), 2) + ", brightness: " + Lib.toFixed(color.brightness(), 2) + ", alpha: " + Lib.toFixed(color.alpha(), 2) + ").CGColor"] 166 | } else if(fillType == 1 && styleFill.gradient().gradientType() == 0) { 167 | var gradientStops = styleFill.gradient().stops() 168 | var colorsArr = [] 169 | var locationsArr = [] 170 | for(var i=0; i< gradientStops.count(); i ++) { 171 | var stop = gradientStops.objectAtIndex(i) 172 | var color = stop.color() 173 | locationsArr.push("NSNumber(float: " + Lib.toFixed(stop.position(), 2) + ")") 174 | colorsArr.push("UIColor(hue: " + Lib.toFixed(color.hue(), 2) +", saturation: " + Lib.toFixed(color.saturation(), 2) + ", brightness: " + Lib.toFixed(color.brightness(), 2) + ", alpha: " + Lib.toFixed(color.alpha(), 2) + ").CGColor") 175 | } 176 | 177 | var from = styleFill.gradient().from() 178 | var to = styleFill.gradient().to() 179 | 180 | return ["l.colors = ["+colorsArr.toString()+"]", 181 | "l.locations = ["+locationsArr.toString()+"]", 182 | "l.startPoint = CGPointMake(" + Lib.toFixed(from.x, 2) + ", " + Lib.toFixed(from.y, 2) + ")", 183 | "l.endPoint = CGPointMake(" + Lib.toFixed(to.x, 2) + ", " + Lib.toFixed(to.y, 2) + ")"] 184 | } else if(fillType == 1) { 185 | log("Unsupported gradient type: " + styleFill.gradient().gradientType()); 186 | } 187 | return ["l.fillColor = nil"] 188 | } 189 | 190 | var extractStroke = function(style) { 191 | // Default stroke is nil, so no need to specify anything 192 | var array = [] 193 | 194 | var borders = style.borders() 195 | 196 | if (borders != null && borders.count() > 0) { 197 | var borderOptions = style.borderOptions() 198 | var lineJoin = borderOptions.lineJoinStyle(); 199 | var lineCap = borderOptions.lineCapStyle(); 200 | var dashPattern = borderOptions.dashPattern().componentsJoinedByString(",") 201 | 202 | for(var i = borders.count() - 1; i >= 0; i--) { 203 | if(borders[i].isEnabled() && borders[i].position() == 0) { 204 | var color = borders[i].color(); 205 | array.push("l.lineWidth = " + borders[i].thickness()) 206 | array.push("l.lineDashPattern = [" + dashPattern + "]") 207 | array.push("l.lineJoin = " + ["kCALineJoinMiter", "kCALineJoinRound", "kCALineJoinBevel"][lineJoin]) 208 | array.push("l.lineCap = " + ["kCALineCapButt", "kCALineCapRound", "kCALineCapSquare"][lineCap]) 209 | array.push("l.strokeColor = UIColor(hue: " + Lib.toFixed(color.hue(), 2) +", saturation: " + Lib.toFixed(color.saturation(), 2) + ", brightness: " + Lib.toFixed(color.brightness(), 2) + ", alpha: " + Lib.toFixed(color.alpha(), 2) + ").CGColor") 210 | } 211 | } 212 | } 213 | return array 214 | } 215 | 216 | var processShapePath = function(anything, boundsRect) { 217 | if(!Lib.isShape(anything)) { return null; } 218 | 219 | var swiftCode = ["let path = UIBezierPath()", "let wdtRatio = bounds.width/" + boundsRect.width(), "let hgtRatio = bounds.height/" + boundsRect.height()] 220 | 221 | for (var j = 0; j < anything.layers().count(); j++) { 222 | var layer = anything.layers().objectAtIndex(j) 223 | 224 | var path = layer.path() 225 | var pointsCount = path.numberOfPoints() 226 | 227 | for(var i = 0; i < pointsCount; i++) { addPoint(swiftCode, layer, path, i, i == 0); } 228 | if(path.isClosed()) { 229 | addPoint(swiftCode, layer, path, 0, false); 230 | swiftCode.push("path.closePath()"); 231 | } 232 | } 233 | swiftCode.push("return path.CGPath"); 234 | 235 | return swiftCode 236 | } 237 | 238 | var addPoint = function(acc, layer, path, index, isFirst) { 239 | var offsetX = CGRectGetMinX(layer.frameInArtboard()) 240 | var offsetY = CGRectGetMinY(layer.frameInArtboard()) 241 | 242 | var pathPoint = path.pointAtIndex(index); 243 | var abs_point = layer.absolutePoint(pathPoint.point()) 244 | 245 | var abs_pointTo = null 246 | if(pathPoint.hasCurveTo()) { abs_pointTo = layer.absolutePoint(pathPoint.curveTo()); } 247 | 248 | var prev_abs_pointFrom = null 249 | if(index >= 0 && !isFirst) { 250 | var prevPoint = path.pointAtIndex( (index-1 + path.numberOfPoints()) % path.numberOfPoints() ); 251 | if(prevPoint.hasCurveFrom()) { prev_abs_pointFrom = layer.absolutePoint(prevPoint.curveFrom()); } 252 | } 253 | 254 | if(index == 0 && isFirst) { acc.push("path.moveToPoint("+relPointOffset(abs_point, offsetX, offsetY)+")") } 255 | else if(prev_abs_pointFrom && abs_pointTo) { 256 | acc.push("path.addCurveToPoint("+relPointOffset(abs_point, offsetX, offsetY)+", controlPoint1: "+relPointOffset(prev_abs_pointFrom, offsetX, offsetY)+", controlPoint2:"+relPointOffset(abs_pointTo, offsetX, offsetY)+")") 257 | } else if(prev_abs_pointFrom || abs_pointTo) { 258 | var controlPoint = prev_abs_pointFrom || abs_pointTo 259 | acc.push("path.addQuadCurveToPoint("+relPointOffset(abs_point, offsetX, offsetY)+", controlPoint: "+relPointOffset(controlPoint, offsetX, offsetY)+")") 260 | } 261 | else { 262 | acc.push("path.addLineToPoint("+relPointOffset(abs_point, offsetX, offsetY)+")") 263 | } 264 | } 265 | 266 | var relPointOffset = function(point, offsetX, offsetY) { 267 | var x = Lib.toFixed(parseFloat(point.x) + parseFloat(offsetX), 2 ) 268 | var y = Lib.toFixed(parseFloat(point.y) + parseFloat(offsetY), 2 ) 269 | var widthString = "*wdtRatio" 270 | var heightString = "*hgtRatio") 271 | return "CGPoint(x: " + x + widthString + " , y: " + y + heightString + ")" 272 | } 273 | 274 | var relRect = function(rect, frame) { 275 | var x = rect.x() 276 | var y = rect.y() 277 | var width = rect.width() 278 | var height = rect.height() 279 | var frame_width = frame.width() 280 | var frame_height = frame.height() 281 | 282 | return "CGRect(x: " + Lib.toFixed(x, 2) + " * bounds.width/"+Lib.toFixed(frame_width, 2) + 283 | ", y: " + Lib.toFixed(y, 2) + " * bounds.height/"+Lib.toFixed(frame_height, 2) + 284 | ", width: " + Lib.toFixed(width, 2) + " * bounds.width/"+Lib.toFixed(frame_width, 2) + 285 | ", height: " + Lib.toFixed(height, 2) + " * bounds.height/"+Lib.toFixed(frame_height, 2)+")" 286 | } 287 | --------------------------------------------------------------------------------