• Global community
    • Language:
      • Deutsch
      • English
      • Espaรฑol
      • Franรงais
      • Portuguรชs
  • ๆ—ฅๆœฌ่ชžใ‚ณใƒŸใƒฅใƒ‹ใƒ†ใ‚ฃ
    Dedicated community for Japanese speakers
  • ํ•œ๊ตญ ์ปค๋ฎค๋‹ˆํ‹ฐ
    Dedicated community for Korean speakers

๐Ÿ”Ž Quick Tips: How to draw lines and arrows

Adobe Employee ,
Aug 26, 2022 Aug 26, 2022

Copy link to clipboard

Copied

โ€ƒ

 

2QUICK TIPS format header.jpg

 

Lines and Arrows

 

Did you know you can draw lines and arrows with the line tool?  You can make a pixel based line, or if you want to make a scalable line that you can edit later, you can use the Shape mode and draw a vector line. Follow the steps below to draw either type of line. You can also check out the video showing how to draw a shape based line with an arrowhead.

 

 

 

 

How to draw a Shape based line with an arrowhead

 

โถ  Click and hold the Shape tool group iconps-shapetool.png ) in the toolbar to bring up the tool options and select the Line tool.

Note: any one of these shapes may be visible on the toolbar. On mine, the rectangle was showing. The one showing will be determined by which one was used most recently.

 

Screen Shot 2022-06-20 at 3.53.58 PM.png

โ€ƒ

 

โท Choose Shape from the line mode options.

โธ Set the Fill color in the Options bar to the color you want the line to be.

โน Set the line width of the line by adjusting the Weight in the Options bar.

 

Options bar.jpg

โ€ƒ

โบ Click on the gear on the options bar to see arrowhead options.

โป Click on Start and/or End to create an arrowhead at either end of the line.

โผ Set the width, length, and concavity for your arrowhead.

 

Screen Shot 2022-08-10 at 5.03.02 PM.png

    

โฝ If you want to have an outline around the arrow, You can set the color and thickness of the stroke in the menu bar.

 

stroke line.jpg

โ€ƒ

 

โพ Now, to draw the arrow, just click and drag in the canvas to draw a line. Hold shift to constrain the line to the nearest 45 degrees.

 

Arrow samples.jpg

 

For more information about line options, visit Work with the line tool.

 

 

How to draw a Pixel based line

 

โถ Click and hold the Shape tool group icon ( ps-shapetool.png ) in the toolbar to bring up the shape tool choices and Select the Line tool.

 

Screen Shot 2022-06-20 at 3.53.58 PM.png

 

 

โท Click on the options pulldown and select Pixel

pixel mode.jpg

โ€ƒ

 

โธ Set the Weight in Pixels in the Options bar.

โน Set the foreground color to the color you want the line to be

 

Screen Shot 2022-08-09 at 5.16.25 PM.png

โ€ƒ

โป (Optional) Create arrowheads.

  • If you want arrowheads, click on the gear on the options bar to see options.
  • Click on Start and/or End to create an arrowhead at either end of the line.
  • Set the width, length, and concavity for your arrowhead.

 

โบ Click and drag in the canvas to draw a line. Hold shift to keep the  line straight  and aligned to the nearest 45 degrees.

 

Besides drawing your own arrows using lines and arrowheads, you can also use custom shapes. See Find and use Legacy Shapes to learn how to get to the legacy shapes. In the All Legacy Default Shapes folder, you will find an entire folder of different types of arrows.

 

If you want to learn more about Photoshop in little bite-sized chunks, visit our Photoshop Quick Tips home page. It's loaded with tips, features, and projects you can try,

 

Related links:

Find and use Legacy Shapes

Work with the line tool

Draw and edit shapes

Drawing shapes just got easier

 

 

 

 

 

 

TOPICS
macOS , Windows

Views

1.8K

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 10, 2022 Sep 10, 2022

Copy link to clipboard

Copied

This is really hellpful, thank you!

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 20, 2022 Sep 20, 2022

Copy link to clipboard

Copied

This is really hellpful, thanks 

 

Likes

 
https://dobocaocap.online

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 23, 2022 Sep 23, 2022

Copy link to clipboard

Copied

PhotoShop is one of the best applications for graphic designers and many other careers, it has made life so easy. It was a very useful video <site removed by moderator>.

Thanks for the tips, it was a great help.

Digital Transformation Partner<br />Mobile App Development Company<br />>DxMinds<br />Digital Transformation Partner<br />Mobile App Development Company<br />
https://dxminds.com/top-5-mobile-app-development-companies-in-dubai-uae/

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
New Here ,
Sep 28, 2022 Sep 28, 2022

Copy link to clipboard

Copied

ghรช za, ฤ‘รณ h xร i adobe cลฉ khรดng biแบฟt gรฌ hแบฟt trฦกn

 

>Nhแบฑm mang lแบกi hiแป‡u quแบฃ tแป‘t nhแบฅt mร  vแบซn ฤ‘แบฃm bแบฃo ฤ‘ฦฐแปฃc sแปฑ an toร n vแป sแปฉc khแปe cลฉng nhฦฐ khแบฃ nฤƒng sinh sแบฃn cแปงa chแป‹ em phแปฅ nแปฏ, Phรฒng khรกm ฤa khoa Hแป“ng Phรกt luรดn thแปฑc hiแป‡n ฤ‘แบงy ฤ‘แปง cรกc bฦฐแป›c thฤƒm khรกm vร  chฤƒm sรณc sแปฉc khแปe trฦฐแป›c khi ฤ‘ฦฐa ra bแบฅt cแปฉ phฦฐฦกng รกn ฤ‘รฌnh chแป‰ thai kแปณ nร o.<br />

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

Great resource, thanks

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

And if you want to edit a line or arrow, without having to redraw it, you can use this script:

 

#target photoshop

//copyright 2017 Chuck Uebele, all rights reserved
//Use at your own risk.

var xmlFile = new File(Folder.desktop+'/ArrowPrefs.xml');
var xmlPref

if(xmlFile.exists){
    xmlPref = readXMLFile (xmlFile)
    }
else{xmlPref = new XML('<root><prefs><lines/><arrows/></prefs>')};


//varables for lines and points
var run = true;
var lineType;
var origLineWidth;
var lineAngTan1;//from first point to oppsite side of line
var lineAngTan2;//From oppsite side of line to first point
var lineLengthAng;
var lineLength;
var lineMid1;//mid width on line from first point
var lineMid2;//mid width on line from oppsite end of line
var newWidth = 20
var ptTemp1
var ptTemp2
var ptTemp3
var ptTemp4
var dropLst = new Array()
var prefsDrop

var headIntersect1;
var headIntersect2;
//-----------
var arrowLength;
var arrowWidth;
var arrowEndsMid;
var arrowConcave;
var arrowConcaveFactor;
var arrowLengthFactor;
var arrowWidthFactor;
/////////////////

app.preferences.rulerUnits = Units.PIXELS;
try{
    var doc = activeDocument
    var sLay = doc.activeLayer
    var sLayName = sLay.name + ' Shape Path'
    var cPath = doc.pathItems.getByName(sLayName)
    var ptArray = new Array();
    var ptNewArray = new Array();
    var idPath;

recordAnchors (cPath);
var numAnchors = ptArray.length;
    }
catch(e){
    run = false;
    var numAnchors=0
    }


switch(numAnchors){
    case 4:
        lineType = 'Normal Line'
        origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);
        lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);
        lineAngTan2 = getAng (ptArray[1][0], ptArray[1][1], ptArray[0][0], ptArray[0][1]);
        lineMid1 = [(ptArray[0][0] + ptArray[1][0])/2,(ptArray[0][1] + ptArray[1][1])/2 ];  
        lineMid2 = [(ptArray[2][0] + ptArray[3][0])/2,(ptArray[2][1] + ptArray[3][1])/2 ];
        
        ui ();
        
        ptNewArray[0] = newPt (lineMid1[0],lineMid1[1], newWidth/2, lineAngTan1);
        ptNewArray[3] = newPt (lineMid2[0],lineMid2[1], newWidth/2, lineAngTan1);
        ptNewArray[1] = newPt (lineMid1[0],lineMid1[1], newWidth/2, lineAngTan2);
        ptNewArray[2] = newPt (lineMid2[0],lineMid2[1], newWidth/2, lineAngTan2);


        break;
    case 7:
        if(Math.round (getAng (ptArray[0][0], ptArray[0][1], ptArray[6][0], ptArray[6][1]))==Math.round (getAng (ptArray[1][0], ptArray[1][1], ptArray[2][0], ptArray[2][1]))){
            lineType = 'Single Arrow End';
            origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);
            lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[1][0], ptArray[1][1]);
            lineAngTan2 = getAng (ptArray[1][0], ptArray[1][1], ptArray[0][0], ptArray[0][1]);
            lineMid1 = [(ptArray[1][0] + ptArray[0][0])/2,(ptArray[1][1] + ptArray[0][1])/2 ];  
            lineMid2 = [(ptArray[2][0] + ptArray[6][0])/2,(ptArray[2][1] + ptArray[6][1])/2 ];
            arrowEndsMid = [(ptArray[3][0] + ptArray[5][0])/2,(ptArray[3][1] + ptArray[5][1])/2 ];            
            arrowLength = lineL (ptArray[4][0], ptArray[4][1], arrowEndsMid[0], arrowEndsMid[1]);
            
            var arrowLength2 
            arrowWidth = lineL (ptArray[5][0], ptArray[5][1], ptArray[3][0], ptArray[3][1]);   
            $.writeln(arrowLength +'=='+arrowWidth)
            arrowConcaveFactor = getConcaveFactor (ptArray[6][0], ptArray[6][1], ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1], ptArray[5][0], ptArray[5][1], ptArray[3][0], ptArray[3][1]);
            arrowLengthFactor = Math.round((arrowLength/origLineWidth)*100);
            arrowWidthFactor = Math.round((arrowWidth/origLineWidth)*100);            
            lineLengthAng = getAng (arrowEndsMid[0], arrowEndsMid[1],ptArray[4][0], ptArray[4][1]);
            //////////////////////////////////////

            ui ()
            //New points    
            arrowEndsMid = newPt (ptArray[4][0], ptArray[4][1], arrowLengthFactor, lineLengthAng); 
            ptNewArray[5] = newPt (arrowEndsMid[0], arrowEndsMid[1], (arrowWidthFactor)/2, lineAngTan1);
            ptNewArray[3] = newPt (arrowEndsMid[0], arrowEndsMid[1], (arrowWidthFactor)/2, lineAngTan2);
            ptNewArray[1] = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan2);
            ptNewArray[0] = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan1);           
            ptTemp1 = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan1);            
            ptTemp2 = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan2);              
            headIntersect1= getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[0][0], ptNewArray[0][1], ptArray[4][0], ptArray[4][1], ptNewArray[5][0], ptNewArray[5][1]);            
            headIntersect2= getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[1][0], ptNewArray[1][1], ptArray[4][0], ptArray[4][1], ptNewArray[3][0], ptNewArray[3][1]);            
            ptTemp3 = getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[0][0], ptNewArray[0][1], ptNewArray[5][0], ptNewArray[5][1], ptNewArray[3][0], ptNewArray[3][1]);            
            ptTemp4 = getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[5][0], ptNewArray[5][1], ptNewArray[3][0], ptNewArray[3][1]);            
            arrowConcave = lineL (headIntersect1[0], headIntersect1[1], ptTemp3[0], ptTemp3[1])*arrowConcaveFactor*.01;            
            ptNewArray[6] = newPt (ptTemp3[0], ptTemp3[1], -arrowConcave, lineLengthAng);            
            ptNewArray[2] = newPt (ptTemp4[0], ptTemp4[1], -arrowConcave, lineLengthAng);   
            }
        else{
            //alert('beginning')  
            lineType = 'Single Arrow Start';
            origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);
            lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);
            lineAngTan2 = getAng (ptArray[4][0], ptArray[4][1], ptArray[0][0], ptArray[0][1]);
            lineMid1 = [(ptArray[4][0] + ptArray[0][0])/2,(ptArray[4][1] + ptArray[0][1])/2 ];  
            lineMid2 = [(ptArray[5][0] + ptArray[6][0])/2,(ptArray[5][1] + ptArray[6][1])/2 ];
            arrowEndsMid = [(ptArray[1][0] + ptArray[3][0])/2,(ptArray[1][1] + ptArray[3][1])/2 ]
            arrowLength = lineL (ptArray[2][0], ptArray[2][1], arrowEndsMid[0], arrowEndsMid[1]);         
            arrowWidth = lineL (ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1]);
            arrowConcaveFactor = getConcaveFactor (ptArray[0][0], ptArray[0][1], ptArray[6][0], ptArray[6][1], ptArray[2][0], ptArray[2][1], ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1])
            arrowLengthFactor = Math.round((arrowLength/origLineWidth)*100);
            arrowWidthFactor = Math.round((arrowWidth/origLineWidth)*100);
            lineLengthAng = getAng (arrowEndsMid[0], arrowEndsMid[1],ptArray[2][0], ptArray[2][1]);
              
            //////////////////////////////////////
            ui ()
            //New points
            arrowEndsMid = newPt (ptArray[2][0], ptArray[2][1], arrowLengthFactor, lineLengthAng);
            ptNewArray[1] = newPt (arrowEndsMid[0], arrowEndsMid[1], (arrowWidthFactor)/2, lineAngTan1);
            ptNewArray[3] = newPt (arrowEndsMid[0], arrowEndsMid[1], (arrowWidthFactor)/2, lineAngTan2);
            ptNewArray[5] = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan2);
            ptNewArray[6] = newPt (lineMid2[0], lineMid2[1], newWidth/2, lineAngTan1);
            ptTemp1 = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan1);
            ptTemp2 = newPt (lineMid1[0], lineMid1[1], newWidth/2, lineAngTan2);    
            headIntersect1= getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[6][0], ptNewArray[6][1], ptArray[2][0], ptArray[2][1], ptNewArray[1][0], ptNewArray[1][1])
            headIntersect2= getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[5][0], ptNewArray[5][1], ptArray[2][0], ptArray[2][1], ptNewArray[3][0], ptNewArray[3][1])
            ptTemp3 = getIntersect (ptTemp1[0], ptTemp1[1], ptNewArray[6][0], ptNewArray[6][1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1])
            ptTemp4 = getIntersect (ptTemp2[0], ptTemp2[1], ptNewArray[5][0], ptNewArray[5][1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1])
            arrowConcave = lineL (headIntersect1[0], headIntersect1[1], ptTemp3[0], ptTemp3[1])*arrowConcaveFactor*.01;
            ptNewArray[0] = newPt (ptTemp3[0], ptTemp3[1], -arrowConcave, lineLengthAng);
            ptNewArray[4] = newPt (ptTemp4[0], ptTemp4[1], -arrowConcave, lineLengthAng);
            }
    
        break;
    case 10:
            lineType = 'Double Arrow';
            origLineWidth = lineL (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);
            lineAngTan1 = getAng (ptArray[0][0], ptArray[0][1], ptArray[4][0], ptArray[4][1]);
            lineAngTan2 = getAng (ptArray[4][0], ptArray[4][1], ptArray[0][0], ptArray[0][1]);                 
            arrowEndsMid = [(ptArray[1][0] + ptArray[3][0])/2,(ptArray[1][1] + ptArray[3][1])/2 ];            
            arrowLength = lineL (ptArray[2][0], ptArray[2][1], arrowEndsMid[0], arrowEndsMid[1]);             
            arrowWidth = lineL (ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1]);            
            arrowConcaveFactor = getConcaveFactor (ptArray[0][0], ptArray[0][1], ptArray[9][0], ptArray[9][1], ptArray[2][0], ptArray[2][1], ptArray[1][0], ptArray[1][1], ptArray[3][0], ptArray[3][1]);
            arrowLengthFactor = Math.round((arrowLength/origLineWidth)*100);
            arrowWidthFactor = Math.round((arrowWidth/origLineWidth)*100);
            lineLengthAng = getAng (ptArray[7][0], ptArray[7][1],ptArray[2][0], ptArray[2][1]);    
            /////////////////////////////////////////////
            ui ()
            //new points
            arrowEndsMid = newPt (ptArray[2][0], ptArray[2][1], arrowLengthFactor, lineLengthAng);
            ptNewArray[1] = newPt (arrowEndsMid[0], arrowEndsMid[1], (arrowWidthFactor )/2, lineAngTan1);            
            ptNewArray[3] = newPt (arrowEndsMid[0], arrowEndsMid[1], (arrowWidthFactor )/2, lineAngTan2);
            arrowEndsMid = newPt (ptArray[7][0], ptArray[7][1], -arrowLengthFactor, lineLengthAng); 
            ptNewArray[8] = newPt (arrowEndsMid[0], arrowEndsMid[1], (arrowWidthFactor)/2, lineAngTan1);            
            ptNewArray[6] = newPt (arrowEndsMid[0], arrowEndsMid[1], (arrowWidthFactor)/2, lineAngTan2);            
            ptTemp1 = newPt (ptArray[2][0], ptArray[2][1], newWidth/2, lineAngTan1);
            var ptTemp1a = newPt (ptArray[7][0], ptArray[7][1], newWidth/2, lineAngTan1);
            ptTemp2 = newPt (ptArray[2][0], ptArray[2][1], newWidth/2, lineAngTan2);
            var ptTemp2a = newPt (ptArray[7][0], ptArray[7][1], newWidth/2, lineAngTan2);
            
            headIntersect1= getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptArray[2][0], ptArray[2][1], ptNewArray[1][0], ptNewArray[1][1]);
            headIntersect2= getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptArray[2][0], ptArray[2][1], ptNewArray[3][0], ptNewArray[3][1]);
            var headIntersect3= getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptArray[7][0], ptArray[7][1], ptNewArray[8][0], ptNewArray[8][1]);
            var headIntersect4= getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptArray[7][0], ptArray[7][1], ptNewArray[6][0], ptNewArray[6][1]); 
            ptTemp3 = getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1]);
            var ptTemp3a = getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptNewArray[1][0], ptNewArray[1][1], ptNewArray[3][0], ptNewArray[3][1]);
            ptTemp4 = getIntersect (ptTemp1[0], ptTemp1[1], ptTemp1a[0], ptTemp1a[1], ptNewArray[6][0], ptNewArray[6][1], ptNewArray[8][0], ptNewArray[8][1]);
            var ptTemp4a = getIntersect (ptTemp2[0], ptTemp2[1], ptTemp2a[0], ptTemp2a[1], ptNewArray[6][0], ptNewArray[6][1], ptNewArray[8][0], ptNewArray[8][1]);
            
           arrowConcave = lineL (headIntersect1[0], headIntersect1[1], ptTemp3[0], ptTemp3[1])*arrowConcaveFactor*.01;
           ptNewArray[0] = newPt (ptTemp3[0], ptTemp3[1], -arrowConcave, lineLengthAng);
           ptNewArray[4] = newPt (ptTemp3a[0], ptTemp3a[1], -arrowConcave, lineLengthAng);      
           
           ptNewArray[9] = newPt (ptTemp4[0], ptTemp4[1], arrowConcave, lineLengthAng);
           ptNewArray[5] = newPt (ptTemp4a[0], ptTemp4a[1], arrowConcave, lineLengthAng);              
            
        break;
        default:
        run = false;
        alert("The layer selected didn't match the criteria for a line or arrow")
    }//end switch

if(run){
    var myPathInfo = mkNewPathInfo ();
    deltPath ();
    var tempPath = app.activeDocument.pathItems.add( 'temp', myPathInfo);
    selPath ();
    doc.activeLayer = sLay;
    mkPath ()
    tempPath.remove();
    }

////////////////////////////////////
function ui(){
    var dlg = new Window('dialog','Edit Line Tool Line');
        dlg.alignChildren = ['left','top'];
            dlg.lType = dlg.add('statictext',undefined,lineType);        
            dlg.wGp = dlg.add('group');
                dlg.wGp.alignChildren = ['left','top'];
                dlg.wGp.sTxts = dlg.wGp.add('statictext',undefined,'Line Width');
                dlg.wGp.eTxt = dlg.wGp.add('edittext',undefined,Math.round(origLineWidth));
                    dlg.wGp.eTxt.size = [50,12];
                dlg.wGp.sTxte = dlg.wGp.add('statictext',undefined,'px');
                
            if(lineType!='Normal Line'){
                for(var i=0;i<xmlPref.prefs.arrows.children().length();i++){
                    dropLst[i]= xmlPref.prefs.arrows.children()[i].@preset
                    }
                }
            else{
                for(var i=0;i<xmlPref.prefs.lines.children().length();i++){
                    dropLst[i]= xmlPref.prefs.lines.children()[i].@preset
                    }               
                }
            if(lineType!='Normal Line'){
                dlg.aLgp = dlg.add('group');
                    dlg.aLgp.alignChildren = ['left','top'];
                    dlg.aLgp.sTxts = dlg.aLgp.add('statictext',undefined,'Arrow Length');
                    dlg.aLgp.ALen = dlg.aLgp.add('edittext',undefined,Math.round (arrowLength));
                        dlg.aLgp.ALen.size = [50,12];
                    dlg.aLgp.sTxte = dlg.aLgp.add('statictext',undefined,'px');
                    
                dlg.aWgp = dlg.add('group');
                    dlg.aWgp.alignChildren = ['left','top'];
                    dlg.aWgp.sTxts = dlg.aWgp.add('statictext',undefined,'Arrow Width');
                    dlg.aWgp.AWid = dlg.aWgp.add('edittext',undefined,Math.round(arrowWidth));
                        dlg.aWgp.AWid.size = [50,12];
                    dlg.aWgp.sTxte = dlg.aWgp.add('statictext',undefined,'px');     
                    
                dlg.aConGp = dlg.add('group');
                    dlg.aConGp.alignChildren = ['left','top'];
                    dlg.aConGp.sTxts = dlg.aConGp.add('statictext',undefined,'Arrow Concave');
                    dlg.aConGp.ACon = dlg.aConGp.add('edittext',undefined,arrowConcaveFactor);
                        dlg.aConGp.ACon.size = [50,12];
                    dlg.aConGp.sTxte = dlg.aConGp.add('statictext',undefined,'%');                      
                }
            
            dlg.btnGp = dlg.add('group');
            dlg.btnGp.okay = dlg.btnGp.add('button',undefined,'Okay');
            dlg.btnGp.cancel = dlg.btnGp.add('button',undefined,'Cancel');
            
        dlg.prefsPn = dlg.add('panel',undefined,'Preferences');
            dlg.prefsPn.alignChildren = ['left','top'];
            dlg.prefsPn.save = dlg.prefsPn.add('button',undefined,'Save Preference');
            dlg.prefsPn.del = dlg.prefsPn.add('button',undefined,'Delete Preference');
            
            prefsDrop = dlg.prefsPn.add('dropdownlist',undefined,dropLst);
            prefsDrop.title = 'Load Preferences';            
            prefsDrop.size = [300,25];      
            
        prefsDrop.onChange = function(){
            if(lineType!='Normal Line'){
                dlg.wGp.eTxt.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].width
                dlg.aLgp.ALen.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].leng
                dlg.aWgp.AWid.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].aWidth
                dlg.aConGp.ACon.text = xmlPref.prefs.arrows.children()[parseInt(prefsDrop.selection)].concave
                }
            else{
                dlg.wGp.eTxt.text = xmlPref.prefs.lines.children()[parseInt(prefsDrop.selection)].width
                }
            };
            
        dlg.wGp.eTxt.onChange = function(){
            textToNum (1, 1000, dlg.wGp.eTxt, origLineWidth);
            }
        if(lineType!='Normal Line'){        
            dlg.aLgp.ALen.onChange = function(){
                textToNum (1, 10000, dlg.aLgp.ALen, arrowLengthFactor);
                }       
            
            dlg.aWgp.AWid.onChange = function(){
                textToNum (1, 10000, dlg.aWgp.AWid, arrowWidthFactor);
                } 
            
            dlg.aWgp.AWid.onChange = function(){
                textToNum (-50, 50, dlg.aConGp.ACon, arrowConcaveFactor);
                }    
        }//end if
            
            dlg.prefsPn.save.onClick = function(){
                savePrefs ();

                }
            
            dlg.prefsPn.del.onClick = function(){
                if(prefsDrop.selection != null){
                    var selc = parseInt(prefsDrop.selection);                    
                    prefsDrop.remove(selc);
                    if(lineType!='Normal Line'){
                        delete xmlPref.prefs.arrows.children()[selc];
                        }
                    else{
                        delete xmlPref.prefs.lines.children()[selc];
                        }
                    writeXMLFile (xmlFile, xmlPref)
                    }

                }            
            
        dlg.btnGp.okay.onClick = function(){
            dlg.close();
            newWidth = parseInt (dlg.wGp.eTxt.text);
                if(lineType!='Normal Line'){
                arrowLengthFactor = parseInt (dlg.aLgp.ALen.text);
                arrowWidthFactor = parseInt (dlg.aWgp.AWid.text);
                arrowConcaveFactor = parseInt (dlg.aConGp.ACon.text);
                }
            }
        
        dlg.btnGp.cancel.onClick = function(){            
            run = false;
            dlg.close()
            }  
//==================
function savePrefs(){
    var newName = prompt ('Enter New Profile Name', '', 'Save Preferences');
    var prefGood = true;
    for(var i=0;i<prefsDrop.items.length;i++){
        if(prefsDrop.items[i].text == newName){
            newName = prompt ('That preset exists\nPlease choose a unique name','', 'Save Preferences' );
            i=0
            }
        }
        prefsDrop.add('item',newName)
        if(lineType=='Normal Line'){
            xmlPref.prefs.lines.appendChild (XML('<line preset="'+ newName+ '"><width>'+dlg.wGp.eTxt.text+'</width></line>'));
            }
        else{   
            xmlPref.prefs.arrows.appendChild (XML('<arrow preset="'+ newName+ '"><width>'+dlg.wGp.eTxt.text+'</width><leng>'+dlg.aLgp.ALen.text+'</leng><aWidth>'+dlg.aWgp.AWid.text+'</aWidth><concave>'+dlg.aConGp.ACon.text+'</concave></arrow>'));
            }
        writeXMLFile (xmlFile, xmlPref) 

    }

//=====================        
    dlg.show();
    }

function textToNum(sMin,sMax,e,def){
    def=Math.round (def)
	var sHold = def;
			if(isNaN(parseInt(e.text))){
			alert('"' + e.text + '" is not a number\nEnter a value between ' + sMin + '-' + sMax );
			e.text = def};
            else{
                sHold = parseInt(e.text)
			if(sHold < sMin){
				rangeAlert();
				sHold = sMin;				
				};
			if(sHold > sMax){
				rangeAlert();
				sHold = sMax;
				};
			e.text = sHold;
            }
	function rangeAlert(){alert('Number range must be between ' + sMin + '-' + sMax)}; 
};//end function textToNum

function getConcaveFactor(x1,y1,x2,y2, x3, y3, x4, y4, x5, y5){//1 & 2 =  shaft pt 1 &2; 3 & 4 = arrow length line; 5 = tail point opp side
    var ptAH = getIntersect (x1, y1, x2, y2, x3, y3, x4, y4);//intersection of shaft with sides of arrowhead
    //mkDot (ptAH)
    var ptTail = getIntersect (x1, y1, x2, y2, x4, y4, x5, y5);//Intersection of arrow tip ends cross shaft
    var conTotalLen = lineL (x1, y1, ptAH[0], ptAH[1]);//gets total length to see if the concave goes in toward the arrowhead or out (-)
    var conFullLen =  lineL (ptTail[0], ptTail[1], ptAH[0], ptAH[1]);//length of arrow from end tips to intersection with shaft
    var conF = lineL (x1, y1, ptTail[0], ptTail[1])/conFullLen
    if(conTotalLen>conFullLen){conF*=-1}
    return Math.round(conF*100)
    }

function getIntersect(x1,y1,x2,y2, x3, y3, x4, y4){
    var slope1 = (y1-y2)/(x1-x2);
    var bIntersect1 = y1-(slope1*x1)
    var slope2 = (y3-y4)/(x3-x4);
    var bIntersect2 = y3-(slope2*x3)  
    var xNew ;
    var yNew;
    if(bIntersect1=='-Infinity'||bIntersect1=='Infinity'){
        xNew=x1;
        yNew = slope2*xNew + bIntersect2;
        }
    else if(bIntersect2=='-Infinity'||bIntersect2=='Infinity'){
        xNew = x3;
        yNew = slope1*xNew + bIntersect1;
        }
    else{
        xNew= (-(bIntersect1-bIntersect2))/(slope1-slope2);
        yNew = slope1*xNew + bIntersect1
        }
    
    
    return [xNew,yNew]
    }

function recordAnchors(pathObj){
    ptArray = new Array();
    for(var i=0;i<pathObj.subPathItems[0].pathPoints.length;i++){
        ptNewArray [i] = ptArray[i] = pathObj.subPathItems[0].pathPoints[i].anchor;
        }//end loop
    }//end function

function mkNewPathInfo(){
    var pathArray = new Array();
    var piArray = new Array();
    for(var i=0;i<ptNewArray.length;i++){
         piArray[i] = new PathPointInfo;
         piArray[i].kind = cPath.subPathItems[0].pathPoints[i].kind; 
         piArray[i].anchor = ptNewArray[i];
         piArray[i].leftDirection = ptNewArray[i];
         piArray[i].rightDirection = ptNewArray[i];
        }//end loop
    pathArray[0] = new SubPathInfo();
    pathArray[0].operation = cPath.subPathItems[0].operation;
    pathArray[0].closed = cPath.subPathItems[0].closed;
    pathArray[0].entireSubPath = piArray;  
    return pathArray;
    };//end function

/////////////////////
    function extractSubPathInfo(pathObj,oldPoint,newPoint){
        var pathArray = new Array();
        var pl = pathObj.subPathItems.length;
        for(var s=0;s<pl;s++){
            var pArray = new Array();
              for(var i=0;i<pathObj.subPathItems[s].pathPoints.length;i++){
                 pArray[i] = new PathPointInfo;
                 pArray[i].kind = pathObj.subPathItems[s].pathPoints[i].kind;
             if(pathObj.subPathItems[s].pathPoints[i].anchor[0]==oldPoint[0] &&
                   pathObj.subPathItems[s].pathPoints[i].anchor[1]==oldPoint[1]){
                pArray[i].anchor = newPoint;
                pArray[i].leftDirection = newPoint;
                pArray[i].rightDirection = newPoint;
             }else{
                pArray[i].anchor = pathObj.subPathItems[s].pathPoints[i].anchor;
                pArray[i].leftDirection = pathObj.subPathItems[s].pathPoints[i].leftDirection;
                pArray[i].rightDirection = pathObj.subPathItems[s].pathPoints[i].rightDirection;
             }
              };
            pathArray[pathArray.length] = new Array();
            pathArray[pathArray.length - 1] = new SubPathInfo();
            pathArray[pathArray.length - 1].operation = pathObj.subPathItems[s].operation;
            pathArray[pathArray.length - 1].closed = pathObj.subPathItems[s].closed;
            pathArray[pathArray.length - 1].entireSubPath = pArray;
        };
        return pathArray;
    };
        
    function deltPath(){
        var idDlt = charIDToTypeID( "Dlt " );
        var desc2 = new ActionDescriptor();
        var idnull = charIDToTypeID( "null" );
            var ref1 = new ActionReference();
            idPath = charIDToTypeID( "Path" );
            var idvectorMask = stringIDToTypeID( "vectorMask" );
            ref1.putEnumerated( idPath, idPath, idvectorMask );
            var idLyr = charIDToTypeID( "Lyr " );
            var idOrdn = charIDToTypeID( "Ordn" );
            var idTrgt = charIDToTypeID( "Trgt" );
            ref1.putEnumerated( idLyr, idOrdn, idTrgt );
        desc2.putReference( idnull, ref1 );
        executeAction( idDlt, desc2, DialogModes.NO );
        }
    
    function selPath(){
         var idslct = charIDToTypeID( "slct" );
            var desc2 = new ActionDescriptor();
            var idnull = charIDToTypeID( "null" );
                var ref1 = new ActionReference();
                var idPath = charIDToTypeID( "Path" );
                ref1.putName( idPath, "temp" );
            desc2.putReference( idnull, ref1 );
        executeAction( idslct, desc2, DialogModes.NO );       
        }
    
    function mkPath(){
         var idMk = charIDToTypeID( "Mk  " );
            var desc10 = new ActionDescriptor();
            var idnull = charIDToTypeID( "null" );
                var ref3 = new ActionReference();
                var idPath = charIDToTypeID( "Path" );
                ref3.putClass( idPath );
            desc10.putReference( idnull, ref3 );
            var idAt = charIDToTypeID( "At  " );
                var ref4 = new ActionReference();
                var idPath = charIDToTypeID( "Path" );
                var idPath = charIDToTypeID( "Path" );
                var idvectorMask = stringIDToTypeID( "vectorMask" );
                ref4.putEnumerated( idPath, idPath, idvectorMask );
            desc10.putReference( idAt, ref4 );
            var idUsng = charIDToTypeID( "Usng" );
                var ref5 = new ActionReference();
                var idPath = charIDToTypeID( "Path" );
                var idOrdn = charIDToTypeID( "Ordn" );
                var idTrgt = charIDToTypeID( "Trgt" );
                ref5.putEnumerated( idPath, idOrdn, idTrgt );
            desc10.putReference( idUsng, ref5 );
        executeAction( idMk, desc10, DialogModes.NO );       
        }
    
function lineL (ax,ay,bx,by){
    var x = Math.abs (ax-bx);
    var y = Math.abs (ay-by);
    var len = Math.sqrt (Math.pow (x, 2) + Math.pow (y, 2));
    return len
    }

function getAng(ax,ay,bx,by){
    var dx = ax-bx;
    var dy = ay-by;
    var theta = Math.atan2 (dy, dx);
    //theta *= 180/Math.PI
    return theta;
    }

function newPt (x1,y1,rad,ang){
    var newEnd = new Array();
    newEnd[0] = x1 + rad * Math.cos (ang);
    newEnd[1] = y1 + rad * Math.sin (ang);
    return newEnd;
    }

//===============READ/WRITE functions========================================
//=========================================================================
 function readXMLFile(file) {
	if (!file.exists) {
		alert( "Cannot find file: " + deodeURI(file.absoluteURI));
		}
	else{
		file.encoding = "UTF8";
		file.lineFeed = "unix";
		file.open("r", "TEXT", "????");
		var str = file.read();
		file.close();

		return new XML(str);
		};
};

function writeXMLFile(file, xml) {
	if (!(xml instanceof XML)) {
		alert( "Bad XML parameter");
		};
	else{
		file.encoding = "UTF8";
		file.open("w", "TEXT", "????");
		//unicode signature, this is UTF16 but will convert to UTF8 "EF BB BF"
		file.write("\uFEFF");
		file.lineFeed = "unix";
		file.write(xml.toXMLString());
		file.close();
		};
	};
 //=========================================================================
 
    

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

Nice one Chuck.  That's a welcome fix for an annoying limitation with Photoshop. 

Something that also annoys me is that the arrow size appears to need setting manually according to the line weight.  I am sure that was not always the case, and that arrow head would scale with the line width.  I have tried using both % and pc after the value, but the resulting error message says it will only accept a value in pixels.  Has that changed, or am I remembering it wrong?

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

It's changed. It used to be a percentage, which caused issues with consistency, but I'm not sure the pixel method is any better.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

Thanks for the heads up Chuck. At least I now know to stop trying to outfox the settings.  An OK rule of thumb seems to be to use no stroke and set the line weight in pixels, and the arrow head width at 200% of the line weight, and length at 400% of the line weight.  But YMMV.

 

Thanks again for the script.  I used to love your Equal Spacing extension before they built it into the Move > Align tool.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Oct 05, 2022 Oct 05, 2022

Copy link to clipboard

Copied

LATEST

Yea, the new align is much faster, but boy, I sure needed that script that I wrote for a lot of artwork that I used to do.

Likes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines