├── .gitignore ├── README.md ├── Skew.sketchplugin └── Contents │ ├── Resources │ ├── icon-main.png │ ├── icon-skew-horizontal.png │ └── icon-skew-vertical.png │ └── Sketch │ ├── manifest.json │ └── script.cocoascript ├── appcast.xml └── screengrab.gif /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # Sketch Plugin: Skew! 4 | 5 | A Sketch plugin for skewing (or shearing) shapes horizontally or vertically. 6 | 7 | img 8 | 9 | ## To do 10 | 11 | - Functionality for skewing beziers 12 | 13 | ## Installation 14 | 15 | #### Install from repo 16 | 17 | 1. Download the latest *.zip and unzip 18 | 2. Double click on the .sketchplugin 19 | 3. If all went well Sketch just installed the plugin!` 20 | 21 | Or simply install via Sketch Runner 22 | 23 | #### Usage 24 | 25 | 1. Select some shapes or groups of shapes 26 | 2. Select one of the Skew options via the menu (or use Runner) 27 | 3. A window pops up and asks for a skew degree between -90 and 90 degrees. Hit enter. 28 | 4. Boom! Your shapes are skewed by given degrees. 😎 29 | 30 | --- 31 | 32 | 33 | -------------------------------------------------------------------------------- /Skew.sketchplugin/Contents/Resources/icon-main.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mheesakkers/sketch-plugin-skew/a24cf1ecc89c5374f8967dc36571c7493a4c8d67/Skew.sketchplugin/Contents/Resources/icon-main.png -------------------------------------------------------------------------------- /Skew.sketchplugin/Contents/Resources/icon-skew-horizontal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mheesakkers/sketch-plugin-skew/a24cf1ecc89c5374f8967dc36571c7493a4c8d67/Skew.sketchplugin/Contents/Resources/icon-skew-horizontal.png -------------------------------------------------------------------------------- /Skew.sketchplugin/Contents/Resources/icon-skew-vertical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mheesakkers/sketch-plugin-skew/a24cf1ecc89c5374f8967dc36571c7493a4c8d67/Skew.sketchplugin/Contents/Resources/icon-skew-vertical.png -------------------------------------------------------------------------------- /Skew.sketchplugin/Contents/Sketch/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "author" : "Misha Heesakkers", 3 | "identifier" : "com.mishaheesakkers.sketch.skew", 4 | "version" : "3.0", 5 | "description" : "Skew (or shear) shapes horizontally or vertically.", 6 | "authorEmail" : "misha.heesakkers@gmail.com", 7 | "name" : "Skew!", 8 | "icon" : "icon-main.png", 9 | "appcast" : "https://raw.githubusercontent.com/mheesakkers/sketch-plugin-skew/master/appcast.xml", 10 | "commands" : [ 11 | { 12 | "script" : "script.cocoascript", 13 | "name" : "Skew horizontally...", 14 | "handler" : "skewHorizontalHandler", 15 | "identifier" : "skew-horizontally", 16 | "icon" : "icon-skew-horizontal.png" 17 | }, 18 | { 19 | "script" : "script.cocoascript", 20 | "name" : "Skew vertically...", 21 | "handler" : "skewVerticalHandler", 22 | "identifier" : "skew-vertically", 23 | "icon" : "icon-skew-vertical.png" 24 | } 25 | 26 | ], 27 | "menu" : { 28 | "isRoot": false, 29 | "items" : [ 30 | "skew-horizontally", 31 | "skew-vertically" 32 | ] 33 | } 34 | } -------------------------------------------------------------------------------- /Skew.sketchplugin/Contents/Sketch/script.cocoascript: -------------------------------------------------------------------------------- 1 | var onRun = function(context, skewHorizontal = true) { 2 | var sketch = require('sketch') 3 | var UI = require('sketch/ui') 4 | var doc = context.document 5 | var selection = sketch.getSelectedDocument().selectedLayers 6 | 7 | var inputSkewAngle = parseFloat( [doc askForUserInput:"Define a skew angle (Range: -90 - 90)?" initialValue:"10"] ).toFixed(1) 8 | inputSkewAngle = checkInputSkewAngle(inputSkewAngle) 9 | 10 | if (selection.length > 0) { 11 | 12 | // Loop through selection and get all shape layers 13 | var shapeLayers = []; 14 | selection.forEach( function iterate(layer) { 15 | layer.type === 'ShapePath' && shapeLayers.push(layer.sketchObject); 16 | layer.type === 'Text' && UI.message('This plugins works only for shape layers.') 17 | layer.type === 'Image' && UI.message('This plugins works only for shape layers.') 18 | if (layer.layers) { 19 | layer.layers.forEach(iterate) 20 | } 21 | // log(layer.type); 22 | }); 23 | 24 | // Loop over shape layers 25 | shapeLayers.forEach(layer => { 26 | const shape = layer.isMemberOfClass(MSShapeGroup) ? layer.layers()[0] : layer 27 | // shape.flattenedLayer(); 28 | 29 | var shapeWidth = shape.absoluteRect().width() 30 | var shapeHeight = shape.absoluteRect().height() 31 | var points = shape.points() 32 | 33 | if (points.length > 0) { 34 | if (skewHorizontal) { 35 | const skewAngleFactor = shapeHeight / shapeWidth 36 | // log(skewAngleFactor) 37 | points.forEach(p => { 38 | p.point = skewX( p.point(), inputSkewAngle, skewAngleFactor) 39 | }) 40 | UI.message('Skewed horizontally by ' + inputSkewAngle + '°') 41 | } else { 42 | const skewAngleFactor = shapeWidth / shapeHeight 43 | // log(skewAngleFactor) 44 | points.forEach(p => { 45 | const skewAngleFactor = shapeWidth / shapeHeight 46 | p.point = skewY( p.point(), inputSkewAngle, skewAngleFactor) 47 | }) 48 | UI.message('Skewed vertically by ' + inputSkewAngle + '°') 49 | } 50 | } 51 | 52 | var flattened = shape.flattenedLayer(); // Converts custom shapes into MSShapePathLayer 53 | 54 | var flattener = MSLayerFlattener.alloc().init(); 55 | flattener.flattenLayer_options(flattened, 2);// includes removing duplicate points 56 | 57 | var group = shape.parentGroup(); 58 | group.insertLayer_afterLayer(flattened, shape); 59 | group.removeLayer(shape); 60 | 61 | }) 62 | 63 | } else { 64 | UI.message('No shape layers selected.') 65 | } 66 | } 67 | 68 | // Skew functionality 69 | function skewX (point, angle, factor) { 70 | const skewedX = point.x + point.y * (1 / Math.tan( -toRadians( 270.0 - angle)) ) * factor // 270 degrees is the base angle & I invert the radians to match Illustrators orientation 71 | return { x: skewedX, y: point.y } // Return horizontal skew 72 | } 73 | 74 | function skewY (point, angle, factor) { 75 | const skewedY = point.y + point.x * (1 / Math.tan( toRadians( 270.0 - angle)) ) * factor 76 | return { x: point.x, y: skewedY } // Return vertical skew 77 | } 78 | 79 | function checkInputSkewAngle (angle) { 80 | var UI = require('sketch/ui') 81 | var maxmin = 89 82 | 83 | if (angle < -maxmin) { 84 | angle = -maxmin 85 | UI.message('Skew angle is set to -' + maxmin + ', the min limit to skew. Otherwise the artwork gets too big.') 86 | } 87 | if (angle > maxmin) { 88 | angle = maxmin 89 | UI.message('Skew angle is set to ' + maxmin + ', the max limit to skew. Otherwise the artwork gets too big.') 90 | } 91 | 92 | return angle; 93 | } 94 | 95 | // Helpers // 96 | function toRadians (angle) { 97 | return angle * (Math.PI / 180); 98 | } 99 | 100 | // Command handlers 101 | var skewHorizontalHandler = function (context) { 102 | onRun(context, true) 103 | } 104 | 105 | var skewVerticalHandler = function (context) { 106 | onRun(context, false) 107 | } 108 | 109 | // Doesn't work with: 110 | // 1. Bezier points give wrong results 111 | // 2. Multiple shapes -------------------------------------------------------------------------------- /appcast.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Sketch Plugin: Skew! 5 | http://sparkle-project.org/files/sparkletestcast.xml 6 | A Sketch plugin for skewing (or shearing) shapes horizontally or vertically. 7 | en 8 | 9 | Version 3.0 10 | 11 | 13 |
  • Made compatible with Sketch v53.1
  • 14 | 15 | ]]> 16 |
    17 | 18 |
    19 | 20 | Version 2.0 21 | 22 | 24 |
  • Improved skewing/shearing that matches Adobe Illustrator.
  • 25 | 26 | ]]> 27 |
    28 | 29 |
    30 | 31 | Version 1.1 32 | 33 | 35 |
  • Made compatible with Sketch v52
  • 36 | 37 | ]]> 38 |
    39 | 40 |
    41 | 42 | Version 1.0 43 | 44 | 46 |
  • First release
  • 47 | 48 | ]]> 49 |
    50 | 51 |
    52 |
    53 |
    -------------------------------------------------------------------------------- /screengrab.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mheesakkers/sketch-plugin-skew/a24cf1ecc89c5374f8967dc36571c7493a4c8d67/screengrab.gif --------------------------------------------------------------------------------